{"record":{"id":"c4feee52054578f1","repo":"embassy-rs/embassy","slug":"dsi-phy-clock-must-be-enabled-before-init","errorCode":null,"errorMessage":"DSI PHY clock must be enabled before init","messagePattern":"DSI PHY clock must be enabled before init","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"embassy-stm32/src/dsihost/phy.rs","lineNumber":124,"sourceCode":"        });\n\n        T::regs().pconfr().modify(|w| {\n            w.set_nl(config.lanes as u8);\n            w.set_sw_time(config.stop_wait_time);\n        });\n\n        T::regs().ccr().modify(|w| {\n            w.set_tockdiv(timeout_div);\n            w.set_txeckdiv(escape_div);\n        });\n\n        #[cfg(dsihost_v1)]\n        {\n            let clocks = unsafe { get_freqs() };\n            let phy_clock = clocks\n                .dsi_phy\n                .to_hertz()\n                .expect(\"DSI PHY clock must be enabled before init\");\n\n            // Calculate UIX4\n            let uix4 = (4_000_000_000u64) / phy_clock.0 as u64;\n            let uix4 = uix4.max(1).min(63) as u8;\n            T::regs().wpcr0().modify(|w| {\n                w.set_uix4(uix4);\n            });\n        }\n\n        T::regs().pcr().modify(|w| {\n            w.set_crcrxe(config.crc_rx);\n            w.set_eccrxe(config.ecc_rx);\n            w.set_etrxe(config.eotp_rx);\n            w.set_ettxe(config.eotp_tx);\n            w.set_btae(config.bta);\n        });\n\n        T::regs().cltcr().modify(|w| {","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/embassy-rs/embassy/blob/463a07b963419a1bfe61d5d597c44acb810afb8b/embassy-stm32/src/dsihost/phy.rs#L106-L142","documentation":"phy_init for dsihost_v1 reads the RCC Frequencies and converts clocks.dsi_phy to Hertz with an expect. The panic asserts the DSI PHY clock was programmed and enabled before the PHY is initialized (needed to compute the UIX4 timing value). Without it the PHY timing registers cannot be set correctly.","triggerScenarios":"Calling start_panel (which calls phy_init) when the RCC config has no dsi_phy clock set; enabling DSIHOST peripheral clock but not the DSI PHY clock source (PLLDSI); running phy_init before RCC init commits frequencies.","commonSituations":"STM32F469/DSI projects where only DSIHOST kernel clock was configured; switching chip families (F4 -> H7/U5) where the clock field name/PLL changed; order-of-init mistakes where panel start happens before set-up of PLLDSI.","solutions":["Add `rcc.dsi_phy = Some(PllSel::PllN)` (and configure that PLL) in the RCC config before starting the panel.","Enable the PLL that feeds the DSI PHY (PLLDSI) and check it appears in the computed Frequencies.","Ensure start_panel is called after Rcc::new/config application, not before.","Compare with the embassy-stm32 dsihost example for your exact chip."],"exampleFix":"// before\nconfig.rcc.dsihost = Some(...) // only kernel clock\n\n// after\nconfig.rcc.pll3 = Some(Pll { source: PllSource::HSE, ... });\nconfig.rcc.dsi_phy = Some(PllSel::Pll3); // PHY clock must be set\nconfig.rcc.dsihost = Some(...);","handlingStrategy":"validation","validationCode":"// Guard before starting the panel:\n// RCC config must include the DSI PHY clock\nlet mut config = Config::default();\nconfig.rcc.pll3 = Some(Pll { .. });\nconfig.rcc.dsi_phy = Some(PllSel::Pll3);\n// then: Rcc::new, DsiHost::new, start_panel","typeGuard":"fn phy_clock_enabled(freqs: &Frequencies) -> bool {\n    freqs.dsi_phy.to_hertz().is_ok()\n}","tryCatchPattern":null,"preventionTips":["Enable the DSI PHY PLL (PLLDSI) plus the DSIHOST kernel clock in RCC.","Call start_panel only after full RCC initialization.","Diff your clock config against the official example when changing chips."],"tags":["embedded","stm32","dsi","display","clock-config"],"backgroundTag":"missing-required-config-field","analyzedSha":"463a07b963419a1bfe61d5d597c44acb810afb8b","analyzedAt":"2026-09-10T13:38:26.660Z","contentChangedAt":"2026-09-10T13:38:26.660Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}