rust-embedded/rust-raspberrypi-OS-tutorials · error
No handler registered for IRQ {}
Error message
No handler registered for IRQ {} What it means
The GICv2 interrupt controller's handle_pending_irqs looks up the pending IRQ number in the registered handler table; if the slot is None, no driver ever registered a handler for that interrupt, so the kernel panics. This library throws it because delivering an IRQ nobody claimed to handle would leave it perpetually asserted (spurious re-fires), which is unrecoverable in this design.
Source
Thrown at 20_timer_callbacks/kernel/src/bsp/device_driver/arm/gicv2.rs:209
}
fn handle_pending_irqs<'irq_context>(
&'irq_context self,
ic: &exception::asynchronous::IRQContext<'irq_context>,
) {
// Extract the highest priority pending IRQ number from the Interrupt Acknowledge Register
// (IAR).
let irq_number = self.gicc.pending_irq_number(ic);
// Guard against spurious interrupts.
if irq_number > GICv2::MAX_IRQ_NUMBER {
return;
}
// Call the IRQ handler. Panic if there is none.
self.handler_table.read(|table| {
match table[irq_number] {
None => panic!("No handler registered for IRQ {}", irq_number),
Some(descriptor) => {
// Call the IRQ handler. Panics on failure.
descriptor.handler().handle().expect("Error handling IRQ");
}
}
});
// Signal completion of handling.
self.gicc.mark_comleted(irq_number as u32, ic);
}
fn print_handler(&self) {
use crate::info;
info!(" Peripheral handler:");
self.handler_table.read(|table| {
for (i, opt) in table.iter().skip(32).enumerate() {View on GitHub (pinned to 644474cc09)
Solutions
- Call register_handler() with an IRQHandler descriptor for the reported IRQ number before enabling it in the GIC.
- Disable the unexpected IRQ at the GIC distributor (GICD_ICENABLER) if it should not fire, or mask it at the peripheral.
- Cross-check the IRQ number printed in the panic against the device datasheet and the BSP's defined IRQ numbers.
- Add a default/no-op handler for interrupts you intend to ignore but not mask.
Example fix
// before interrupt_controller.irq_manager.enable(irq_number); // enabled but no handler registered // after interrupt_controller.irq_manager.register_handler(irq_number, &timer_handler); interrupt_controller.irq_manager.enable(irq_number);
Defensive patterns
Strategy: validation
Validate before calling
// Before enabling an IRQ, assert a handler is registered:
fn can_enable(irq: usize, table: &[Option<IrqDescriptor>; N]) -> bool {
table.get(irq).map_or(false, |slot| slot.is_some())
} Type guard
fn has_handler(irq: usize, table: &[Option<IrqDescriptor>]) -> bool {
matches!(table.get(irq), Some(Some(_)))
} Prevention
- Register every handler before enabling its IRQ line — make enable() require prior registration.
- Keep a single source of truth for IRQ numbers per BSP to avoid numbering mistakes.
- Test each IRQ by forcing it to fire during bring-up.
- Disable unused IRQ lines at the distributor so they cannot become pending.
When it happens
Trigger: A pending interrupt read from GICD_ISENABLER/GICC IAR has an ID whose entry in the IRQ handler table is None — i.e. the IRQ was enabled at the GIC/distributor level but register_handler() was never called for it.
Common situations: Enabling an IRQ in the GIC distributor before registering its handler, BSP interrupt-controller init enabling default IRQs, adding a new device that fires an IRQ but forgetting to register its handler, or IRQ number mismatches between datasheet and code.
Related errors
- Error handling IRQ
- CPU Exception! {}
- Should not be here. Use of SP_EL0 in EL1 is not supported.
- No handler registered for IRQ {}
- Error handling IRQ
AI-assisted analysis of rust-embedded/rust-raspberrypi-OS-tutorials@644474cc09 (2026-09-06).
Data as JSON: /api/errors/59726003563d052d.
Report an issue: GitHub.