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

时间:2013-09-20 16:50:56

标签: linux-kernel linux-device-driver interrupt irq

我有一个带处理函数的驱动程序代码和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;
}

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

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

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

  3. 我应该将“启用设备中断”之前执行的操作从“thread fn”移动到“handler fn”(这会花费我多4次i2c操作和一位操作吗?) - 根据上述代码实现,我可能会错过中断的原因。

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

  5. 请为我提供适合上述情况的最佳解决方案。

    提前致谢。

1 个答案:

答案 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。