You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

共享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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 04:24:11