diff options
| author | Frank Stevenson <[email protected]> | 2025-07-24 13:26:10 +0200 |
|---|---|---|
| committer | Frank Stevenson <[email protected]> | 2025-07-24 13:26:10 +0200 |
| commit | fd3cdfcf251225fb333870f0341ae9ce416f54ad (patch) | |
| tree | 446dc36650bdeddd5d69045a2db7a13e0b52d55b | |
| parent | cf9856255e1c2abf3ad2164ce669645f5da098c6 (diff) | |
Introduce configration options for Pll fast modes.
Ensure that the auto calibration is applied to an active clock.
| -rw-r--r-- | embassy-stm32/src/rcc/u5.rs | 54 |
1 files changed, 49 insertions, 5 deletions
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 0c7dc8ecc..ae0ef73f4 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, Msipllsel, Msirgsel, Pllmboost, Pllrge}; | 8 | use crate::pac::rcc::vals::{Hseext, Msipllfast, 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}; |
| @@ -72,12 +72,30 @@ pub enum MsiAutoCalibration { | |||
| 72 | MSIS, | 72 | MSIS, |
| 73 | /// MSIK is given priority for auto-calibration | 73 | /// MSIK is given priority for auto-calibration |
| 74 | MSIK, | 74 | MSIK, |
| 75 | /// MSIS with fast mode (always on) | ||
| 76 | MsisFast, | ||
| 77 | /// MSIK with fast mode (always on) | ||
| 78 | MsikFast, | ||
| 75 | } | 79 | } |
| 76 | 80 | ||
| 77 | impl MsiAutoCalibration { | 81 | impl MsiAutoCalibration { |
| 78 | const fn default() -> Self { | 82 | const fn default() -> Self { |
| 79 | MsiAutoCalibration::Disabled | 83 | MsiAutoCalibration::Disabled |
| 80 | } | 84 | } |
| 85 | |||
| 86 | fn base_mode(&self) -> Self { | ||
| 87 | match self { | ||
| 88 | MsiAutoCalibration::Disabled => MsiAutoCalibration::Disabled, | ||
| 89 | MsiAutoCalibration::MSIS => MsiAutoCalibration::MSIS, | ||
| 90 | MsiAutoCalibration::MSIK => MsiAutoCalibration::MSIK, | ||
| 91 | MsiAutoCalibration::MsisFast => MsiAutoCalibration::MSIS, | ||
| 92 | MsiAutoCalibration::MsikFast => MsiAutoCalibration::MSIK, | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | fn is_fast(&self) -> bool { | ||
| 97 | matches!(self, MsiAutoCalibration::MsisFast | MsiAutoCalibration::MsikFast) | ||
| 98 | } | ||
| 81 | } | 99 | } |
| 82 | 100 | ||
| 83 | impl Default for MsiAutoCalibration { | 101 | impl Default for MsiAutoCalibration { |
| @@ -159,7 +177,23 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 159 | Some(lse_config) => { | 177 | Some(lse_config) => { |
| 160 | // Allow +/- 5% tolerance for LSE frequency | 178 | // Allow +/- 5% tolerance for LSE frequency |
| 161 | if lse_config.peripherals_clocked && (31_100..=34_400).contains(&lse_config.frequency.0) { | 179 | if lse_config.peripherals_clocked && (31_100..=34_400).contains(&lse_config.frequency.0) { |
| 162 | Some(lse_config.frequency) | 180 | // Check that the calibration is applied to an active clock |
| 181 | match ( | ||
| 182 | config.auto_calibration.base_mode(), | ||
| 183 | config.msis.is_some(), | ||
| 184 | config.msik.is_some(), | ||
| 185 | ) { | ||
| 186 | (MsiAutoCalibration::MSIS, true, _) => { | ||
| 187 | // MSIS is active and using LSE for auto-calibration | ||
| 188 | Some(lse_config.frequency) | ||
| 189 | } | ||
| 190 | (MsiAutoCalibration::MSIK, _, true) => { | ||
| 191 | // MSIK is active and using LSE for auto-calibration | ||
| 192 | Some(lse_config.frequency) | ||
| 193 | } | ||
| 194 | // improper configuration, no LSE calibration | ||
| 195 | _ => None, | ||
| 196 | } | ||
| 163 | } else { | 197 | } else { |
| 164 | None | 198 | None |
| 165 | } | 199 | } |
| @@ -192,7 +226,9 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 192 | w.set_msipllen(false); | 226 | w.set_msipllen(false); |
| 193 | w.set_msison(true); | 227 | w.set_msison(true); |
| 194 | }); | 228 | }); |
| 195 | let msis = if let (Some(freq), MsiAutoCalibration::MSIS) = (lse_calibration_freq, config.auto_calibration) { | 229 | let msis = if let (Some(freq), MsiAutoCalibration::MSIS) = |
| 230 | (lse_calibration_freq, config.auto_calibration.base_mode()) | ||
| 231 | { | ||
| 196 | // Enable the MSIS auto-calibration feature | 232 | // Enable the MSIS auto-calibration feature |
| 197 | RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIS)); | 233 | RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIS)); |
| 198 | RCC.cr().modify(|w| w.set_msipllen(true)); | 234 | RCC.cr().modify(|w| w.set_msipllen(true)); |
| @@ -228,7 +264,9 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 228 | RCC.cr().modify(|w| { | 264 | RCC.cr().modify(|w| { |
| 229 | w.set_msikon(true); | 265 | w.set_msikon(true); |
| 230 | }); | 266 | }); |
| 231 | let msik = if let (Some(freq), MsiAutoCalibration::MSIK) = (lse_calibration_freq, config.auto_calibration) { | 267 | let msik = if let (Some(freq), MsiAutoCalibration::MSIK) = |
| 268 | (lse_calibration_freq, config.auto_calibration.base_mode()) | ||
| 269 | { | ||
| 232 | // Enable the MSIK auto-calibration feature | 270 | // Enable the MSIK auto-calibration feature |
| 233 | RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK)); | 271 | RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK)); |
| 234 | RCC.cr().modify(|w| w.set_msipllen(true)); | 272 | RCC.cr().modify(|w| w.set_msipllen(true)); |
| @@ -242,10 +280,16 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 242 | 280 | ||
| 243 | // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source. | 281 | // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source. |
| 244 | if let Some(lse_freq) = lse_calibration_freq { | 282 | if let Some(lse_freq) = lse_calibration_freq { |
| 283 | // Check if Fast mode should be used | ||
| 284 | if config.auto_calibration.is_fast() { | ||
| 285 | RCC.cr().modify(|w| { | ||
| 286 | w.set_msipllfast(Msipllfast::FAST); | ||
| 287 | }); | ||
| 288 | } | ||
| 245 | if let (Some(msis_range), Some(msik_range)) = (config.msis, config.msik) { | 289 | if let (Some(msis_range), Some(msik_range)) = (config.msis, config.msik) { |
| 246 | if (msis_range as u8 >> 2) == (msik_range as u8 >> 2) { | 290 | if (msis_range as u8 >> 2) == (msik_range as u8 >> 2) { |
| 247 | // Clock source is shared, both will be auto calibrated. | 291 | // Clock source is shared, both will be auto calibrated. |
| 248 | match config.auto_calibration { | 292 | match config.auto_calibration.base_mode() { |
| 249 | MsiAutoCalibration::MSIS => { | 293 | MsiAutoCalibration::MSIS => { |
| 250 | // MSIS and MSIK are using the same clock source, recalibrate | 294 | // MSIS and MSIK are using the same clock source, recalibrate |
| 251 | msik = Some(calculate_calibrated_msi_frequency(msik_range, lse_freq)); | 295 | msik = Some(calculate_calibrated_msi_frequency(msik_range, lse_freq)); |
