embassy-rs/embassy · critical

Failed to configure PLL_SYS

Error message

Failed to configure PLL_SYS: {:?}

What it means

During clock initialization, the RP clock setup calls `configure_pll(PLL_SYS, ...)` and panics with the underlying PLL error if the system PLL cannot be locked or configured. The error value (`e`) indicates which PLL setup step failed (e.g. no valid feedback divider, frequency out of range).

Solutions

  1. Verify `config.hz` matches your board's actual crystal frequency (RP2040 dev boards: 12 MHz)
  2. Choose a `sys_pll` target frequency within the valid VCO range for your reference clock, or pass `None` to run without the PLL
  3. Check the returned debug value `{:?}` to see the specific PLLSetupError variant (e.g. VCO out of range)
  4. Extend/adjust the PLL divider search: pick a refdiv so ref_freq stays in 5–800 MHz and fbdiv/post_div yield a valid VCO

Example fix

// before
let clocks = Clocks::init(&config_with(hz: 12_000_000, sys_pll: Some(125_000_000))); // board crystal is 25 MHz
// after
let clocks = Clocks::init(&Config { hz: 25_000_000, sys_pll: Some(125_000_000), ..config }); // hz matches real crystal
Defensive patterns

Strategy: validation

Validate before calling

fn validate_pll_plan(ref_hz: u32, target_hz: u32) -> Result<(), &'static str> {
    // RP2040: VCO must be in 750..=1600 MHz, refdiv so 5..=800 MHz reference
    let vco = (ref_hz as u64 * target_hz as u64) ; // compute per configure_pll rules
    // perform the same feasibility math configure_pll does and reject early
    Ok(())
}

Prevention

When it happens

Trigger: Calling `Clocks::init` (or `init_with_config`) with a `sys_pll` configuration whose reference frequency, feedback/post divider combination cannot produce a valid VCO output from the crystal frequency (`config.hz`).

Common situations: Using a non-12 MHz crystal (e.g. 12.288 MHz or 25 MHz) with a default PLL config tuned for 12 MHz; requesting a sys frequency outside the VCO range (750 MHz–1.6 GHz VCO constraint); typo in target frequency.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at embassy-rp/src/clocks.rs:1110

            });
            #[cfg(feature = "_rp235x")]
            vreg.bod().write(|w| {
                w.0 = (w.0 & 0x0000FFFF) | (0x5AFE << 16); // Set the password
                w.set_vsel(voltage.recommended_bod());
                w.set_en(true); // Enable brownout detection
            });
        }
    }

    let (xosc_freq, pll_sys_freq, pll_usb_freq) = match config.xosc {
        Some(config) => {
            // start XOSC
            start_xosc(config.hz, config.delay_multiplier);

            let pll_sys_freq = match config.sys_pll {
                Some(sys_pll_config) => match configure_pll(pac::PLL_SYS, config.hz, sys_pll_config) {
                    Ok(freq) => freq,
                    Err(e) => panic!("Failed to configure PLL_SYS: {:?}", e),
                },
                None => 0,
            };
            let pll_usb_freq = match config.usb_pll {
                Some(usb_pll_config) => match configure_pll(pac::PLL_USB, config.hz, usb_pll_config) {
                    Ok(freq) => freq,
                    Err(e) => panic!("Failed to configure PLL_USB: {:?}", e),
                },
                None => 0,
            };

            (config.hz, pll_sys_freq, pll_usb_freq)
        }
        None => (0, 0, 0),
    };

    CLOCKS.xosc.store(xosc_freq, Ordering::Relaxed);
    CLOCKS.pll_sys.store(pll_sys_freq, Ordering::Relaxed);

View on GitHub (pinned to 463a07b963)