日期:2014-05-16 浏览次数:20922 次
Linux中断的沿触发和电平触发
初始化中断向量表时,有一个重要的操作就是set_irq_handler。这个函数参数一般为handle_edge_irq或者handle_level_irq。对于边缘中断,使用handle_edge_irq作参数;对于电平中断,使用handle_level_irq作为中断。那这两个函数有什么区别呢?
1. handle_edge_irq
kernel源代码中的注释为:
c代码
/**
* handle_edge_irq - edge type IRQ handler
* @irq: the interrupt number
* @desc: the interrupt description structure for this irq
*
* Interrupt occures on the falling and/or rising edge of a hardware
* signal. The occurence is latched into the irq controller hardware
* and must be acked in order to be reenabled. After the ack another
* interrupt can happen on the same source even before the first one
* is handled by the assosiacted event handler. If this happens it
* might be necessary to disable (mask) the interrupt depending on the
* controller hardware. This requires to reenable the interrupt inside
* of the loop which handles the interrupts which have arrived while
* the handler was running. If all pending interrupts are handled, the
* loop is left.
*/
下面翻译为中文:
中断发生在硬件信号的上升沿/下降沿。中断事件保存在中断控制器中并且必须被立刻响应以重新打开中断。响应之后,即使第一个中断还没有被相关的中断函数处理完,另一个中断也可能在同一个中断源发生。如果这种情况发生的话就有必要关闭中断。这样,在中断处理函数运行时发生的中断就会被标记为阻塞,在中断处理循环处理完这些阻塞的中断之后,就有必要在循环内部重新打开中断。如果全部的阻塞中断处理完毕,就可以离开中断处理循环。
2. handle_level_irq
c代码
/**
* handle_level_irq - Level type irq handler
* @irq: the interrupt number
* @desc: the interrupt description structure for this irq
*
* Level type interrupts are active as long as the hardware line has
* the active level. This may require to mask the interrupt and unmask
* it after the associated handler has acknowledged the device, so the
* interrupt line is back to inactive.
*/
一旦硬件线路达到了激活电平,电平类型的中断就会被触发。这可能需要屏蔽中断,并且在相关的中断处理程序响应了设备之后重新打开中断,这样中断线才能恢复反激活状态。
对比上述两个函数可见,对于电平中断,一进入中断处理程序就会立刻屏蔽中断,直到退出中断的时候才会unmask中断;而对于边缘中断,除非在处理当前中断时有一个新的中断被触发否则不会屏蔽中断。这两个处理函数的特点刚好和这两种中断的特点一致:对于电平中断,只要中断脚在激活电平电平,就会不断地触发中断;而边缘中断只在上升沿或者下降沿被触发。
下面是linux 2.6.32版本kernel的代码。
//觉得很奇怪,既然电平中断一开始就mask了中断,
//退出的时候才unmask,怎么会与同类型的其他中断冲突呢?
c代码