自定义硬件中断处理问题:Linux下无法捕获Xilinx FPGA中断
Alright, let's walk through this—moving from uCOS-II to Linux for FPGA interrupts has some key differences that are probably tripping you up. Let's start with the extra steps you need beyond just registering the IRQ, then cover how to monitor all interrupt traffic to the CPU.
Extra Steps Beyond register_irq (or request_irq)
uCOS-II is a lightweight RTOS that often maps hardware interrupts directly, but Linux has a more robust interrupt subsystem with extra layers. Here's what you might be missing:
Validate the IRQ number mapping
The hardware interrupt ID 94 you used in uCOS-II might not match the Linux virtual IRQ number. On Xilinx systems (especially ARM with GIC), hardware interrupts (like SPI interrupts) are mapped to Linux IRQs via the interrupt controller. Usecat /proc/interruptsto list registered IRQs, or in your driver, useirq_find_mapping()orplatform_get_irq()(if using device tree) to fetch the correct Linux IRQ number instead of hardcoding 94.Explicitly set the interrupt trigger type
Unlike uCOS-II, Linux requires you to specify the trigger mode when requesting an IRQ. Make sure you pass the correct flags todevm_request_irq()(the modern, resource-managed alternative toregister_irq), likeIRQF_TRIGGER_RISING,IRQF_TRIGGER_FALLING, orIRQF_TRIGGER_HIGH—this must match how your FPGA is configured to send interrupts. For example:devm_request_irq(&pdev->dev, irq, my_interrupt_handler, IRQF_TRIGGER_RISING, "my-fpga-irq", dev_data);Enable the interrupt at the hardware level
uCOS-II might have initialized the FPGA's interrupt controller (or AXI interrupt router) automatically, but Linux expects your driver to handle this. Check your FPGA's register map—you'll likely need to write to a specific MMIO register to unmask/enable the interrupt line leading to the CPU. Don't skip this step!Verify interrupt controller configuration
If you're on an ARM system with GIC, ensure the GIC has routed the interrupt to your target CPU core. You can check/set interrupt affinity with:# Bind IRQ to CPU 0 (replace <linux-irq-number> with the correct value) echo 1 > /proc/irq/<linux-irq-number>/smp_affinityAlso, use debugfs (if enabled) to inspect
/sys/kernel/debug/irq/<irq-number>/statusand confirm the interrupt isn't masked at the controller level.Use the modern IRQ registration API
register_irq()is deprecated in newer Linux kernels. Switch todevm_request_irq()which handles resource cleanup automatically and reduces bugs. Make sure your interrupt handler follows the correct prototype:irqreturn_t my_interrupt_handler(int irq, void *dev_id) { // Handle interrupt logic here return IRQ_HANDLED; }
How to Monitor All Interrupts to the CPU (Even Unhandled Ones)
To confirm whether the CPU is receiving the FPGA's interrupt (even if your handler isn't triggering), try these tools:
Check
/proc/interrupts
This file shows the count of interrupts received per IRQ and CPU core. If your FPGA is sending interrupts, the count for the corresponding Linux IRQ should increment—even if there's no handler registered (behavior varies slightly by interrupt controller).Use
perffor interrupt tracing
Theperftool can capture all interrupt events, including unhandled ones. Run:# Record all interrupt events with call graphs perf record -e irq:* -g # View the captured report perf reportLook for events like
irq:irq_entryorirq:irq_exitto see if the CPU is acknowledging the interrupt.Inspect kernel debug logs
Enable verbose interrupt debugging by adjusting the kernel printk level:echo 1 > /proc/sys/kernel/printkThen watch
dmesg -w—if the CPU receives an unhandled interrupt, you might see messages likeunhandled interrupt <irq-number>(depending on your kernel'sCONFIG_IRQ_DEBUGsetting).Use hardware debugging tools
For Xilinx FPGAs, use Vivado's Integrated Logic Analyzer (ILA) to probe the interrupt output pin of your custom hardware. This confirms whether the FPGA is actually sending the signal before it reaches the CPU. You can also read the GIC's pending registers via MMIO to check if the interrupt is reaching the controller.Check debugfs for interrupt status
If your kernel hasCONFIG_DEBUG_FSenabled, navigate to/sys/kernel/debug/irq/. Theirqsfile lists all interrupts and their state (pending, active, etc.)—even those without registered handlers.
内容的提问来源于stack exchange,提问作者charlesw




