diff options
| author | Frank Stevenson <[email protected]> | 2025-06-17 14:27:37 +0200 |
|---|---|---|
| committer | Frank Stevenson <[email protected]> | 2025-06-17 14:27:37 +0200 |
| commit | 7fe4547ecb8a2838b26e6e0a902fbef3a4d22e52 (patch) | |
| tree | f455e3f78aeacf5a4eecdd75522e5a41633d44f7 /embassy-stm32 | |
| parent | 6186d111a5c150946ee5b7e9e68d987a38c1a463 (diff) | |
U5: Apply auto-calibration on MSIK and calculate frequencies for detuned LSE input
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/rcc/u5.rs | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 97eb2eb6d..7e5001499 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs | |||
| @@ -5,7 +5,7 @@ pub use crate::pac::rcc::vals::{ | |||
| 5 | Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, | 5 | Hpre as AHBPrescaler, Msirange, Msirange as MSIRange, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul, |
| 6 | Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, | 6 | Pllsrc as PllSource, Ppre as APBPrescaler, Sw as Sysclk, |
| 7 | }; | 7 | }; |
| 8 | use crate::pac::rcc::vals::{Hseext, Msirgsel, Pllmboost, Pllrge}; | 8 | use crate::pac::rcc::vals::{Hseext, Msipllsel, Msirgsel, Pllmboost, Pllrge}; |
| 9 | #[cfg(all(peri_usb_otg_hs))] | 9 | #[cfg(all(peri_usb_otg_hs))] |
| 10 | pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; | 10 | pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; |
| 11 | use crate::pac::{FLASH, PWR, RCC}; | 11 | use crate::pac::{FLASH, PWR, RCC}; |
| @@ -131,7 +131,18 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 131 | PWR.vosr().modify(|w| w.set_vos(config.voltage_range)); | 131 | PWR.vosr().modify(|w| w.set_vos(config.voltage_range)); |
| 132 | while !PWR.vosr().read().vosrdy() {} | 132 | while !PWR.vosr().read().vosrdy() {} |
| 133 | 133 | ||
| 134 | let msis = config.msis.map(|range| { | 134 | let lse_calibration_freq = match config.ls.lse { |
| 135 | Some(lse_config) => { | ||
| 136 | if lse_config.peripherals_clocked && (31_000..=34_000).contains(&lse_config.frequency.0) { | ||
| 137 | Some(lse_config.frequency) | ||
| 138 | } else { | ||
| 139 | None | ||
| 140 | } | ||
| 141 | } | ||
| 142 | _ => None, | ||
| 143 | }; | ||
| 144 | |||
| 145 | let mut msis = config.msis.map(|range| { | ||
| 135 | // Check MSI output per RM0456 § 11.4.10 | 146 | // Check MSI output per RM0456 § 11.4.10 |
| 136 | match config.voltage_range { | 147 | match config.voltage_range { |
| 137 | VoltageScale::RANGE4 => { | 148 | VoltageScale::RANGE4 => { |
| @@ -184,8 +195,25 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 184 | RCC.cr().modify(|w| { | 195 | RCC.cr().modify(|w| { |
| 185 | w.set_msikon(true); | 196 | w.set_msikon(true); |
| 186 | }); | 197 | }); |
| 198 | if lse_calibration_freq.is_some() { | ||
| 199 | // Enable the MSIK auto-calibration feature | ||
| 200 | RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK)); | ||
| 201 | RCC.cr().modify(|w| w.set_msipllen(true)); | ||
| 202 | } | ||
| 187 | while !RCC.cr().read().msikrdy() {} | 203 | while !RCC.cr().read().msikrdy() {} |
| 188 | msirange_to_hertz(range) | 204 | if let Some(freq) = lse_calibration_freq { |
| 205 | // Estimate frequency based on it being a fixed fractional multiple of LSE | ||
| 206 | let base = msirange_to_hertz(range).0; | ||
| 207 | let multiplier = (base + 8096) / 16384; | ||
| 208 | let msik_freq = Hertz(freq.0 * multiplier / 2); | ||
| 209 | if config.msis == config.msik { | ||
| 210 | // If MSIS and MSIK are the same range both will be auto calibrated to the same frequency | ||
| 211 | msis = Some(msik_freq) | ||
| 212 | } | ||
| 213 | msik_freq | ||
| 214 | } else { | ||
| 215 | msirange_to_hertz(range) | ||
| 216 | } | ||
| 189 | }); | 217 | }); |
| 190 | 218 | ||
| 191 | let hsi = config.hsi.then(|| { | 219 | let hsi = config.hsi.then(|| { |
