{"record":{"id":"1237c2396f52c807","repo":"rust-embedded/rust-raspberrypi-OS-tutorials","slug":"error-handling-irq-1237c2","errorCode":null,"errorMessage":"Error handling IRQ","messagePattern":"Error handling IRQ","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"20_timer_callbacks/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs","lineNumber":158,"sourceCode":"            let enable_bit: u32 = 1 << (irq.get() % 32);\n\n            // Writing a 1 to a bit will set the corresponding IRQ enable bit. All other IRQ enable\n            // bits are unaffected. So we don't need read and OR'ing here.\n            enable_reg.set(enable_bit);\n        });\n    }\n\n    fn handle_pending_irqs<'irq_context>(\n        &'irq_context self,\n        _ic: &exception::asynchronous::IRQContext<'irq_context>,\n    ) {\n        self.handler_table.read(|table| {\n            for irq_number in self.pending_irqs() {\n                match table[irq_number] {\n                    None => panic!(\"No handler registered for IRQ {}\", irq_number),\n                    Some(descriptor) => {\n                        // Call the IRQ handler. Panics on failure.\n                        descriptor.handler().handle().expect(\"Error handling IRQ\");\n                    }\n                }\n            }\n        })\n    }\n\n    fn print_handler(&self) {\n        use crate::info;\n\n        info!(\"      Peripheral handler:\");\n\n        self.handler_table.read(|table| {\n            for (i, opt) in table.iter().enumerate() {\n                if let Some(handler) = opt {\n                    info!(\"            {: >3}. {}\", i, handler.name());\n                }\n            }\n        });","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/644474cc09f755249f9c55d99a5d1e07a2562fc7/20_timer_callbacks/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/peripheral_ic.rs#L140-L176","documentation":"In the BCM peripheral interrupt controller, when a registered handler's handle() returns Err, .expect(\"Error handling IRQ\") panics. The library escalates handler-internal failures because the interrupt cannot be confirmed serviced and the peripheral may remain in a pending state.","triggerScenarios":"The handler registered for a pending peripheral IRQ returns Err from handle() — its device-specific servicing logic fails (status bit not set as expected, clear operation rejected, internal invariant broken) at the moment the IRQ fires.","commonSituations":"System-timer handler invoked with a mismatched compare register configuration, GPIO handler triggered by a pin whose event configuration was changed after enabling the IRQ, drivers sharing IRQs with incompatible handlers, or handler state invalidated by re-initialization while the IRQ stays enabled.","solutions":["Trace the concrete Err returned by the failing handler and fix the device servicing logic (correct status/clear registers).","Disable the IRQ while reconfiguring its device, then re-enable after the handler's invariants hold.","Make handlers tolerant of spurious or shared-IRQ firings by acknowledging and returning Ok.","Ensure the device behind the handler is fully initialized before its IRQ is unmasked."],"exampleFix":"// before\nfn handle(&self) -> Result<(), &'static str> {\n    Err(\"M1 bit not set\") // -> expect(\"Error handling IRQ\") panic\n}\n// after\nfn handle(&self) -> Result<(), &'static str> {\n    self.timer.clear_matched();\n    Ok(())\n}","handlingStrategy":"validation","validationCode":"// Verify the device can service its IRQ before enabling it:\nif !gpio.event_config_valid(pin) { panic!(\"configure GPIO event before enabling its IRQ\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Write handlers that acknowledge unconditionally so spurious/shared IRQs return Ok.","Freeze device configuration before enabling its IRQ; reconfigure only with the IRQ masked.","Keep handler state private and immutable after init to avoid races.","Test each handler's Err paths and eliminate them by construction."],"tags":["interrupts","bcm","raspberry-pi","bare-metal","panic"],"backgroundTag":"irq-handler-failed","analyzedSha":"644474cc09f755249f9c55d99a5d1e07a2562fc7","analyzedAt":"2026-09-06T09:25:56.584Z","contentChangedAt":"2026-09-06T09:25:56.584Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}