embassy-rs/embassy · error

When the HSI is used as cpu/system bus clock or clock…

Error message

When the HSI is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled

What it means

Same in-use guard as error 254 but for HSI: the driver refuses to disable HSI when it is the current cpu/system bus clock or the ready source of any running PLL (PLL1-PLL4), because the STM32N6 hardware does not allow disabling an oscillator that clocks the system or PLLs.

Solutions

  1. Move sysclk to a source not depending on HSI and stop all HSI-fed PLLs before disabling HSI
  2. Skip disabling HSI if it must remain the backup/active source
  3. Reorder: disable PLL1-4 first, then switch sysclk, then HSI off

Example fix

// before
config.hsi = None; // HSI still feeds sysclk
config.sys = SysClk::Hsi;
// after
config.hsi = Some(Hsi { .. });
config.sys = SysClk::Pll1; // PLL1 fed by HSE
config.hsi = None;
Defensive patterns

Strategy: validation

Validate before calling

fn hsi_in_use() -> bool {
    sysclk_is(Syssws::Hsi) || (0..4).any(|n| pll_ready(n) && pll_source(n) == Pllsel::Hsi)
}
assert!(!hsi_in_use(), "HSI still clocks sys or a PLL");

Prevention

When it happens

Trigger: Invoking the HSI-off path while sys source is HSI, or any PLL with pllrdy set uses Pllsel::Hsi as its input.

Common situations: Low-power entry or rcc re-init that blindly turns HSI off while HSI still feeds sysclk or a PLL; switching sysclk to a PLL that itself is fed by HSI (so HSI is still in use); partially migrated clock-tree code from another chip.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at embassy-stm32/src/rcc/n6.rs:996

    let (hsi, hsi_div) = if let Some(hsi) = config.hsi {
        RCC.csr().write(|w| w.set_hsions(true));
        while !RCC.sr().read().hsirdy() {}

        // set divider and calibration
        RCC.hsicfgr().modify(|w| {
            w.set_hsidiv(hsi.pre);
            w.set_hsitrim(hsi.trim);
        });

        (Some(HSI_FREQ), Some(HSI_FREQ / hsi.pre))
    } else if cpu_src == Cpusws::Hsi
        || sys_src == Syssws::Hsi
        || (pll1_src == Pllsel::Hsi && rcc_sr.pllrdy(0))
        || (pll2_src == Pllsel::Hsi && rcc_sr.pllrdy(1))
        || (pll3_src == Pllsel::Hsi && rcc_sr.pllrdy(2))
        || (pll4_src == Pllsel::Hsi && rcc_sr.pllrdy(3))
    {
        panic!(
            "When the HSI is used as cpu/system bus clock or clock source for any PLL, it is not allowed to be disabled"
        );
    } else {
        debug!("HSI off");

        RCC.ccr().write(|w| w.set_hsionc(true));
        while RCC.sr().read().hsirdy() {}

        (None, None)
    };

    // msi configuration
    debug!("configuring MSI");
    let msi = if let Some(msi) = config.msi {
        RCC.msicfgr().modify(|w| w.set_msifreqsel(msi.freq));
        RCC.csr().write(|w| w.set_msions(true));
        while !RCC.sr().read().msirdy() {}
        RCC.msicfgr().modify(|w| w.set_msitrim(msi.trim));

View on GitHub (pinned to 463a07b963)