{"record":{"id":"5e2877c3fa46c2a1","repo":"embassy-rs/embassy","slug":"enabling-ostimer-clock-should-not-fail","errorCode":null,"errorMessage":"Enabling OsTimer clock should not fail","messagePattern":"Enabling OsTimer clock should not fail","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-mcxa/src/ostimer.rs","lineNumber":83,"sourceCode":"    /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.\n    alarms: Mutex<CriticalSectionRawMutex, AlarmState>,\n    queue: Mutex<CriticalSectionRawMutex, RefCell<Queue>>,\n}\n\nimpl OsTimer {\n    fn init(&'static self, irq_prio: crate::interrupt::Priority) {\n        // init alarms\n        critical_section::with(|cs| {\n            let alarm = DRIVER.alarms.borrow(cs);\n            alarm.timestamp.set(u64::MAX);\n        });\n\n        let parts = unsafe {\n            enable_and_reset::<OSTIMER0>(&OsTimerConfig {\n                power: PoweredClock::AlwaysEnabled,\n                source: OstimerClockSel::Clk1M,\n            })\n            .expect(\"Enabling OsTimer clock should not fail\")\n        };\n\n        // Currently does nothing as Clk1M is always enabled anyway, this is here\n        // to make sure that doesn't change in a refactoring.\n        core::mem::forget(parts.wake_guard);\n\n        interrupt::OS_EVENT.disable();\n\n        // Make sure interrupt is masked\n        OSTIMER0.osevent_ctrl().modify(|w| w.set_ostimer_intena(false));\n\n        // Default to the end of time\n        OSTIMER0.match_l().write(|w| w.set_match_value(u32::MAX));\n        OSTIMER0.match_h().write(|w| w.set_match_value(u16::MAX));\n\n        interrupt::OS_EVENT.unpend();\n        interrupt::OS_EVENT.set_priority(irq_prio);\n        unsafe { interrupt::OS_EVENT.enable() };","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-mcxa/src/ostimer.rs#L65-L101","documentation":"embassy-mcxa's OsTimer driver init calls enable_and_reset::<OSTIMER0> and unwraps the result with the message \"Enabling OsTimer clock should not fail\". The expect assumes the 1 MHz always-on clock (Clk1M) is always available; if the clock enable operation returns an error (e.g. the power/clock controller rejects the request or the config's clock source is gated), the driver panics during time-driver initialization.","triggerScenarios":"Initializing the embassy time driver (embassy_mcxa::ostimer::OsTimer::init, usually reached via embassy executor/time driver setup) when enable_and_reset::<OSTIMER0> with PoweredClock::AlwaysEnabled and OstimerClockSel::Clk1M returns Err.","commonSituations":"Boot issues on MCX A/N series boards where the always-on 1 MHz clock domain or the OSTIMER0 peripheral clock gate is unavailable or the clock configuration layer has a bug/regression.","solutions":["Update embassy-mcxa to the latest version; failures in this path are typically library bugs fixed upstream","Verify your chip/feature selection matches your actual MCX part so the correct OSTIMER0 instance and clock config are used","Check that nothing earlier in boot disabled the always-on/1 MHz clock domain or the OSTIMER0 power domain","If it persists, file an upstream issue with the returned error from enable_and_reset (temporarily replace the expect with a match to log it)"],"exampleFix":"// before\n.enable_and_reset::<OSTIMER0>(&OsTimerConfig { .. })\n    .expect(\"Enabling OsTimer clock should not fail\");\n// after (debug)\nlet parts = unsafe { enable_and_reset::<OSTIMER0>(&cfg) };\nif let Err(e) = &parts { defmt::error!(\"ostimer enable failed: {:?}\", e); }\nlet parts = parts.expect(\"Enabling OsTimer clock should not fail\");","handlingStrategy":"try-catch","validationCode":"// Probe the clock before handing control to the time driver\n// (no_std: log the concrete error instead of an opaque panic)\nmatch unsafe { enable_and_reset::<OSTIMER0>(&OsTimerConfig::default()) } {\n    Ok(_) => {},\n    Err(e) => defmt::error!(\"OSTIMER0 enable failed: {:?}\", e),\n}","typeGuard":null,"tryCatchPattern":"// Replace the library's expect during bring-up to surface the root cause\nlet parts = unsafe { enable_and_reset::<OSTIMER0>(&cfg) };\nlet parts = match parts {\n    Ok(p) => p,\n    Err(e) => { defmt::error!(\"ostimer init failed: {:?}\", e); defmt::panic!(); }\n};","preventionTips":["Keep embassy-mcxa and related HAL crates on versions tested together","Initialize the time driver first, before any code can gate clocks","Verify your target/feature selection matches the exact MCX part number on your board","During bring-up, surface enable_and_reset errors with logging rather than bare expects"],"tags":["embedded","mcx","clock-config","panic","time-driver"],"backgroundTag":"module-init-failed","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}