embassy-rs/embassy · critical
Failed to configure PLL_USB
Error message
Failed to configure PLL_USB: {:?} What it means
Same failure path as PLL_SYS but for the USB PLL: `configure_pll(PLL_USB, ...)` returned an error during clock init and the driver panics with the PLL error attached. The USB PLL must produce a 48 MHz clock for USB operation, and invalid divider settings from the crystal reference cause setup failure.
Solutions
- Confirm `config.hz` equals the actual crystal frequency on the board
- Use the default usb_pll config (targets 48 MHz) rather than a hand-computed value
- Read the `{:?}` error payload to identify whether VCO or post-divider selection failed
- Set `usb_pll: None` only if you do not need USB and have an alternate 48 MHz source
Example fix
// before usb_pll: Some(96_000_000) // cannot post-divide to required USB clock from this ref // after usb_pll: Some(48_000_000) // standard USB PLL target from the default config
Defensive patterns
Strategy: validation
Validate before calling
fn validate_usb_pll(ref_hz: u32) -> Result<(), &'static str> {
// USB PLL must produce exactly 48 MHz after refdiv/fbdiv/postdiv
if ref_hz != 12_000_000 && ref_hz != 12_288_000 && ref_hz != 25_000_000 {
return Err("unsupported crystal for default USB PLL plan");
}
Ok(())
}
Prevention
- Prefer the default USB PLL configuration targeting 48 MHz
- Verify crystal frequency against the schematic for custom boards
- Only override usb_pll with verified divider math
When it happens
Trigger: Calling clock init with a `usb_pll: Some(config)` whose frequency plan cannot be derived from `config.hz` (crystal frequency mismatch or invalid VCO/divider combination).
Common situations: Board crystal differs from the assumed 12 MHz; board code passing a custom usb_pll value that cannot hit exactly 48 MHz after post-dividers; clone/custom hardware with an unusual oscillator.
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
- Failed to configure PLL_SYS
- timer must be stopped before setting counter
- DMA: error on DMA_0 channel
- InterruptExecutor::start() called multiple times on the…
- InterruptExecutor::spawner() called on uninitialized…
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/49c6f2265600e6ae.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-rp/src/clocks.rs:1117
}
}
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);
CLOCKS.pll_usb.store(pll_usb_freq, Ordering::Relaxed);
let (ref_src, ref_aux, clk_ref_freq) = {
use ClkRefCtrlAuxsrc as Aux;
use ClkRefCtrlSrc as Src;
let div = config.ref_clk.div as u32;
assert!(div >= 1 && div <= 4);View on GitHub (pinned to 463a07b963)