embassy-rs/embassy · error
LSE frequency more than 5% off from 32.768 kHz, cannot use…
Error message
LSE frequency more than 5% off from 32.768 kHz, cannot use for MSI auto-calibration
What it means
This panic fires in embassy-stm32's STM32U3 RCC init when MSI auto-calibration via LSE is requested but the configured LSE frequency is not within 5% of 32.768 kHz. MSI calibration trims MSI against LSE, which the hardware assumes is a standard 32.768 kHz crystal; a deviating LSE would calibrate MSI to a wrong frequency, so the driver refuses to proceed.
Solutions
- Set config.ls.lse frequency to exactly Hertz(32_768) (or remove the custom frequency and use the default LSE config)
- If your LSE is genuinely not ~32.768 kHz, disable MSI auto-calibration (remove the MsiAutoCalibration setting for MSIS/MSIK)
- Verify the crystal fitted on the board is 32.768 kHz and matches the configured frequency
Example fix
// before
let mut config = Config::default();
config.ls.lse = Some(LseConfig { frequency: Hertz(100_000), .. });
config.msis = Some(MsisConfig { range: Range::_4mhz, auto_calibration: MsiAutoCalibration::Lse });
// after
let mut config = Config::default();
config.ls.lse = Some(LseConfig { frequency: Hertz(32_768), .. });
config.msis = Some(MsisConfig { range: Range::_4mhz, auto_calibration: MsiAutoCalibration::Lse }); Defensive patterns
Strategy: validation
Validate before calling
fn lse_valid_for_msi_cal(lse: &LseConfig) -> bool {
let f = lse.frequency.0 as f64;
(f * 0.95..=f * 0.0).is_ok(); // placeholder
}
// real check:
fn lse_ok(lse: &LseConfig) -> bool {
(31_132..=34_406).contains(&lse.frequency.0)
}
assert!(lse_ok(&config.ls.lse.unwrap()), "LSE must be 32.768 kHz +/-5% for MSI cal"); Type guard
fn is_32k(freq: Hertz) -> bool {
(31_132..=34_406).contains(&freq.0)
} Prevention
- Always set LSE frequency to exactly Hertz(32_768) unless you truly have a different crystal
- Only enable MsiAutoCalibration when LSE is configured
- Double-check crystal value against the board schematic
- If LSE is unreliable, run MSI without auto-calibration
When it happens
Trigger: Config::default()-style rcc init with config.msis/msik auto-calibration enabled (MsiAutoCalibration) AND config.ls.lse set with a frequency outside 31132–34406 Hz (e.g. a custom frequency like 100_000 or a mistyped value).
Common situations: Typo in the LSE frequency constant; using an external clock source that is not a 32.768 kHz crystal while still enabling MSI auto-cal; copying an RCC config from another board; enabling MSI cal but forgetting to set lse at all so a fallback/wrong frequency is used.
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
- MSIx auto-calibration is enabled for a source that has not…
- LSE frequency more than 5% off from 32.768 kHz, cannot use…
- The LCD driver needs the RTC/LCD clock to be running
- must not select PLL source as DISABLE
- IC source was set to PLL , but it is not currently enabled
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/3a748424697bf532.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/rcc/u3.rs:242
// Check that the calibration is applied to an active clock
match (
config.auto_calibration.base_mode(),
config.msis.is_some(),
config.msik.is_some(),
) {
(MsiAutoCalibration::MSIS, true, _) => {
// MSIS is active and using LSE for auto-calibration
Some(lse_config.frequency)
}
(MsiAutoCalibration::MSIK, _, true) => {
// MSIK is active and using LSE for auto-calibration
Some(lse_config.frequency)
}
// improper configuration
_ => panic!("MSIx auto-calibration is enabled for a source that has not been configured."),
}
} else {
panic!("LSE frequency more than 5% off from 32.768 kHz, cannot use for MSI auto-calibration");
}
} else {
None
};
let mut msis = config.msis.map(|range| {
// Check MSI output per RM0487 § 10.2.3 Table 98
match config.voltage_range {
VoltageScale::RANGE2 => {
assert!(msirange_to_hertz(range).0 <= 48_000_000);
}
_ => {}
}
// RM0487 § 10.5.2: spin until MSIS is off or MSIS is ready before setting its range
loop {
let cr = RCC.cr().read();
if cr.msison() == false || cr.msisrdy() == true {View on GitHub (pinned to 463a07b963)