embassy-rs/embassy · error

The LCD driver needs the RTC/LCD clock to be running

Error message

The LCD driver needs the RTC/LCD clock to be running

What it means

The LCD controller is clocked from the RTC/LCD clock domain. During driver construction the code reads the currently configured RTC frequency via rcc::get_freqs(); if it is None the driver cannot compute the prescaler/divider, so it panics instead of producing garbage timing.

Solutions

  1. Enable and configure the RTC/LCD clock source (LSE, LSI or HSE/32) in the RCC config before constructing the LCD driver.
  2. Verify rcc::get_freqs().rtc is Some(hz) after your clock setup, then create the Lcd driver.
  3. If LSE is used, account for its startup delay before initializing the LCD.

Example fix

// before
let mut lcd = Lcd::new(p.LCD, p.RTC, config); // rtc clock not configured
// after
let rtc = Rtc::new(p.RTC, RtcConfig::default()); // starts LSE/RTC clock
let mut lcd = Lcd::new(p.LCD, p.RTC, config);
Defensive patterns

Strategy: validation

Validate before calling

// assert RTC clock is configured before LCD init
let freqs = embassy_stm32::rcc::get_freqs();
assert!(freqs.rtc.to_hertz().is_some(), "RTC/LCD clock must run before Lcd::new");

Try / catch

// Not catchable in idiomatic embedded Rust; ensure init order:
let rtc = Rtc::new(p.RTC, RtcConfig::default());
let lcd = Lcd::new(p.LCD, p.RTC, config);

Prevention

When it happens

Trigger: Instantiating Lcd::new() before the RTC peripheral (and its LCD clock source, e.g. LSE/LSI) has been enabled and configured in the RCC setup.

Common situations: Forgetting to call the rtc enable/config step in the board init; RCC config that selects no RTC clock source; running LCD init code before clock configuration on boards where LSE startup is deferred.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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

Appendix: source

Thrown at embassy-stm32/src/lcd.rs:201

        );

        // Set the pins
        for pin in pins.iter_mut() {
            pin.pin.pin.set_as_af(
                pin.af_num,
                AfType::output(crate::gpio::OutputType::PushPull, crate::gpio::Speed::VeryHigh),
            );
        }

        // Initialize the display ram to 0
        for i in 0..8 {
            T::regs().ram_com(i).low().write_value(0);
            T::regs().ram_com(i).high().write_value(0);
        }

        // Calculate the clock dividers
        let Some(lcd_clk) = (unsafe { rcc::get_freqs().rtc.to_hertz() }) else {
            panic!("The LCD driver needs the RTC/LCD clock to be running");
        };
        let duty_divider = match config.duty {
            Duty::Static => 1,
            Duty::Half => 2,
            Duty::Third => 3,
            Duty::Quarter => 4,
            Duty::Eigth => 8,
        };
        let target_clock = config.target_fps.0 * duty_divider;
        let target_division = lcd_clk.0 / target_clock;

        let mut ps = 0;
        let mut div = 0;
        let mut best_fps_match = u32::MAX;

        for trial_div in 0..0xF {
            let trial_ps = (target_division / (trial_div + 16))
                .next_power_of_two()

View on GitHub (pinned to 463a07b963)