当前位置: 首页 > 工具软件 > ir-rescue > 使用案例 >

request_threaded_irq及IRQF_ONESHOT的简单研究

寇夜洛
2023-12-01

        最近有对request_threaded_irq以及IRQF_ONESHOT进行了一下研究,

         首先是通过TP驱动的IRQ来做实验,中断为低有效,gpio默认状态为输入高电平,驱动内部代码为:

ret =request_threaded_irq(touchdev->irq,NULL,zinitix_touch_work,IRQF_TRIGGER_FALLING| IRQF_ONESHOT , ZINITIX_DRIVER_NAME ,touch_dev);

         这里先把下降沿出发改成了低电平触发发现烧录之后,正常work

         即request_threaded_irq(touchdev->irq,NULL,zinitix_touch_work,IRQF_TRIGGER_LOW | IRQF_ONESHOT , ZINITIX_DRIVER_NAME,touch_dev);

         思考之后,觉得对于TP的场景,下降沿和低电平应该都是可以的。推测改成上升沿触发之后TP会失效,因为TP的工作原理是拉低触发中断,之后需要中断处理函数的结尾发命令给TP的IC去把中断pin拉回高电平。实验验证:改成上升沿触发后,TP工作失效,触屏无反应

 

         进一步想研究IRQF_ONESHOT的状态。如果根据网上的结论,即one_shot为保证中断在底半部threaded_handler执行完之后才会继续接受中断,那么这个标识理论上在我们TP的工作模式下,如果是下降沿触发应该不需要添加标识。这里对下降沿触发和低电平触发,分别拿掉了IRQF_ONESHOT,发现都无法正常work。通过adb抓取log ,发现原因是irq申请失败,同时失败log为grnirq:Threaded irq requested with handler=NULLand !ONE_SHOT for irq 420.

         requset_thread_irq函数中,如果我们对于顶半部的申请用的是NULL,那么系统会使用默认的顶半部,然后会进入__setup_irq函数,函数中有一个判断是如果顶半部为默认的handler而且中断标识里没有IRQF_ONESHOT,那么处于安全考虑,会返回失败。

         将代码给出

else if (new->handler == irq_default_primary_handler &&

                      !(desc->irq_data.chip->flags &IRQCHIP_ONESHOT_SAFE)) {

                   /*

                    * The interrupt was requested with handler =NULL, so

                    * we use the default primary handler for it.But it

                    * does not have the oneshot flag set. Incombination

                    * with level interrupts this is deadly,because the

                    * default primary handler just wakes thethread, then

                    * the irq lines is reenabled, but the devicestill

                    * has the level irq asserted. Rinse andrepeat....

                    *

                    * While this works for edge type interrupts,we play

                    * it safe and reject unconditionally becausewe can't

                    * say for sure which type this interruptreally

                    * has. The type flags are unreliable as the

                    * underlying chip implementation can overridethem.

                    */

                   pr_err("Threadedirq requested with handler=NULL and !ONESHOT for irq %d\n",

                          irq);

                   ret= -EINVAL;

                   gotoout_mask;

         }

        

         这里考虑手动在驱动中添加了一个和系统默认的handler同样功能的函数irq_primary_handler,进行试验。

        

 

有ONE_SHOT

没有ONE_SHOT

IRQF_TRIGGER_FALLING

TP正常WORK

TP正常WORK

IRQF_TRIGGER_LOW

TP正常WORK

TP NO WORK

 

所以在驱动中,

1.      使用request_threaded_irq来申请中断时,通常的处理的使用NULL来使用系统默认的primary_handler,这时IRQF_ONESHOT标识不可少,否则中断会申请失败

2.       IRQF_ONESHOT的作用是保证thread_handler函数执行完整,才会接受下一个中断信号
 类似资料: