/*
* 设备树的中断属性
*/
interrupt-controller /* 中断控制器 */
#interrupt-cells /* 表明引用这个中断控制器的话需要多少个 cell */
#interrupt-cells=<1> /* 其它节点要使用这个中断控制器时,只需要一个 cell 来表明使用"哪一个中断" */
#interrupt-cells=<2> /* 其它节点要使用这个中断控制器时,第一个 cell 来表明使用"哪一个中断" */
/* 另一个 cell 来描述中断,一般是表明触发类型. bits[3] = 0,1,2,4,8 */
interrupt-parent = <&gpio2>;
interrupts = <30 0>;
中断控制器是GPIO2,使用它的30号中断。(30是指30号引脚),0是指触发的方式(上升沿、下降沿等)。
interrupts = <0 38 1>;
interrupts = <GIC_SPI 38 1>;
interrupts = <GIC_PPI 18 1>;
#define GIC_SPI 0
#define GIC_PPI 1
IPI:inter-processer interrupt 中断号 0 ~ 15
PPI:per processor interrupts 中断号 16 ~ 31
SPI:shared processor interrupts 中断号 32 ~ 32+224
SGI:software generated interrupts (SGI).
第一个参数表示是 IPI、PPI、SPI、SGI 其中的一个
第二个参数表示:是第一个参数里面的第几个
第三个参数表示:中断触发的类型。(上升沿、下降沿等)
interrupts = <GIC_SPI 68 1>;
表示中断类型为共享处理器中断(SPI),
中断号为SPI中断类型中的第68号中断号,计算出来的实际中断号即为32+68=100号中断,
1表示上升沿触发中断。
中断类型的值:
#define IRQ_TYPE_NONE 0 /* 内核不改变它,开机或uboot设置它是什么样就什么样 */
#define IRQ_TYPE_EDGE_RISING 1 /* 上升沿触发 */
#define IRQ_TYPE_EDGE_FALLING 2 /* 下降沿触发 */
#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) /* 双边沿触发 */
#define IRQ_TYPE_LEVEL_HIGH 4 /* 电平触发-高电平 */
#define IRQ_TYPE_LEVEL_LOW 8 /* 电平触发-低电平 */
一个"interrupts-extended"属性就可以既指定"interrupt-parent",也指定"interrupts"
interrupts-extended = <&intc1 5 1>, <&intc2 1 0>;
/* 相关源文件 */
drivers/irqchip/irq-gic.c
/* 申请中断,绑定中断处理函数 */
static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler,
unsigned long flags, const char name, void *dev)
irq : 用于指定"内核中断号",这个参数我们会从设备树中获取或转换得到
handler: 中断处理函数, irqreturn_t (*irq_handler_t)(int irq, void * dev);
flags: 设置中断触发方式,该设置会覆盖设备树里面配置的中断触发方式
name: 中断的名字,中断申请成功后会在"/proc/interrupts"目录下看到对应的文件
dev: :如果使用了 IRQF_SHARED 宏,则开启了共享中断。"共享中断"指的是多个驱动程序共用同一个中断。
开启了共享中断之后,中断发生后内核会依次调用这些驱动的"中断服务函数"。
这就需要在中断服务函数里判断中断是否来自本驱动,这里就可以用 dev 参数做中断判断。
即使不用 dev 参数判断中断来自哪个驱动,在申请中断时也要加上 dev 参数因为在注销驱动时内核会根据 dev
参数决定删除哪个中断服务函数
/* 中断注销函数 */
void free_irq(unsigned int irq, void *dev)
/* 通过gpio编号获得中断号 */
int gpio_to_irq(unsigned int gpio)
/* 中断使能和禁用 */
/* 控制某个中断 */
void enable_irq(unsigned int irq)
void disable_irq(unsigned int irq)
/* 控制全局中断 */
local_irq_enable()
local_irq_disable()
local_irq_save(flags) // 保存当前中断状态,并关闭中断
local_irq_restore(flags) // 恢复中断,将中断恢复到flags状态
/* 从设备树里解析出中断号 */
of_irq_get(dev->of_node, 0)
i2c : i2c_device_probe() ---> of_irq_get (drivers/i2c/i2c-core.c)
spi : spi_drv_probe() ---> of_irq_get (drivers/spi/spi.c)
/* 获得 GPIO 中断号 */
gpio_to_irq()
gpiod_to_irq()
/* 获得引脚和 flag */
gpio_to_desc()
of_get_gpio_flags()
/* GPC INTC (General Power Controller, Interrupt Controller) */
通用电源控制器、中断控制器,提供中断屏蔽、中断状态查询、唤醒功能