{"record":{"id":"078cfc91881550bc","repo":"rust-embedded/rust-raspberrypi-OS-tutorials","slug":"error-handling-irq-078cfc","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/local_ic.rs","lineNumber":153,"sourceCode":"            let enable_bit: u32 = 1 << (irq.get());\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            regs.CORE0_TIMER_INTERRUPT_CONTROL.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!(\"      Local 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":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/rust-embedded/rust-raspberrypi-OS-tutorials/blob/644474cc09f755249f9c55d99a5d1e07a2562fc7/20_timer_callbacks/kernel/src/bsp/device_driver/bcm/bcm2xxx_interrupt_controller/local_ic.rs#L135-L171","documentation":"In the BCM local interrupt controller, a registered handler's handle() returning Err triggers .expect(\"Error handling IRQ\"), panicking. The library surfaces handler failures as fatal because the local IRQ cannot be considered serviced and the system state is undefined.","triggerScenarios":"The handler registered for a pending local IRQ (e.g. local timer) returns Err from handle() — internal state checks fail, the peripheral's pending bit cannot be cleared, or the handler's expected device state is absent when the IRQ arrives.","commonSituations":"Local timer handler running before the timer was initialized on that core, status-register bit layouts differing between BCM2837 and BCM2711, shared IRQs where the handler finds no source to service, and re-entrant IRQ handling corrupting handler state.","solutions":["Read the specific Err from the failing handler's handle() and fix the underlying peripheral interaction (clear/ack the correct register).","Ensure per-core device initialization completes before enabling the core's local IRQs.","Make the handler robust to spurious firings (acknowledge and return Ok instead of Err).","Check for races: disable the IRQ while reconfiguring the device it belongs to."],"exampleFix":"// before\nfn handle(&self) -> Result<(), &'static str> {\n    Err(\"no pending source\") // -> expect(\"Error handling IRQ\") panic\n}\n// after\nfn handle(&self) -> Result<(), &'static str> {\n    if self.pending() { self.clear_pending(); }\n    Ok(())\n}","handlingStrategy":"validation","validationCode":"// Ensure per-core device init completed before enabling its local IRQ:\nif !local_timer_initialized_on(core_id) { panic!(\"init local timer before enabling its IRQ\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Initialize per-core devices before enabling their local IRQs.","Acknowledge pending sources even on spurious firings to keep handle() returning Ok.","Disable IRQs while reconfiguring the device they belong to.","Match handler logic to the exact BCM chip revision in use."],"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"}