字符设备驱动程序之中断方式的按键驱动_Linux中断处理结构
解析asm_do_IRQ,了解中断处理,怎么进行的。
单片机下的中断处理:
1、分辨是哪一个中断
2、调用处理函数
3、清中断
Linux内核:
asm_do_IRQ(C函数入口)最终 调用到 事先初始化的handle_irq函数。
以上单片机的三项,是用asm_do_IRQ函数来实现的。
1、参数irq:中断号。
2、irq_desc:是一个数组。
irq_desc[NR_IRQS]:中断描述数组,以中断号NR_IRQS为下标。
3、desc_handle_irq(irq, desc)进入处理
desc就是irq_desc[irq]。irq_desc全局数组,以irq中断号为下标的数组项。
分辨是哪一个中断;调用处理函数;清中断,这三项内容就是在handle_irq里实现的。
4、irq_desc:
hadle_irq,chip。
5、初始化:s3c24xxx_init_irq函数:
所以:
外部中断0:IRQ_EINT0=16,irq=16,找到数组项,然后进行赋值。
数组irq_desc[EINT0~EINT3]
{
handle_irq = handle_edge_irq;
chip = s3c_irq_eint0t0t4;
}
数组irq_desc[EINT4~EINT23]
{
handle_irq = handle_edge_irq;
chip = s3c_irqext_chip;
}
6、处理边缘出发中断 handle_edge_irq函数:
(1) desc->chip->ack(irq):清中断
(2) hadle_irq_event:处理中断(取出action链表中的成员,执行action->handle(处理函数))
action是一个链表,action=action->next,ret=action->handler,取出链表的各种成员,然后调用它们的hadler函数
总结:
发生中断之后,按下按键:
中断的框架:
1、CPU自动进入异常模式
b vector_irq + stubs_offset (vector_irq是一个宏来定义的)
2、然后调用到 __irq_usr
3、最终调用到 b asm_do_IRQ
4、irq_desc[irq]->handler_irq (以中断号为下标,取出一项handler_irq)
5、handler_irq = handler_edge_irq (处理边缘中断函数)
(1) desc->chip->ack(irq):清中断
(2) hadle_irq_event:处理中断(取出action链表中的成员,一 一执行action->handle(处理函数))
6、irq_desc 结构体:
(1)函数指针 handle_irq 指向 handle_edge_irq。
(2)action 中断动作链表,链表头,
链表结构体:irqaction(用户注册的中断处理函数)
handler:处理函数
(3)芯片相关的底层处理函数 chip 指向 s3c_irq_eint0t4 、s3c_irqext_chip。
startup、shutdown 启动 关闭这个中断。ennable、disable 使能、禁止中断。ack 响应中断(清中断)。
linux内核中断体系架构:
执行我们自己的中断处理函数:
action->handler
就是在链表里面,把irqaction结构填进去。
告诉内核处理函数是什么!!
request_irq():
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)
irq:中断号
handler:处理函数
irqflags:上升沿触发、下降沿触发、边沿触发
devname:中断的名字
devid:
request_irq函数:
(1)、分配一个irqaction结构,结构里面的成员都指向参数
(2)、设置中断,setup_irq(irq,action)
a.在irq_desc[irq]->action链表,加入刚传进来的action
b.desc->chip->settype(),把对应的引脚设置为中断引脚
c.desc->chip->startup / enable,使能中断
不想使用中断:
free_irq(irq,dev_id)
总结这两个函数:
注册中断服务程序
request_irq(irq, handler, flags, name, dev_id)
分配一个irqaction结构,指向参数;
把这个结构放入irq_desc[irq]数组项 的 action链表里;
设置引脚,使能中断
释放
free_irq(irq, dev_id)
出链(从链表里拖出来)
禁止中断(什么时候禁止呢? 如果链表里没有irqaction结构成员了,就会关闭中断。如果原来有两个,free掉一个,就不会禁止中断)