embassy-rs/embassy · error
Lcd clock error
Error message
Lcd clock error
What it means
After scanning prescaler (PS) and divider values, the driver could not find a combination that brings the LCD clock into the target frame-rate range: either no match was found (best_fps_match == u32::MAX) or the required prescaler exceeds the 4-bit field (>0xF). The requested frame rate is unreachable from the given RTC clock, so the driver panics.
Solutions
- Lower the requested fps (or widen the fps range) in the LcdConfig so a valid PS/div exists.
- Change the RTC/LCD clock source or frequency so the target fps is reachable within PS<=0xF and div<=3.
- Keep the RTC clock near 32.768 kHz, the frequency the LCD timing math is designed around.
Example fix
// before let config = LcdConfig::default().fps(120); // unreachable with 32.768 kHz LSE // after let config = LcdConfig::default().fps(30); // reachable PS/div combination
Defensive patterns
Strategy: validation
Validate before calling
// sanity-check the target fps against a 32.768 kHz LCD clock before Lcd::new
fn fps_reachable(rtc_hz: u32, fps: u32, duty_div: u32) -> bool {
// max division is ps(0xF -> 2^16) * div(3) * duty; fps * divs must stay under rtc_hz
fps * duty_div * (1 << 16) * 3 >= rtc_hz / 4 && fps <= rtc_hz / (duty_div * 2)
} Prevention
- Keep the LCD clock near 32.768 kHz; use LSE for the RTC/LCD domain.
- Choose fps values in the range typical for segment LCDs (30-60 Hz).
- Verify the duty setting matches the panel; changing duty shifts the divider math.
When it happens
Trigger: Calling Lcd::new() with a config whose target fps is impossible for the configured rtc clock and duty divider; an RTC clock so high or low that even PS=0xF/div=15 cannot hit the fps window.
Common situations: Unusual LSE/LSI frequencies combined with aggressive fps targets in the config; copying a config from another board with a different RTC clock; duty setting change (e.g. Duty::Quarter) shifting the divider math out of range.
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
- The LCD driver needs the RTC/LCD clock to be running
- Maximal allowed frequency for ADC4 is
- Maximal allowed frequency for the ADC is
- Maximal allowed frequency for the ADC is
- Selected PCLK2 frequency is too high for ADC with largest…
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/1c1520f4a8e5c458.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/lcd.rs:242
continue;
}
if fps < best_fps_match {
ps = trial_ps;
div = trial_div;
best_fps_match = fps;
}
}
let ck_div = lcd_clk.0 / ((1 << ps) * (div + 16));
trace!(
"lcd_clk: {}, fps: {}, ps: {}, div: {}, ck_div: {}",
lcd_clk, best_fps_match, ps, div, ck_div
);
if best_fps_match == u32::MAX || ps > 0xF {
panic!("Lcd clock error");
}
// Set the frame control
T::regs().fcr().modify(|w| {
w.set_ps(ps as u8);
w.set_div(div as u8);
w.set_cc(0b100); // Init in the middle-ish
w.set_dead(0b000);
w.set_pon(config.drive as u8 & 0x07);
w.set_hd((config.drive as u8 & !0x07) != 0);
});
// Wait for the frame control to synchronize
while !T::regs().sr().read().fcrsf() {}
// Set the control register values
T::regs().cr().modify(|w| {
#[cfg(lcd_v2)]View on GitHub (pinned to 463a07b963)