rust-embedded/rust-raspberrypi-OS-tutorials · error
Error handling IRQ
Error message
Error handling IRQ
What it means
After finding a registered IRQ descriptor, the GICv2 driver calls descriptor.handler().handle() and expects Ok(()); if the handler itself reports failure, the .expect("Error handling IRQ") panics. This library throws it because an IRQ handler that cannot service its interrupt leaves the peripheral in a stuck state and the error must be surfaced loudly.
Source
Thrown at 20_timer_callbacks/kernel/src/bsp/device_driver/arm/gicv2.rs:212
&'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() {
if let Some(handler) = opt {
info!(" {: >3}. {}", i + 32, handler.name());
}View on GitHub (pinned to 644474cc09)
Solutions
- Inspect the failing handler's handle() implementation and its error type to see which internal condition failed.
- Fix the handler so it correctly acknowledges/clears the interrupt source in the peripheral's status registers.
- Verify device initialization order — the handler's device must be fully initialized before its IRQ is enabled.
- If handle() returns Err for spurious interrupts, make the handler tolerate them (return Ok for no-op firings) instead of erroring.
Example fix
// before
fn handle(&self) -> Result<(), &'static str> {
Err("unexpected interrupt") // propagates -> expect("Error handling IRQ") panic
}
// after
fn handle(&self) -> Result<(), &'static str> {
self.clear_status();
Ok(())
} Defensive patterns
Strategy: validation
Validate before calling
// Handlers must be able to service their IRQ; verify the source is pending before enabling: assert!(timer.status_pending_bit_is_accessible(), "timer IRQ source must be serviceable");
Prevention
- Make handle() infallible where possible: acknowledge/clear unconditionally and reserve Err for truly impossible states.
- Fully initialize the device before enabling its IRQ.
- Handle spurious IRQs gracefully (ack and return Ok) instead of returning Err.
- Unit-test handlers against the datasheet's status-register semantics.
When it happens
Trigger: A registered IRQ handler's handle() implementation returns Err — e.g. the timer handler cannot clear its match/status register, a device's status register read fails the handler's internal validity checks, or the handler's expected state does not match reality when the IRQ fires.
Common situations: Timer handler called but timer registers were reconfigured concurrently, handler written for a different device revision whose status bits differ, IRQ shared/raced so the handler finds nothing to service and errors out, or a handler whose internal invariants were violated by earlier init mistakes.
Related errors
- No handler registered for 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/0fdaa64e19047b56.
Report an issue: GitHub.