一、中断是什么

中断是指CPU在执行程序的过程中,出现了某些突发事件急需处理,CPU暂停当前程序的执行,转去处理突发事件,处理完后又返回原程序被中断的地方继续执行。

中断分为两种:

(1)中断,又叫外部中断或异步中断,它的产生是由于外设向处理器发出中断请求。外部中断有两种,由配置寄存器设定:普通中断请求(IRQ)和快速中断请求(FIQ)。

(2)异常,又叫内部中断或同步中断,它的产生是由于处理器执行指令出错。

二、中断请求线

中断请求线,又叫中断号,每个中断都会通过一个唯一的数值来标识,这个值称为中断请求线。

三、中断处理函数

当响应一个中断时,内核会执行该信号对应的一个函数,该函数就叫做该中断对应的中断处理函数。一般来说,中断的优先级是最高的,一旦接收到中断,内核就会调用对应的中断处理函数。

四、注册和释放中断

(1)注册中断处理函数:

int request_irq(unsigned int irq, irq_handler_t handler,

unsigned long irqflags, const char *devname, void *dev_id)

irq:指定要分配的中断号

handler:中断处理函数指针

irqflags :中断处理标志

devname:该字符串将显示在/proc/irq/proc/interrupt

dev_id ID

返回值:成功返回0,失败返回非0;该函数会睡眠,必须判断返回值。

(2)中断处理标识iraflags

#define IRQF_TRIGGER_NONE   0x00000000

#define IRQF_TRIGGER_RISING 0x00000001 //上升沿触发中断

#define IRQF_TRIGGER_FALLING    0x00000002 //下降沿触发中断

#define IRQF_TRIGGER_HIGH   0x00000004 //高电平触发中断

#define IRQF_TRIGGER_LOW    0x00000008 //低电平触发中断                                                               

#define IRQF_TRIGGER_MASK   (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW | \

                 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)

#define IRQF_TRIGGER_PROBE  0x00000010

 

(3)释放中断

void free_irq(unsigned int irq, void *dev_id)

(4)中断处理函数

中断处理函数声明:

static irqreturn_t intr_handler(int irq, void *dev_id)

返回值:中断处理函数正确调用会返回IRQ_HANDLED

 

五、共享中断号

调用request_irq(),是中断号与中断处理函数对应,有时候会有这样的情况,中断已经被另外的驱动程序注册中断了,而现在又想再注册一次这个中断,这就出现了一个中断号不止对应一个中断处理函数的情况。这里与硬件上的共享中断不一样,这里是指,当一个中断信号来了,基于操作系统,一个中断的到来可以调用多个中断处理程序,与硬件无关。

前面介绍了函数接口request_irq()的参数irqflags,处理IRQ_TIRGGER_FALLING这类指明中断触发的条件的标志外,下面还介绍三个:

SA_INTERRUPT:这个标志表明该中断处理程序是一个快速中断处理程序。过去,Linux系统会区分快速和慢速中断,但现在这个标志只有这样的效果:当响应这个中断时,禁止所有的中断,使该中断处理函数不会被其他中断打断,迅速执行。

SA_SAMPLE_RANDOM:这个标志表明产生的中断会对内核的entroy pool有贡献。Entroy pool负责产生随机数。

SA_SHIRQ:这个标志表明多个中断处理程序可以共享一个中断号。

相对于其他两个,SA_SHIQR是常用的标记。中断注册失败,原因是没有共享标记。

 

ARMSA_SHIRQ相当于标志IRQF_SHARED

#define IRQF_DISABLED 0x00000020  //SA_INTERRUPT 

#define IRQF_SAMPLE_RANDOM 0x00000040  //SA_SAMPLE_RANDOM

#define IRQF_SHARED 0x00000080  //SA_SHIRQ 

例如:

ret = request_irq(irq, irq_handler,

IRQF_TRIGGER_FALLING | IRQF_SHARED, "key INT_EINT1", &id);

设备号ID——dev_id

内核通过dev_id对应中断处理函数handler,另外,也可以通过它来传参给中断处理函数。

 

六、总结

(1)调用request_irq必须通过返回值判断是否成功。

(2)共享中断号时,所有共享这个中断号的request_irq都必须添加标记IRQF_SHARED,另外用一个独特的设备号dev_id,让内核能够通过dev_id对应注册时的中断处理函数。

Logo

更多推荐