embassy-rs/embassy · error

PLL should not be disabled / reconfigured if used for IC2…

Error message

PLL should not be disabled / reconfigured if used for IC2, IC6 or IC11 (sysclksrc)

What it means

Companion guard to error 257 on the system-clock side: when reconfiguring a PLL, if the system clock switch is on IC2 and any of IC2/IC6/IC11 currently select this PLL, disabling it would collapse the system clock, so the driver panics before the disable/reconfigure.

Solutions

  1. Switch sysclk to a temporary independent source (e.g. HSI via a direct Syssw) before reconfiguring the PLL
  2. Reconfigure a PLL that is not in the active IC2/IC6/IC11 chain, then retarget the ICs
  3. Design the final clock tree up front and avoid re-running init_config on a live PLL-fed sysclk

Example fix

// before
config.pll2 = Some(new_pll2_cfg); // IC2 chain runs on PLL2
init(config);
// after
// step 1: switch sysclk off the PLL chain
config.sys = SysClk::Hsi;
init(config);
// step 2: apply new PLL2 and switch back to SysClk::Ic2
Defensive patterns

Strategy: validation

Validate before calling

let sys_src = current_sys_sws();
let chain = [current_ic2_sel(), current_ic6_sel(), current_ic11_sel()];
assert!(!(sys_src == Syssws::Ic2 && chain.contains(&Icsel::from_bits(n as u8))),
        "switch sysclk off the IC2 chain before reconfiguring this PLL");

Prevention

When it happens

Trigger: is_new_pll_config detects a changed PLL n; sys_src == Syssws::Ic2 and ic2_src, ic6_src, or ic11_src equals Icsel::from_bits(n) — the PLL being torn down is part of the active sysclk chain.

Common situations: Runtime retuning of a PLL that feeds the sysclk via IC2/IC6/IC11; re-running init with tweaked PLL dividers on a live system; bootloaders re-entering clock init after switching to a PLL-derived sysclk.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

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

        // Return the new sys source
        RCC.cfgr().read().syssws()
    } else {
        sys_src
    };

    for (n, (&pll, out)) in pll_configs.iter().zip(pll_outputs.iter_mut()).enumerate() {
        debug!("configuring PLL{}", n + 1);
        let pll_ready = RCC.sr().read().pllrdy(n);

        if is_new_pll_config(pll, n) {
            let this_pll = Icsel::from_bits(n as u8);

            if cpu_src == Cpusws::Ic1 && ic1_src == this_pll {
                panic!("PLL should not be disabled / reconfigured if used for IC1 (cpuclksrc)")
            }

            if sys_src == Syssws::Ic2 && (ic2_src == this_pll || ic6_src == this_pll || ic11_src == this_pll) {
                panic!("PLL should not be disabled / reconfigured if used for IC2, IC6 or IC11 (sysclksrc)")
            }

            *out = pll.map_or_else(
                || {
                    disable_pll(n);
                    PllOutput::default()
                },
                |c| init_pll(Some(c), n, &pll_input),
            );
        } else if pll.is_some() {
            // Config matches current register state.
            *out = pll_output(pll, &pll_input);
            if !pll_ready {
                RCC.csr().write(|w| w.set_pllons(n, true));
                while !RCC.sr().read().pllrdy(n) {}
            }
        }
    }

View on GitHub (pinned to 463a07b963)