aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Stevenson <[email protected]>2025-07-24 13:26:10 +0200
committerFrank Stevenson <[email protected]>2025-07-24 13:26:10 +0200
commitfd3cdfcf251225fb333870f0341ae9ce416f54ad (patch)
tree446dc36650bdeddd5d69045a2db7a13e0b52d55b
parentcf9856255e1c2abf3ad2164ce669645f5da098c6 (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.rs54
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};
8use crate::pac::rcc::vals::{Hseext, Msipllsel, Msirgsel, Pllmboost, Pllrge}; 8use crate::pac::rcc::vals::{Hseext, Msipllfast, Msipllsel, Msirgsel, Pllmboost, Pllrge};
9#[cfg(all(peri_usb_otg_hs))] 9#[cfg(all(peri_usb_otg_hs))]
10pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG}; 10pub use crate::pac::{syscfg::vals::Usbrefcksel, SYSCFG};
11use crate::pac::{FLASH, PWR, RCC}; 11use 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
77impl MsiAutoCalibration { 81impl 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
83impl Default for MsiAutoCalibration { 101impl 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));