我有一个带处理函数的驱动程序代码和request_threaded_irq的线程函数,类似于:
irq-handler fn()
{
/*disable device interrupt*/
i2c read from register;
set disable bit to client-device-interrupt
i2c write back;
return IRQ_WAKe_THREAD;
}
irq-thread fn()
{
i2c read from register;
....
....
/*enable device interrupt*/
i2c read from register;
set enable bit to client-device-interrupt
i2c write back;
/*Rest of the operation*/
..........
..........
return IRQ_HANDLED;
}
关于上述实施,我几乎没有问题。
“处理程序fn”中的2 i2c操作是否需要相当长的时间。?
我是否需要在“handler fn”atomic中进行位操作?
我应该将“启用设备中断”之前执行的操作从“thread fn”移动到“handler fn”(这会花费我多4次i2c操作和一位操作吗?) - 根据上述代码实现,我可能会错过中断的原因。
如果我这样做(根据问题3)。它是如何影响其他设备中断的。(因为我基本怀疑硬IRQ上下文中的“处理程序fn”是否在禁用中断的情况下运行)
请为我提供适合上述情况的最佳解决方案。
提前致谢。
答案 0 :(得分:5)
I2C读/写传输不是确定性的。
该协议允许外围从设备IC执行clock stretching,从而允许它们“保持”主设备,直到它们准备就绪。 然而,这不是常见的情况,因此每次I2C传输通常在大多数时间以预定间隔完成。但是,这不是保证,因此在ISR中执行多个I2C传输并不是一个好主意。
这个link包含了关于线程irq的基本原理及其正确用法的一个很好的解释。
使用线程中断处理程序方法不会有很多好处,因为尝试启用/禁用设备上的中断会增加延迟。
在您当前的场景中(来自单个设备的单个中断),可以坚持使用常规request_irq()
来注册中断服务例程(ISR)。
ISR 代码:
1.在ISR中,呼叫disable_irq()
以防止进一步中断
2.安排下半部处理程序功能(工作队列是一个不错的选择)
3.从ISR返回IRQ_HANDLED
。
下半部处理程序代码:
4.执行I2C传输
5.拨打enable_irq()
并退出。
注意:
实现相同设计的另一种方法是使用 threaded-irq而不使用ISR 。这与上面的设计相同,并且无需在代码中单独定义/初始化/清理下半部分处理程序。
在this approach one中,将所有I2C读/写代码放在 IRQ thread function 中,并将其与request_threaded_irq()
一起传递给handler = NULL
,即一个空的ISR。