embassy-rs/embassy · error

Enabling OsTimer clock should not fail

Error message

Enabling OsTimer clock should not fail

What it means

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.

Solutions

  1. Update embassy-mcxa to the latest version; failures in this path are typically library bugs fixed upstream
  2. Verify your chip/feature selection matches your actual MCX part so the correct OSTIMER0 instance and clock config are used
  3. Check that nothing earlier in boot disabled the always-on/1 MHz clock domain or the OSTIMER0 power domain
  4. 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)

Example fix

// before
.enable_and_reset::<OSTIMER0>(&OsTimerConfig { .. })
    .expect("Enabling OsTimer clock should not fail");
// after (debug)
let parts = unsafe { enable_and_reset::<OSTIMER0>(&cfg) };
if let Err(e) = &parts { defmt::error!("ostimer enable failed: {:?}", e); }
let parts = parts.expect("Enabling OsTimer clock should not fail");
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe the clock before handing control to the time driver
// (no_std: log the concrete error instead of an opaque panic)
match unsafe { enable_and_reset::<OSTIMER0>(&OsTimerConfig::default()) } {
    Ok(_) => {},
    Err(e) => defmt::error!("OSTIMER0 enable failed: {:?}", e),
}

Try / catch

// Replace the library's expect during bring-up to surface the root cause
let parts = unsafe { enable_and_reset::<OSTIMER0>(&cfg) };
let parts = match parts {
    Ok(p) => p,
    Err(e) => { defmt::error!("ostimer init failed: {:?}", e); defmt::panic!(); }
};

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/5e2877c3fa46c2a1. Report an issue: GitHub.

Appendix: source

Thrown at embassy-mcxa/src/ostimer.rs:83

    /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.
    alarms: Mutex<CriticalSectionRawMutex, AlarmState>,
    queue: Mutex<CriticalSectionRawMutex, RefCell<Queue>>,
}

impl OsTimer {
    fn init(&'static self, irq_prio: crate::interrupt::Priority) {
        // init alarms
        critical_section::with(|cs| {
            let alarm = DRIVER.alarms.borrow(cs);
            alarm.timestamp.set(u64::MAX);
        });

        let parts = unsafe {
            enable_and_reset::<OSTIMER0>(&OsTimerConfig {
                power: PoweredClock::AlwaysEnabled,
                source: OstimerClockSel::Clk1M,
            })
            .expect("Enabling OsTimer clock should not fail")
        };

        // Currently does nothing as Clk1M is always enabled anyway, this is here
        // to make sure that doesn't change in a refactoring.
        core::mem::forget(parts.wake_guard);

        interrupt::OS_EVENT.disable();

        // Make sure interrupt is masked
        OSTIMER0.osevent_ctrl().modify(|w| w.set_ostimer_intena(false));

        // Default to the end of time
        OSTIMER0.match_l().write(|w| w.set_match_value(u32::MAX));
        OSTIMER0.match_h().write(|w| w.set_match_value(u16::MAX));

        interrupt::OS_EVENT.unpend();
        interrupt::OS_EVENT.set_priority(irq_prio);
        unsafe { interrupt::OS_EVENT.enable() };

View on GitHub (pinned to 463a07b963)