{"record":{"id":"6c811ce7a885a1e6","repo":"rust-embedded/rust-raspberrypi-OS-tutorials","slug":"no-handler-registered-for-irq-6c811c","errorCode":null,"errorMessage":"No handler registered for IRQ {}","messagePattern":"No handler registered for 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":150,"sourceCode":"\n    fn enable(&self, irq: &Self::IRQNumberType) {\n        self.wo_registers.lock(|regs| {\n            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());","sourceCodeStart":132,"sourceCodeEnd":168,"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#L132-L168","documentation":"The BCM interrupt controller's local interrupt controller iterates all pending IRQs and looks each up in its handler table; a None entry panics with 'No handler registered for IRQ'. Like the GICv2 variant, this library treats an unclaimed pending interrupt as fatal because it cannot be acknowledged and would re-fire endlessly.","triggerScenarios":"pending_irqs() yields an IRQ number (from the local interrupt controller's pending registers) whose handler-table slot was never populated via register_handler() — e.g. a local/per-core interrupt (like a local timer or mailbox IRQ) enabled but not claimed.","commonSituations":"Enabling a local timer or aux IRQ in the local IC before registering its handler, different IRQ numbering per core causing a valid handler on core 0 to be missing on core 1, or copying GIC IRQ numbers into BCM table indices.","solutions":["Register a handler for the reported IRQ number on every core that can receive it (local IC handlers are per-core).","Disable the unwanted local IRQ in the local interrupt controller's enable registers if it should never fire.","Verify the pending IRQ number against the BCM2711/BCM2837 datasheet — BCM IRQ numbering differs from GIC numbering.","Initialize and register handlers identically on each core during SMP bring-up."],"exampleFix":"// before\nlocal_ic.irq_manager.enable(per_core_irq_number); // no handler registered on this core\n// after\nlocal_ic.irq_manager.register_handler(per_core_irq_number, &local_timer_handler);\nlocal_ic.irq_manager.enable(per_core_irq_number);","handlingStrategy":"validation","validationCode":"// Register the handler on every core before enabling a local IRQ:\nfor core in 0..NUM_CORES {\n    local_ic(core).irq_manager.register_handler(irq, &handler);\n    local_ic(core).irq_manager.enable(irq);\n}","typeGuard":"fn irq_is_registered(irq: usize, table: &[Option<IrqDescriptor>]) -> bool {\n    table.get(irq).is_some() && table[irq].is_some()\n}","tryCatchPattern":null,"preventionTips":["Use BCM-specific IRQ numbering; do not reuse GIC numbers.","Initialize and register local-IC handlers identically on all cores during SMP bring-up.","Mask IRQs you do not handle rather than leaving them enabled.","Consult the BCM2711/BCM2837 datasheet when mapping pending IRQ numbers to devices."],"tags":["interrupts","bcm","raspberry-pi","bare-metal","panic"],"backgroundTag":"missing-irq-handler","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"}