和pinctrl和gpio子系统一样,中断也不需要我们去操作具体的寄存器,因为bsp工程师已经帮我们写好了,我们只需要在设备数中添加相应的属性该配置就好了。
1. 中断子系统的基本使用
需要在你的设备树下添加的属性有:
- interrupt-parent = <>, 该属性用于指定父级中断控制器,如:&GPIO1, &GPIO5, …
- interrupts = <>, 该属性的cells有两个,第一个是引脚号,第二个是中断触发方式
#define IRQ_TYPE_NONE 0 // 不触发 #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 // 低电平触发
2. 中断相关函数
2.1 request_irq
该函数用于申请中断,绑定中断处理函数
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); enum irqreturn { IRQ_NONE = (0 << 0), IRQ_HANDLED = (1 << 0), IRQ_WAKE_THREAD = (1 << 1), }; typedef enum irqreturn irqreturn_t;
flags: 设置中断触发方式,该设置会覆盖设备树里面配置的中断触发方式
name: 中断的名字,中断申请成功后会在“/proc/interrupts”目录下看到对应的文件
dev: :如果使用了 IRQF_SHARED 宏,则开启了共享中断。“共享中断”指的是多个驱动程序共用同一个中断。开启了共享中断之后,中断发生后内核会依次调用这些驱动的“中断服务函数”。这就需要我们在中断服务函数里判断中断是否来自本驱动,这里就可以用dev 参数做中断判断。即使不用 dev 参数判断中断来自哪个驱动,在申请中断时也要加上dev 参数因为在注销驱动时内核会根据 dev 参数决定删除哪个中断服务函数
2.2 free_irq
中断注销函数, 其中的dev需要与 request_irq 函数中 dev 传入的参数一致。
void free_irq(unsigned int irq, void *dev);
2.3 中断使能和禁用
// 控制某个中断 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状态
2.4 gpio_to_irq
通过gpio编号获得中断号
int gpio_to_irq(unsigned int gpio)