以Linux2.6.32 arm内核为例:
注册:
一般要使用中断,会在初始化函数或probe函数里调用request_irq申请中断, 如果是共享中断(两个IO共享一个物理中断号),要加上标志IRQF_SHARED调用关系为: request_irq->request_threaded_irq->__setup_irq, 在32的内核里如果你申请的中断是IRQF_SHARED|IRQF_DISABLED的中断就会给你一个警告提示,原因是共享中断的调用在一个中断上下文,如果第一个中断结束了以后又打开了中断,第二个同中断号的handler就会在开中断的情况下运行,这与申请时初衷的IRQF_DISABLED标志相背.所以在共享中断的处理函数里不能调用
local_irq_disable/local_irq_enable.
这里要扯的远一点了,因为Linux是一个在很多平台上都用的操作系统,为了最大的提高兼容性,其中断是允许嵌套的.不过在很多嵌入式的处理器
及其对应的代码里对嵌套中断并没有很好的支持或者说无法从嵌套中断中获得性能上的好处, 但是内核的核心代码又不能修改, 所以说就加上IRQF_DISABLED这个标志来保证中断不被打断.
在中断的处理里会用到两个重要的数据结构
struct irq_desc - interrupt descriptor
struct irqaction - IRQ action list
每一个物理中断对应一个中断描述符的结构, 在其中断描述符结构里有一个中断action指针, 里面指向了对应中断处理所要用的数据结构,比如中断号,
中断函数里要传入的私有数据的指针,处理函数等等.
每调用一次request_irq, 就会填入一个irqaction的内容,如果是共享中断,就会以链表的方式将irqaction链接起来.具体如下:
每个物理中断号对应一个irq_desc, 每个irq_desc里有一个或几个irqaction,一个irqaction对应一个中断源(中断处理函数),如果一个中断号有两个
中断源与其对应,那么就会有两个irqaction与其对应, 每个irqaction结构里有一个struct irqaction *next,指向下一个要处理中断源的处理函数.如果
没有处理函数,则对应next指针为空.
处理:
上面的struct irqaction链表要会在中断处理的时候用到, 函数handle_IRQ_event的do-while循环就是用来处理共享中断的.