request_threaded_irq的"处理函数"中的I2c读取和写入操作如何影响整个驱动程序.

kzs*_*kzs 3 interrupt irq linux-device-driver linux-kernel

我有一个带处理函数的驱动程序代码和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;
}
Run Code Online (Sandbox Code Playgroud)

关于上述实施,我几乎没有问题.

  1. "处理程序fn"中的2 i2c操作是否需要相当长的时间.

  2. 我是否需要在"handler fn"atomic中进行位操作?

  3. 我应该将执行操作直到"启用设备中断"从"线程fn"移动到"处理程序fn"(这将花费我多4次i2c操作和一位操作完全)? - 根据上面的代码实现,我有可能错过中断的原因.

  4. 如果我这样做(根据问题3).它如何影响其他设备中断.(因为我基本怀疑硬IRQ上下文中的"处理程序fn"是否在禁用中断的情况下运行)

请为我提供一个针对上述场景的良好和最佳解决方案.

提前致谢.

The*_*ist 5

I2C读/写传输不是确定性的.

该协议允许外围从设备IC执行时钟延长,从而允许它们"保持"主设备,直到它们准备就绪.然而,这不是常见的情况,因此每次I2C传输通常在大多数时间以预定间隔完成.但是,这不是保证,因此在ISR中执行多个I2C传输并不是一个好主意.

链接包含有关线程irq的基本原理及其正确用法的很好的解释.


针对上述场景的优化设计?

使用线程中断处理程序方法不会有很多好处,因为尝试启用/禁用设备上的中断会增加延迟.

在您当前的场景中(来自单个设备的单个中断),可以坚持常规request_irq()注册中断服务例程(ISR).

ISR代码:
1.在ISR中,调用disable_irq()以防止进一步中断.
2.安排下半部处理函数(workqueue是一个不错的选择).
3. IRQ_HANDLED从ISR 返回.

下半部处理程序代码:
4.执行I2C传输.
5.致电enable_irq()并退出.


注意:
实现相同设计的另一种方法是使用没有ISR线程irq.这实现了与上述设计相同的功能,并且无需在代码中单独定义/初始化/清理下半部分处理程序.

这种方法中,可以将所有I2C读/写代码放在IRQ线程函数中并将其传递给它request_threaded_irq(),handler = NULL即空ISR.