我正在尝试在内核模块中设置一个由gpio-interrupt触发的中断处理程序,但似乎我没有使用request_irq()
- 函数正确...
我通过gpio_to_irq()
得到了我的irq号码,这似乎有效。
然后我正在打电话
request_irq(irqNumber, handler, 0, "GPIO_Test", NULL);
但它返回-22,参数无效。
我认为它可能是处理程序函数,因为我不确定它的签名 - 有时它定义为void handler (int irq, void *dev_id, struct pt_regs *regs)
,有时定义为static irqreturn_t handler(int irq, void *data)
- 在这种情况下哪一个是正确的,以及为什么这两种完全不同的变化吗?
我试过了两个,但总是得到相同的Invalid-parameters-error。
编译器给我一个关于我的handler-function的return-type的警告: 使用时:
static irqreturn_t handler(int irq, void *data)
{
/*interrupt-handling*/
return IRQ_HANDLED;
}
»irq_handler_t«预期,但参数类型为:enum irqreturn_t(*(*)(int,void *))(int,void *)«
......以及使用时:
void handler (int irq, void *dev_id, struct pt_regs *regs){/*interrupt-handling*/}
»irq_handler_t«预期,但参数的类型为:void(*)(int,void *,struct pt_regs *)«
感谢您的支持;)
答案 0 :(得分:1)
问题(-EINVAL
)并非由handler
引起,因为内核无法在运行时确定其签名。
此外,handler
在通过request_irq()
请求IRQ时从不被调用(除非定义了CONFIG_DEBUG_SHIRQ_FIXME
,并且[带有错误的签名]只会导致参数验证后的未定义行为,而不是之前,所以此时不太可能返回-EINVAL
。
在正确设置IRQ之前,有4个关键点已经过验证:
irqflags
- 您没有设置,通过了支票。irq_to_desc()
- 对irq_desc_tree
的{{1}}执行查找。如果找不到,将返回irq
。否则,返回指向irq描述符结构(-EINVAL
)struct irq_desc *
- 检查是否可以请求IRQ。您可以在 irq_settings_can_request()
之前致电int can_request_irq(unsigned int irq, unsigned long irqflags)
,轻松排除此问题。request_irq()
- 会检查handler
是否为handler
。在你的情况下,它不是。所以基本上你只有两个可能导致问题的可能检查,其中一个你可以在调用NULL
之前使用can_request_irq()
排除,但不幸的是,这赢了&# 39;可以在模块下执行,因为request_irq()
符号未导出。
但是如果你有耐心和时间,你可以使用内置的代码构建一个新图像,只需查看can_request_irq
检查是否通过。如果是,则导致问题的唯一检查是can_request_irq()
,这意味着irq_to_desc()
无效。
无法更多地延伸这个答案,因为我的问题没有更多信息可以处理,但我希望它可以帮助您走上正确的轨道。
顺便说一句,只是指出irq
typedef
的情况可能有用:
irq_handler_t
(在4.5树上):
include/linux/interrupt.h:92
答案 1 :(得分:0)
request_any_context_irq
API (patch) 将在您的中断线嵌套并重新使用线程处理程序时自动处理这种情况。由于您无法从模块访问 irq_settings_can_request
,因此在添加检测之前值得使用。
此调用分配中断资源并启用中断线 和 IRQ 处理。它选择硬中断或线程处理 方法取决于上下文。
失败时,它返回一个负值。成功时,它返回 IRQC_IS_HARDIRQ 或 IRQC_IS_NESTED。