共享HW_IRQ的无设备树Module2,如何实现HW_IRQ转Linux IRQ?
共享HW_IRQ的内核模块中断号转换实现方案
针对你描述的场景,有以下几种可行的实现方式:
方法一:通过irq_find_mapping直接映射硬件中断号
Linux内核提供irq_find_mapping函数,可直接将硬件中断号(HW_IRQ)转换为对应的Linux虚拟中断号。由于Module1已经完成了该HW_IRQ的注册映射,调用此函数会直接返回已存在的虚拟中断号(即与linux_irq1相同的linux_irq2)。
代码示例:
#include <linux/interrupt.h> static int __init module2_init(void) { unsigned int hw_irq = YOUR_HW_IRQ_NUMBER; // 替换为实际的硬件中断号 unsigned int linux_irq2 = irq_find_mapping(NULL, hw_irq); if (linux_irq2 == 0) { pr_err("Failed to map HW_IRQ %u to Linux IRQ\n", hw_irq); return -EINVAL; } if (request_irq(linux_irq2, handler2, IRQF_SHARED, "module2_shared_irq", handler2)) { pr_err("Failed to request IRQ %u\n", linux_irq2); return -EBUSY; } pr_info("Module2 registered IRQ %u successfully\n", linux_irq2); return 0; } static void __exit module2_exit(void) { unsigned int hw_irq = YOUR_HW_IRQ_NUMBER; unsigned int linux_irq2 = irq_find_mapping(NULL, hw_irq); if (linux_irq2 != 0) { free_irq(linux_irq2, handler2); } } module_init(module2_init); module_exit(module2_exit); MODULE_LICENSE("GPL");
- 说明:
irq_find_mapping的第一个参数为中断域指针,传入NULL表示使用默认中断域,适用于无特殊中断域的常规硬件场景。
方法二:遍历已注册中断匹配硬件中断号
通过遍历系统中所有已注册的中断描述符,匹配目标HW_IRQ对应的Linux虚拟中断号。
代码示例:
#include <linux/interrupt.h> #include <linux/irqdesc.h> static int __init module2_init(void) { unsigned int hw_irq = YOUR_HW_IRQ_NUMBER; unsigned int linux_irq2 = 0; struct irq_desc *desc; for_each_irq_desc(linux_irq2, desc) { struct irq_data *irq_data = irq_desc_get_irq_data(desc); if (irq_data->hwirq == hw_irq) { break; } linux_irq2 = 0; } if (linux_irq2 == 0) { pr_err("No Linux IRQ mapped to HW_IRQ %u\n", hw_irq); return -EINVAL; } if (request_irq(linux_irq2, handler2, IRQF_SHARED, "module2_shared_irq", handler2)) { pr_err("Failed to request IRQ %u\n", linux_irq2); return -EBUSY; } pr_info("Module2 registered IRQ %u successfully\n", linux_irq2); return 0; } static void __exit module2_exit(void) { unsigned int hw_irq = YOUR_HW_IRQ_NUMBER; unsigned int linux_irq2 = 0; struct irq_desc *desc; for_each_irq_desc(linux_irq2, desc) { struct irq_data *irq_data = irq_desc_get_irq_data(desc); if (irq_data->hwirq == hw_irq) { break; } linux_irq2 = 0; } if (linux_irq2 != 0) { free_irq(linux_irq2, handler2); } } module_init(module2_init); module_exit(module2_exit); MODULE_LICENSE("GPL");
- 说明:
for_each_irq_desc是内核提供的遍历中断描述符的宏,不同内核版本可能存在接口差异,需根据目标内核版本适配;直接访问中断描述符需要模块具备对应权限,编译时需确保内核配置支持相关符号导出。
方法三:修改Module1导出中断号符号(备选)
如果允许对Module1进行微小修改,可以在Module1中添加EXPORT_SYMBOL(linux_irq1);,将linux_irq1导出为全局符号,Module2即可直接引用该符号作为linux_irq2使用。但此方法依赖对Module1的修改权限,若Module1无法修改则不适用。
内容的提问来源于stack exchange,提问作者drymon
相关产品推荐
相关产品推荐

