内核模块中的中断处理:request_irq() 返回 -22,无效参数

Doc*_*lle 6 c interrupt linux-kernel

我正在尝试在由 gpio 中断触发的内核模块中设置一个中断处理程序,但似乎我没有request_irq()正确使用-function...我正在通过以下方式获取我的 irq-numbergpio_to_irq()这似乎有效。然后我打电话

request_irq(irqNumber, handler, 0, "GPIO_Test", NULL);
Run Code Online (Sandbox Code Playgroud)

但它返回-22,无效参数。我认为它可能是处理程序函数,因为我不确定它的签名 - 有时它被定义为void handler (int irq, void *dev_id, struct pt_regs *regs),有时被定义为static irqreturn_t handler(int irq, void *data)- 在这种情况下使用哪个是正确的,为什么有这两种完全不同的变体?我都试过,但总是得到相同的无效参数错误。

编译器给我一个关于我的处理程序函数的返回类型的警告:使用时:

static irqreturn_t handler(int irq, void *data)
{
    /*interrupt-handling*/

    return IRQ_HANDLED;
}
Run Code Online (Sandbox Code Playgroud)

»irq_handler_t« 预期,但参数类型 »enum irqreturn_t (* (*)(int, void *))(int, void *)«

...当使用:

void handler (int irq, void *dev_id, struct pt_regs *regs){/*interrupt-handling*/}
Run Code Online (Sandbox Code Playgroud)

»irq_handler_t« 预期,但参数类型 »void (*)(int, void *, struct pt_regs *)«

感谢您的支持 ;)

pah*_*pah 4

问题 ( -EINVAL) 不是由 引起的handler,因为内核无法在运行时确定其签名。

另外,handler在请求 IRQ via 时永远不会调用request_irq()(除非已定义,并且[使用错误的签名]只会在参数验证之后而不是之前导致未定义的行为,因此此时CONFIG_DEBUG_SHIRQ_FIXME不太可能返回 an )。-EINVAL

在正确设置 IRQ 之前,需要验证 4 个关键点:

  • irqflags- 你还没有设置,通过检查。
  • irq_to_desc()irq_desc_tree- 将执行查找irq. -EINVAL如果没有找到就会返回。否则,返回指向 irq 描述符结构的指针 ( struct irq_desc *)
  • irq_settings_can_request()- 检查是否可以请求 IRQ。int can_request_irq(unsigned int irq, unsigned long irqflags) 您可以通过调用before 轻松排除这种情况request_irq()
  • handler- 将检查是否handlerNULL。就你而言,事实并非如此。

所以基本上你只有两种可能导致问题的检查,其中之一你可以在can_request_irq()调用之前排除使用request_irq(),但不幸的是,这不可能在模块下执行,因为can_request_irq符号没有导出。

但如果您有耐心和时间,您可以使用内置代码构建一个新映像,只需查看can_request_irq()检查是否通过即可。如果确实如此,则导致问题的唯一检查是irq_to_desc(),这意味着该irq检查无效。

无法进一步扩展这个答案,因为我无法从您的问题中获得更多信息,但我希望它可以帮助您走上正确的轨道。

顺便说一句,只是指出在这种typedef情况irq_handler_t下它可能有用:

include/linux/interrupt.h:92(在 4.5 树上):

typedef irqreturn_t (*irq_handler_t)(int, void *);
Run Code Online (Sandbox Code Playgroud)