embassy-rs/embassy · error
DSI lane byte clock
Error message
DSI lane byte clock
What it means
set_video_config converts the configured DSI lane byte clock (a stored Hertz-option) to a concrete value with to_hertz().expect(...). The expect fires when lane_byte_clock is None, i.e. the DSIHOST clock was never configured/enabled in the RCC setup before entering video mode. The register math needs a real frequency value.
Solutions
- Set the dsi_phy clock in the RCC config (e.g. from PLLDSI) before creating the DsiHost and starting the panel.
- Ensure the PLL feeding the DSI lane byte clock is enabled in the same rcc config.
- Verify ordering: clocks configured -> DsiHost::new -> start_panel; not start_panel with default/None clocks.
- Cross-check the clock setup against the embassy-stm32 DSI example for your chip family.
Example fix
// before
let config = Config::default();
// after
let mut config = Config::default();
config.rcc.pll3 = Some(Pll {
source: PllSource::HSE, ...
});
config.rcc.dsi_phy = Some(PllSel::Pll3); // provides lane_byte_clock Defensive patterns
Strategy: validation
Validate before calling
// Before start_panel, verify clocks are configured in RCC config: let cfg = Config::default(); assert!(cfg.rcc.dsi_phy.is_some(), "DSI lane byte clock must be set in RCC config");
Type guard
fn dsi_clocks_ready(freqs: &Frequencies) -> bool {
freqs.dsi_phy.to_hertz().is_ok()
} Prevention
- Always configure dsi_phy (PLLDSI) in the RCC config for DSI display projects.
- Follow the chip-specific embassy-stm32 DSI example clock block verbatim.
- Re-check RCC config after changing the target chip.
When it happens
Trigger: Calling start_panel/set_video_config while the RCC config lacks a dsi_phy/pll-derived lane byte clock, so Frequencies.dsi_phy is None; enabling DSIHOST kernel clock from a PLL not programmed in the same config.
Common situations: Forgetting `dsi_phy: Some(...)` in the RCC config for the DSI-capable part (STM32F469/STM32H747/STM32U5); copying an LTDC-only clock config and adding DSI later; changing PLL settings so the DSI clock line was dropped.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- DSI PHY clock must be enabled before init
- DSI TX escape clock
- AHB frequency is too low
- cannot select OTG_HS reference clock with source frequency…
- DTS PCLK frequency must be less than 127 MHz.
AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10).
Data as JSON: /api/errors/3b94e9585b1749a2.
Report an issue: GitHub.
Appendix: source
Thrown at embassy-stm32/src/dsihost/mode.rs:299
fn set_color<Panel: DsiPanel>(&mut self, color: DsiColor) {
T::regs().lcolcr().modify(|w| {
w.set_colc(color as u8);
w.set_lpe(match color {
DsiColor::Rgb666Config1 | DsiColor::Rgb666Config2 => Panel::LOOSELY_PACKED,
_ => false,
});
});
// Set color coding in DSI wrapper COLMUX
T::regs().wcfgr().modify(|w| {
w.set_colmux(color as u8);
});
}
/// Set video mode registers from a [`DsiVideoConfig`]
fn set_video_config<Panel: DsiPanel>(&mut self, config: &DsiVideoConfig) {
let lane_byte_clock = self.lane_byte_clock.to_hertz().expect("DSI lane byte clock");
let tx_escape_clock = self.tx_escape_clock.to_hertz().expect("DSI TX escape clock");
let ltdc_clock = LTDC::frequency();
T::regs().mcr().modify(|w| w.set_cmdm(false));
T::regs().wcfgr().modify(|w| w.set_dsim(false));
T::regs().vmcr().modify(|w| {
w.set_vmt(config.mode as u8);
w.set_lpvsae(config.lpvsa);
w.set_lpvbpe(config.lpvbp);
w.set_lpvfpe(config.lpvfp);
w.set_lpvae(config.lpva);
w.set_lphbpe(config.lphbp);
w.set_lphfpe(config.lphfp);
w.set_fbtaae(config.bta);
w.set_lpce(config.lpcmd);
});
View on GitHub (pinned to 463a07b963)