嵌入式Linux不使用设备树设置PL/PS中断的问题求助
解决PL到PS中断捕获失败(request_irq返回-22)的无设备树修改方案
首先,request_irq返回-22(EINVAL)的核心原因是你使用的中断号未被内核GIC控制器识别,或者触发配置与硬件不匹配。以下是无需修改设备树的可行方案:
1. 确定正确的硬件中断号
对于Zynq系列(包括7000和UltraScale+),PL到PS的中断属于GIC的SPI(共享外设中断),硬件中断号的计算规则为:
硬件中断号 = 32 + Vivado中配置的IRQ_F2P编号
你的IRQ_F2P是61,因此对应的硬件中断号为32 + 61 = 93(此编号适用于Zynq UltraScale+平台,若为Zynq-7000,IRQ_F2P范围仅0-15,你的场景显然属于UltraScale+)。
2. 动态映射中断号(关键步骤)
由于未修改设备树,内核默认不会将该PL中断加入可用中断池,因此需要先通过irq_create_mapping动态完成硬件中断号到内核虚拟中断号的映射:
#include <linux/irqdomain.h> #include <linux/interrupt.h> // 硬件中断号,根据你的情况设置为93 #define HW_IRQ_NUM 93 int ret; unsigned int virq; // 动态映射硬件中断号到虚拟中断号 virq = irq_create_mapping(NULL, HW_IRQ_NUM); if (!virq) { pr_err("Failed to map hardware interrupt %d\n", HW_IRQ_NUM); return -ENODEV; }
irq_create_mapping会自动查找GIC中断域,完成映射后返回有效的内核虚拟中断号。
3. 使用映射后的虚拟中断号注册中断
用返回的virq替代之前的错误中断号调用request_irq,同时确保触发方式与PL端配置一致(比如PL输出上升沿触发,驱动中就用IRQF_TRIGGER_RISING):
ret = request_irq(virq, your_interrupt_handler, IRQF_TRIGGER_RISING, "pl-irq-driver", NULL); if (ret) { pr_err("Failed to request irq %d, ret = %d\n", virq, ret); irq_dispose_mapping(virq); // 映射失败时清理资源 return ret; }
4. 额外检查项
- 确认PL端中断已正确配置:中断输出使能,触发方式(上升沿/下降沿/电平)与驱动中
request_irq的参数完全匹配; - 查看系统中断状态:通过
cat /proc/interrupts或cat /sys/kernel/debug/irq/irqchip/gic-0/spi(GICv2平台)确认映射后的虚拟中断号是否存在; - 若仍失败,可先设置触发类型再注册:部分平台默认屏蔽未声明的SPI中断,可先调用
irq_set_irq_type(virq, IRQF_TRIGGER_RISING),再执行request_irq。
内容的提问来源于stack exchange,提问作者Boune
相关产品推荐
相关产品推荐

