rust-embedded/rust-raspberrypi-OS-tutorials · error
No handler registered for IRQ {}
Error message
No handler registered for IRQ {} What it means
The BCM peripheral interrupt controller's handle_pending_irqs walks all pending peripheral IRQs and panics if any has no entry in the handler table. This library throws it because an unclaimed pending peripheral interrupt cannot be dispatched or acknowledged and would otherwise re-trigger indefinitely.
Source
Thrown at 20_timer_callbacks/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs:155
®s.ENABLE_2
};
let enable_bit: u32 = 1 << (irq.get() % 32);
// Writing a 1 to a bit will set the corresponding IRQ enable bit. All other IRQ enable
// bits are unaffected. So we don't need read and OR'ing here.
enable_reg.set(enable_bit);
});
}
fn handle_pending_irqs<'irq_context>(
&'irq_context self,
_ic: &exception::asynchronous::IRQContext<'irq_context>,
) {
self.handler_table.read(|table| {
for irq_number in self.pending_irqs() {
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");
}
}
}
})
}
fn print_handler(&self) {
use crate::info;
info!(" Peripheral handler:");
self.handler_table.read(|table| {
for (i, opt) in table.iter().enumerate() {
if let Some(handler) = opt {
info!(" {: >3}. {}", i, handler.name());View on GitHub (pinned to 644474cc09)
Solutions
- Register a handler for the printed IRQ number before enabling it in the peripheral interrupt controller.
- Disable/mask that IRQ at the controller if it is not supposed to fire.
- Map the IRQ number to its device using the BCM datasheet and confirm the numbering scheme matches the controller in use (peripheral vs local vs GIC).
- Audit driver init order: register all handlers, then enable IRQs as the last step.
Example fix
// before peripheral_ic.irq_manager.enable(irq_number); // IRQ unmasked with no handler // after peripheral_ic.irq_manager.register_handler(irq_number, &system_timer_handler); peripheral_ic.irq_manager.enable(irq_number);
Defensive patterns
Strategy: validation
Validate before calling
// Enable an IRQ only after its handler is registered:
fn enable_irq_safely(irq: usize, mgr: &mut IrqManager) {
assert!(mgr.handler_registered(irq), "register a handler before enabling IRQ");
mgr.enable(irq);
} Type guard
fn handler_slot_filled(irq: usize, table: &[Option<IrqDescriptor>]) -> bool {
table.get(irq).map_or(false, |s| s.is_some())
} Prevention
- Treat handler registration as step 1 and IRQ enabling as the final init step in every driver.
- Keep separate, documented IRQ-number tables for peripheral vs local controllers on BCM SoCs.
- Clear stale enabled IRQs from previous boot stages at controller init.
- Provoke each IRQ during testing to confirm it dispatches to a registered handler.
When it happens
Trigger: A peripheral IRQ (GPIO, UART, system timer, etc.) becomes pending in the peripheral IC's pending registers while its handler-table slot is None — i.e. the IRQ was unmasked/enabled but register_handler() was never called for it.
Common situations: Enabling a system-timer or GPIO IRQ before registering its handler, using GIC-style IRQ numbers instead of BCM peripheral IRQ numbers, enabling IRQs in device drivers during bring-up but deferring handler registration, or a leftover enabled IRQ from a previous boot stage.
Related errors
- No handler registered for IRQ {}
- Error handling IRQ
- Error handling IRQ
- 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/af6dd487676da2a6.
Report an issue: GitHub.