Linux驱动笔记(二):中断相关知识

1、中断申请和释放

申请函数:int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev)

成功返回 0

参数含义

irq 中断号
handler 中断处理函数
flags 中断标志  
 
 
name 中断名字,设置以后可以在/proc/interrupts 文件中看到对应的中断名字
 
dev  如果将 flags 设置为 IRQF_SHARED 的话, dev 用来区分不同的中断,一般情况下将
dev 设置为设备结构体, dev 会传递给中断处理函数 irq_handler_t 的第二个参数
 
   

释放:void free_irq(unsigned int irq, void  *dev);


 

中断处理函数格式:irqreturn_t (*irq_handler_t) (int, void *)

第一个参数是要中断处理函数要相应的中断号。第二个参数是一个指向 void 的指针,也就
是个通用指针,需要与 request_irq 函数的 dev 参数保持一致。用于区分共享中断的不同设备,
dev 也可以指向设备数据结构。中断处理函数的返回值为 irqreturn_t 类型,例子:

static irqreturn_t rtc_interrupt(int irq, void *dev_id)

**当前CPU中断:

local_irq_enable();
禁止当前CPU中断:

local_irq_disable();
**指定中断线:

void enable_irq(unsigned int irq);
禁止指定中断线:

void disable_irq(unsigned int irq);
禁止指定中断线:

void disable_irq_nosync(unsigned int irq);
注:此函数调用irq_chip中disable禁止指定中断线,所以不会保证中断线上执行的中断服务程序已经退出。
 

2、中断上下半部

Linux驱动笔记(二):中断相关知识

这里重点关注:Tasklet

2.1下半部定义和初始化

DECLARE_TASKLET(name, func, data)
其中 name 为要定义的 tasklet 名字,这个名字就是一个 tasklet_struct 类型的时候变量, func
就是 tasklet 的处理函数, data 是传递给 func 函数的参数。

2.2下半部函数调用

在上半部,也就是中断处理函数中调用 tasklet_schedule 函数就能使 tasklet 在合适的时间运
行, tasklet_schedule 函数原型如下:
void tasklet_schedule(struct tasklet_struct *t)
函数参数和返回值含义如下:
t:要调度的 tasklet,也就是 DECLARE_TASKLET 宏里面的 name。

 

 

3、设备树里的中断信息
 

3.1实例分析:I.MX6ULL 的中断控制器节点,节点内容如下所示

1 intc: [email protected] {
2 compatible = "arm,cortex-a7-gic";
3 #interrupt-cells = <3>;
4 interrupt-controller;

5 reg = <0x00a01000 0x1000>,
6 <0x00a02000 0x100>;
7 };
 

第 2 行, compatible 属性值为“arm,cortex-a7-gic”在 Linux 内核源码中搜索“arm,cortex-a7-
gic”即可找到 GIC 中断控制器驱动文件。
第 3 行, #interrupt-cells 和#address-cells、 #size-cells 一样。表示此中断控制器下设备的 cells
大小,对于设备而言,会使用 interrupts 属性描述中断信息, #interrupt-cells 描述了 interrupts 属性的 cells 大小,也就是一条信息有几个 cells。每个 cells 都是 32 位整形值,对于 ARM 处理的
GIC 来说,一共有 3 个 cells,这三个 cells 的含义如下:
第一个 cells:中断类型, 0 表示 SPI 中断, 1 表示 PPI 中断。
第二个 cells:中断号,对于 SPI 中断来说中断号的范围为 0~987,对于 PPI 中断来说中断
号的范围为 0~15。
第三个 cells:标志, bit[3:0]表示中断触发类型,为 1 的时候表示上升沿触发,为 2 的时候
表示下降沿触发,为 4 的时候表示高电平触发,为 8 的时候表示低电平触发。 bit[15:8]为 PPI 中
断的 CPU 掩码。

第 4 行, interrupt-controller 节点为空,表示当前节点是中断控制器
3.2实例分析:I.MX6ULL 的中断控制器节点,节点内容如下所示

1 gpio5: [email protected] {
2 compatible = "fsl,imx6ul-gpio", "fsl,imx35-gpio";
3 reg = <0x020ac000 0x4000>;
4 interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
5 <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
6 gpio-controller;
7 #gpio-cells = <2>;
8 interrupt-controller;
9 #interrupt-cells = <2>;
10 };第 4 行, interrupts 描述中断源信息,对于 gpio5 来说一共有两条信息,中断类型都是 SPI,
触发电平都是 IRQ_TYPE_LEVEL_HIGH。不同之处在于中断源,一个是 74,一个是 75,打开
可以打开《IMX6ULL 参考手册》的“Chapter 3 Interrupts and DMA Events”章节,找到表 3-1,
有如图 50.1.3.1 所示的内容:

 

 

图 50.1.3.1 中断表
从图 50.1.3.1 可以看出, GPIO5 一共用了 2 个中断号,一个是 74,一个是 75。其中 74 对
应 GPIO5_IO00~GPIO5_IO15 这低 16 个 IO, 75 对应 GPIO5_IO16~GPIOI5_IO31 这高 16 位 IO。
第 8 行, interrupt-controller 表明了 gpio5 节点也是个中断控制器,用于控制 gpio5 所有 IO
的中断。