【Linux驱动】Linux中断(一)—— 设备树中断节点

裸机使用中断需要通过寄存器手动配置,但有了 Linux 系统后,Linux内核提供了完善的中断框架,我们只需要申请中断,然后注册中断服务函数即可。

一、设备树中断属性

既然驱动中要注册中断服务函数,我们首先需要知道三个点:

  • 中断类型: GIC 目前存在的中断请求有128种,每一种对应一个中断控制器
  • 中断引脚: 指定具体是哪一个引脚会触发
  • 触发方式: 上升沿触发、下降沿触发、高电平触发、低电平触发

设备树中涉及到中断的属性主要有四个

1、指定中断类型

在设备树中每一种中断请求表现为一个节点,且包含属性 interrupt-controller。涉及到的属性还有 #interrupt-cells,指定引用节点中 interrupts 属性中包含的信息个数(注意不是当前节点的interrupts属性)

当某个外设节点要引入中断时,需要通过 interrupt-parent 属性描述自己属于哪一种类型的中断,比如下面的 sii902x 节点的中断类型属于 gpio1。gpio1节点的 interrupts 属性已经包含了中断号等内容,后续与 gpio1 相关的子节点直接引用即可。 

2、指定中断引脚、触发方式

中断的触发需要借助引脚的高低电平实现,所以当某个外设节点引入中断后,需要指定是哪个引脚会触发中断,使用的设备树属性为 interrupts,该属性包含两个信息(中断引脚、触发方式)

格式如下:

interrupts = <引脚编号 触发方式>,
             ···
             <引脚编号 触发方式>;

引脚编号:引脚编号可以直接使用数字,如果是 gpio1_IO10,这里可以填 10

触发方式:Linux内核提供了宏定义来表示触发方式(irq.h)

#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    /* 低电平触发 */

二、设备树中断节点

为便于触发中断,这里以按键 key0 为例,key0 使用的引脚为 GPIO1_IO18,引脚编号为 18,触发类型为下降沿触发。

创建的设备树节点如下:

gpio-key0 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_gpio_keys>;            // pinctrl子系统配置电气属性
	key-gpio = <&gpio1 18 GPIO_ACTIVE_HIGH>;     // gpio子系统进行引脚初始化
	interrupt-parent = <&gpio1>;                 // 中断类型为 gpio1
	interrupts = <18 IRQ_TYPE_EDGE_FALLING>;     // 中断引脚为 GPIO1_IO18,触发方式为下降沿
	status = "okay";
};