embassy-rs/embassy · error

Source must be equal across all enabled PLLs.

Error message

Source must be equal across all enabled PLLs.

What it means

On H7/H7RS the PLLSRC mux is a single shared register field feeding PLL1, PLL2 and PLL3, so all enabled PLLs must select the same source (HSE, HSI, or CSI). init checks this with all_equal and panics if two enabled PLLs disagree. Disabled PLLs (None) are ignored by the check.

Solutions

  1. Set the same PllSource on pll1, pll2 and pll3 (the ones that are Some) in the Config.
  2. Use prediv (DIVM) per-PLL to derive the reference frequencies you need from the single shared source.
  3. Verify with the clock tree that the shared source frequency supports all three PLL outputs.

Example fix

// before
let config = Config {
    pll1: Some(Pll { source: PllSource::HSE, ..Default::default() }),
    pll3: Some(Pll { source: PllSource::CSI, ..Default::default() }),
    ..Default::default()
};
// after
let config = Config {
    pll1: Some(Pll { source: PllSource::HSE, ..Default::default() }),
    pll3: Some(Pll { source: PllSource::HSE, ..Default::default() }),
    ..Default::default()
};
Defensive patterns

Strategy: validation

Validate before calling

let sources: Vec<_> = [config.pll1.as_ref(), config.pll2.as_ref(), config.pll3.as_ref()]
    .into_iter().flatten().map(|p| p.source).collect();
assert!(sources.windows(2).all(|w| w[0] == w[1]), "H7: all enabled PLLs must share one PLLSRC");

Prevention

When it happens

Trigger: Passing a Config in which, e.g., pll1 uses PllSource::HSE and pll2 or pll3 uses PllSource::HSI (or CSI) on stm32h7/stm32h7rs; any combination of two or more Some(pll) entries with differing .source values.

Common situations: Individually copying per-PLL configs from datasheets without noticing they share one source mux; migrating configs from L4/F4 (independent sources) to H7; enabling a second PLL for SAI/USB with a 'more convenient' different source.

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/a5290dcc170b2540. Report an issue: GitHub.

Appendix: source

Thrown at embassy-stm32/src/rcc/h.rs:538

    // Configure HSI48.
    let hsi48 = config.hsi48.map(super::init_hsi48);

    // Configure CSI.
    RCC.cr().modify(|w| w.set_csion(config.csi));
    let csi = match config.csi {
        false => None,
        true => {
            while !RCC.cr().read().csirdy() {}
            Some(CSI_FREQ)
        }
    };

    // H7 has shared PLLSRC, check it's equal in all PLLs.
    #[cfg(any(stm32h7, stm32h7rs))]
    {
        let plls = [&config.pll1, &config.pll2, &config.pll3];
        if !super::util::all_equal(plls.into_iter().flatten().map(|p| p.source)) {
            panic!("Source must be equal across all enabled PLLs.")
        };
    }

    // Configure PLLs.
    let pll_input = PllInput { csi, hse, hsi };
    disable_pll(0);
    let pll1 = config
        .pll1
        .map_or_else(PllOutput::default, |c| init_pll(0, c, &pll_input));
    disable_pll(1);
    let pll2 = config
        .pll2
        .map_or_else(PllOutput::default, |c| init_pll(1, c, &pll_input));
    #[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
    disable_pll(2);
    #[cfg(any(rcc_h5, stm32h7, stm32h7rs))]
    let pll3 = config
        .pll3

View on GitHub (pinned to 463a07b963)