Linux中断的实现(一)
一、中断是什么中断是指CPU在执行程序的过程中,出现了某些突发事件急需处理,CPU暂停当前程序的执行,转去处理突发事件,处理完后又返回原程序被中断的地方继续执行。中断分为两种:(1)中断,又叫外部中断或异步中断,它的产生是由于外设向处理器发出中断请求。外部中断有两种,由配置寄存器设定:普通中断请求(IRQ)和快速中断请求(FIQ)。(2)异常,又叫内部中断或同步中断,它的产生是由于处理器执行指令出
一、中断是什么
中断是指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是常用的标记。中断注册失败,原因是没有共享标记。
在ARM下SA_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对应注册时的中断处理函数。
更多推荐
所有评论(0)