我有一个驱动程序代码,其处理程序函数和线程函数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 操作需要相当长的时间吗?
我是否需要在"处理程序 fn"原子中进行位操作?
我是否应该将执行的操作移动到"启用设备中断"从"线程 fn"到"处理程序 fn"(这将花费我 4 个 i2c 操作和一个位操作)? - 原因是根据上面的代码实现,我可能会错过中断。
如果我这样做(根据问题 3)。 它如何影响其他设备中断。因为我有一个基本的疑问,硬IRQ上下文中的"处理程序fn"是否在禁用中断的情况下运行)
请为我提供上述情况的良好和最佳解决方案。
提前谢谢。
I2C 读/写传输不是确定性的。
该协议允许外设从机IC执行时钟拉伸,从而允许它们"保持"主机,直到它们准备就绪。但是,这不是常见的情况,因此大多数情况下,每个I2C传输通常都在预定的时间间隔内完成。但是,这不是保证,因此在ISR中执行多个I2C传输不是一个好主意。
此链接包含有关线程 irqs 的基础知识及其正确用法的良好解释。
上述场景的最佳设计?
使用线程中断处理程序方法不会有很多好处,因为尝试启用/禁用设备上的中断会增加延迟。
在当前方案中(来自单个设备的单个中断),可以坚持使用常规request_irq()
来注册中断服务例程 (ISR)。
ISR 代码 :
1. 在 ISR 中,呼叫disable_irq()
以防止进一步中断。
2. 安排一个下半部分处理程序函数(工作队列是一个不错的选择)。
3. 从 ISR 返回IRQ_HANDLED
。
下半部分处理程序代码:
4. 执行 I2C 传输。
5. 拨打enable_irq()
并退出。
注 :
实现相同设计的另一种方法是使用不带 ISR 的线程 irq。这实现了与上述设计相同的目标,并且无需在代码中单独定义/初始化/清理下半部分处理程序。
在这种方法中,将所有I2C读/写代码放在IRQ线程函数中,并将其与handler = NULL
一起传递给request_threaded_irq()
,即空的ISR。