aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-10-23 01:48:09 +0200
committerDario Nieuwenhuis <[email protected]>2023-10-23 17:36:21 +0200
commita39ae12edcf23935df82d547fb2d997ca6b7c8d5 (patch)
treed13df6dec747ab5d3af23c7dac1b12c085b26cfd /embassy-stm32/src
parent0ef1cb29f70c71d3c85f5b8b4ad3c7ce60babba8 (diff)
stm32/rcc: misc cleanups.
Diffstat (limited to 'embassy-stm32/src')
-rw-r--r--embassy-stm32/src/rcc/f4f7.rs13
-rw-r--r--embassy-stm32/src/rcc/h.rs110
-rw-r--r--embassy-stm32/src/rcc/l0l1.rs30
-rw-r--r--embassy-stm32/src/rcc/l4l5.rs123
-rw-r--r--embassy-stm32/src/rcc/mod.rs30
5 files changed, 119 insertions, 187 deletions
diff --git a/embassy-stm32/src/rcc/f4f7.rs b/embassy-stm32/src/rcc/f4f7.rs
index 3f9a2be67..2e4f95722 100644
--- a/embassy-stm32/src/rcc/f4f7.rs
+++ b/embassy-stm32/src/rcc/f4f7.rs
@@ -166,8 +166,8 @@ pub(crate) unsafe fn init(config: Config) {
166 }; 166 };
167 167
168 let hclk = sys / config.ahb_pre; 168 let hclk = sys / config.ahb_pre;
169 let (pclk1, pclk1_tim) = calc_pclk(hclk, config.apb1_pre); 169 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
170 let (pclk2, pclk2_tim) = calc_pclk(hclk, config.apb2_pre); 170 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre);
171 171
172 assert!(max::SYSCLK.contains(&sys)); 172 assert!(max::SYSCLK.contains(&sys));
173 assert!(max::HCLK.contains(&hclk)); 173 assert!(max::HCLK.contains(&hclk));
@@ -326,15 +326,6 @@ fn flash_setup(clk: Hertz) {
326 while FLASH.acr().read().latency() != latency {} 326 while FLASH.acr().read().latency() != latency {}
327} 327}
328 328
329fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
330where
331 Hertz: core::ops::Div<D, Output = Hertz>,
332{
333 let pclk = hclk / ppre;
334 let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
335 (pclk, pclk_tim)
336}
337
338#[cfg(stm32f7)] 329#[cfg(stm32f7)]
339mod max { 330mod max {
340 use core::ops::RangeInclusive; 331 use core::ops::RangeInclusive;
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index 8883763ec..7e924f0ac 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -6,8 +6,11 @@ use crate::pac::pwr::vals::Vos;
6pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; 6pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
7#[cfg(stm32h7)] 7#[cfg(stm32h7)]
8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; 8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
9use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; 9pub use crate::pac::rcc::vals::{
10pub use crate::pac::rcc::vals::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul}; 10 Ckpersel as PerClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul,
11 Pllsrc as PllSource, Sw as Sysclk,
12};
13use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre};
11use crate::pac::{FLASH, PWR, RCC}; 14use crate::pac::{FLASH, PWR, RCC};
12use crate::rcc::{set_freqs, Clocks}; 15use crate::rcc::{set_freqs, Clocks};
13use crate::time::Hertz; 16use crate::time::Hertz;
@@ -58,41 +61,9 @@ pub struct Hse {
58 pub mode: HseMode, 61 pub mode: HseMode,
59} 62}
60 63
61#[derive(Clone, Copy, Eq, PartialEq)]
62pub enum Hsi {
63 /// 64Mhz
64 Mhz64,
65 /// 32Mhz (divided by 2)
66 Mhz32,
67 /// 16Mhz (divided by 4)
68 Mhz16,
69 /// 8Mhz (divided by 8)
70 Mhz8,
71}
72
73#[derive(Clone, Copy, Eq, PartialEq)]
74pub enum Sysclk {
75 /// HSI selected as sysclk
76 HSI,
77 /// HSE selected as sysclk
78 HSE,
79 /// CSI selected as sysclk
80 CSI,
81 /// PLL1_P selected as sysclk
82 Pll1P,
83}
84
85#[derive(Clone, Copy, Eq, PartialEq)]
86pub enum PllSource {
87 Hsi,
88 Csi,
89 Hse,
90}
91
92#[derive(Clone, Copy)] 64#[derive(Clone, Copy)]
93pub struct Pll { 65pub struct Pll {
94 /// Source clock selection. 66 /// Source clock selection.
95 #[cfg(stm32h5)]
96 pub source: PllSource, 67 pub source: PllSource,
97 68
98 /// PLL pre-divider (DIVM). 69 /// PLL pre-divider (DIVM).
@@ -152,15 +123,12 @@ impl From<TimerPrescaler> for Timpre {
152/// Configuration of the core clocks 123/// Configuration of the core clocks
153#[non_exhaustive] 124#[non_exhaustive]
154pub struct Config { 125pub struct Config {
155 pub hsi: Option<Hsi>, 126 pub hsi: Option<HSIPrescaler>,
156 pub hse: Option<Hse>, 127 pub hse: Option<Hse>,
157 pub csi: bool, 128 pub csi: bool,
158 pub hsi48: bool, 129 pub hsi48: bool,
159 pub sys: Sysclk, 130 pub sys: Sysclk,
160 131
161 #[cfg(stm32h7)]
162 pub pll_src: PllSource,
163
164 pub pll1: Option<Pll>, 132 pub pll1: Option<Pll>,
165 pub pll2: Option<Pll>, 133 pub pll2: Option<Pll>,
166 #[cfg(any(rcc_h5, stm32h7))] 134 #[cfg(any(rcc_h5, stm32h7))]
@@ -184,13 +152,11 @@ pub struct Config {
184impl Default for Config { 152impl Default for Config {
185 fn default() -> Self { 153 fn default() -> Self {
186 Self { 154 Self {
187 hsi: Some(Hsi::Mhz64), 155 hsi: Some(HSIPrescaler::DIV1),
188 hse: None, 156 hse: None,
189 csi: false, 157 csi: false,
190 hsi48: false, 158 hsi48: false,
191 sys: Sysclk::HSI, 159 sys: Sysclk::HSI,
192 #[cfg(stm32h7)]
193 pll_src: PllSource::Hsi,
194 pll1: None, 160 pll1: None,
195 pll2: None, 161 pll2: None,
196 #[cfg(any(rcc_h5, stm32h7))] 162 #[cfg(any(rcc_h5, stm32h7))]
@@ -303,19 +269,13 @@ pub(crate) unsafe fn init(config: Config) {
303 RCC.cr().modify(|w| w.set_hsion(false)); 269 RCC.cr().modify(|w| w.set_hsion(false));
304 None 270 None
305 } 271 }
306 Some(hsi) => { 272 Some(hsidiv) => {
307 let (freq, hsidiv) = match hsi {
308 Hsi::Mhz64 => (HSI_FREQ / 1u32, Hsidiv::DIV1),
309 Hsi::Mhz32 => (HSI_FREQ / 2u32, Hsidiv::DIV2),
310 Hsi::Mhz16 => (HSI_FREQ / 4u32, Hsidiv::DIV4),
311 Hsi::Mhz8 => (HSI_FREQ / 8u32, Hsidiv::DIV8),
312 };
313 RCC.cr().modify(|w| { 273 RCC.cr().modify(|w| {
314 w.set_hsidiv(hsidiv); 274 w.set_hsidiv(hsidiv);
315 w.set_hsion(true); 275 w.set_hsion(true);
316 }); 276 });
317 while !RCC.cr().read().hsirdy() {} 277 while !RCC.cr().read().hsirdy() {}
318 Some(freq) 278 Some(HSI_FREQ / hsidiv)
319 } 279 }
320 }; 280 };
321 281
@@ -360,25 +320,29 @@ pub(crate) unsafe fn init(config: Config) {
360 } 320 }
361 }; 321 };
362 322
323 // H7 has shared PLLSRC, check it's equal in all PLLs.
324 #[cfg(stm32h7)]
325 {
326 let plls = [&config.pll1, &config.pll2, &config.pll3];
327 if !super::util::all_equal(plls.into_iter().flatten().map(|p| p.source)) {
328 panic!("Source must be equal across all enabled PLLs.")
329 };
330 }
331
363 // Configure PLLs. 332 // Configure PLLs.
364 let pll_input = PllInput { 333 let pll_input = PllInput { csi, hse, hsi };
365 csi,
366 hse,
367 hsi,
368 #[cfg(stm32h7)]
369 source: config.pll_src,
370 };
371 let pll1 = init_pll(0, config.pll1, &pll_input); 334 let pll1 = init_pll(0, config.pll1, &pll_input);
372 let pll2 = init_pll(1, config.pll2, &pll_input); 335 let pll2 = init_pll(1, config.pll2, &pll_input);
373 #[cfg(any(rcc_h5, stm32h7))] 336 #[cfg(any(rcc_h5, stm32h7))]
374 let pll3 = init_pll(2, config.pll3, &pll_input); 337 let pll3 = init_pll(2, config.pll3, &pll_input);
375 338
376 // Configure sysclk 339 // Configure sysclk
377 let (sys, sw) = match config.sys { 340 let sys = match config.sys {
378 Sysclk::HSI => (unwrap!(hsi), Sw::HSI), 341 Sysclk::HSI => unwrap!(hsi),
379 Sysclk::HSE => (unwrap!(hse), Sw::HSE), 342 Sysclk::HSE => unwrap!(hse),
380 Sysclk::CSI => (unwrap!(csi), Sw::CSI), 343 Sysclk::CSI => unwrap!(csi),
381 Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1_P), 344 Sysclk::PLL1_P => unwrap!(pll1.p),
345 _ => unreachable!(),
382 }; 346 };
383 347
384 // Check limits. 348 // Check limits.
@@ -502,8 +466,8 @@ pub(crate) unsafe fn init(config: Config) {
502 466
503 RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into())); 467 RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into()));
504 468
505 RCC.cfgr().modify(|w| w.set_sw(sw)); 469 RCC.cfgr().modify(|w| w.set_sw(config.sys));
506 while RCC.cfgr().read().sws() != sw {} 470 while RCC.cfgr().read().sws() != config.sys {}
507 471
508 // IO compensation cell - Requires CSI clock and SYSCFG 472 // IO compensation cell - Requires CSI clock and SYSCFG
509 #[cfg(stm32h7)] // TODO h5 473 #[cfg(stm32h7)] // TODO h5
@@ -588,8 +552,6 @@ struct PllInput {
588 hsi: Option<Hertz>, 552 hsi: Option<Hertz>,
589 hse: Option<Hertz>, 553 hse: Option<Hertz>,
590 csi: Option<Hertz>, 554 csi: Option<Hertz>,
591 #[cfg(stm32h7)]
592 source: PllSource,
593} 555}
594 556
595struct PllOutput { 557struct PllOutput {
@@ -619,15 +581,11 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
619 }; 581 };
620 }; 582 };
621 583
622 #[cfg(stm32h5)] 584 let in_clk = match config.source {
623 let source = config.source; 585 PllSource::DISABLE => panic!("must not set PllSource::Disable"),
624 #[cfg(stm32h7)] 586 PllSource::HSI => unwrap!(input.hsi),
625 let source = input.source; 587 PllSource::HSE => unwrap!(input.hse),
626 588 PllSource::CSI => unwrap!(input.csi),
627 let (in_clk, src) = match source {
628 PllSource::Hsi => (unwrap!(input.hsi), Pllsrc::HSI),
629 PllSource::Hse => (unwrap!(input.hse), Pllsrc::HSE),
630 PllSource::Csi => (unwrap!(input.csi), Pllsrc::CSI),
631 }; 589 };
632 590
633 let ref_clk = in_clk / config.prediv as u32; 591 let ref_clk = in_clk / config.prediv as u32;
@@ -667,7 +625,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
667 625
668 #[cfg(stm32h5)] 626 #[cfg(stm32h5)]
669 RCC.pllcfgr(num).write(|w| { 627 RCC.pllcfgr(num).write(|w| {
670 w.set_pllsrc(src); 628 w.set_pllsrc(config.source);
671 w.set_divm(config.prediv); 629 w.set_divm(config.prediv);
672 w.set_pllvcosel(vco_range); 630 w.set_pllvcosel(vco_range);
673 w.set_pllrge(ref_range); 631 w.set_pllrge(ref_range);
@@ -681,7 +639,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
681 { 639 {
682 RCC.pllckselr().modify(|w| { 640 RCC.pllckselr().modify(|w| {
683 w.set_divm(num, config.prediv); 641 w.set_divm(num, config.prediv);
684 w.set_pllsrc(src); 642 w.set_pllsrc(config.source);
685 }); 643 });
686 RCC.pllcfgr().modify(|w| { 644 RCC.pllcfgr().modify(|w| {
687 w.set_pllvcosel(num, vco_range); 645 w.set_pllvcosel(num, vco_range);
diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs
index 52e9ccb3c..9fb2062d6 100644
--- a/embassy-stm32/src/rcc/l0l1.rs
+++ b/embassy-stm32/src/rcc/l0l1.rs
@@ -156,23 +156,9 @@ pub(crate) unsafe fn init(config: Config) {
156 w.set_ppre2(config.apb2_pre); 156 w.set_ppre2(config.apb2_pre);
157 }); 157 });
158 158
159 let ahb_freq = sys_clk / config.ahb_pre; 159 let hclk1 = sys_clk / config.ahb_pre;
160 160 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
161 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 161 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
162 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
163 pre => {
164 let freq = ahb_freq / pre;
165 (freq, freq * 2u32)
166 }
167 };
168
169 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
170 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
171 pre => {
172 let freq = ahb_freq / pre;
173 (freq, freq * 2u32)
174 }
175 };
176 162
177 #[cfg(crs)] 163 #[cfg(crs)]
178 if config.enable_hsi48 { 164 if config.enable_hsi48 {
@@ -209,11 +195,11 @@ pub(crate) unsafe fn init(config: Config) {
209 195
210 set_freqs(Clocks { 196 set_freqs(Clocks {
211 sys: sys_clk, 197 sys: sys_clk,
212 hclk1: ahb_freq, 198 hclk1,
213 pclk1: apb1_freq, 199 pclk1,
214 pclk2: apb2_freq, 200 pclk2,
215 pclk1_tim: apb1_tim_freq, 201 pclk1_tim,
216 pclk2_tim: apb2_tim_freq, 202 pclk2_tim,
217 rtc, 203 rtc,
218 }); 204 });
219} 205}
diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs
index 50128d389..2f89f6821 100644
--- a/embassy-stm32/src/rcc/l4l5.rs
+++ b/embassy-stm32/src/rcc/l4l5.rs
@@ -235,7 +235,7 @@ pub(crate) unsafe fn init(config: Config) {
235 235
236 // L4 has shared PLLSRC, PLLM, check it's equal in all PLLs. 236 // L4 has shared PLLSRC, PLLM, check it's equal in all PLLs.
237 #[cfg(all(stm32l4, not(rcc_l4plus)))] 237 #[cfg(all(stm32l4, not(rcc_l4plus)))]
238 match get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) { 238 match super::util::get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) {
239 Err(()) => panic!("Source must be equal across all enabled PLLs."), 239 Err(()) => panic!("Source must be equal across all enabled PLLs."),
240 Ok(None) => {} 240 Ok(None) => {}
241 Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| { 241 Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| {
@@ -246,7 +246,7 @@ pub(crate) unsafe fn init(config: Config) {
246 246
247 // L4+, WL has shared PLLSRC, check it's equal in all PLLs. 247 // L4+, WL has shared PLLSRC, check it's equal in all PLLs.
248 #[cfg(any(rcc_l4plus, stm32wl))] 248 #[cfg(any(rcc_l4plus, stm32wl))]
249 match get_equal(_plls.into_iter().flatten().map(|p| p.source)) { 249 match super::util::get_equal(_plls.into_iter().flatten().map(|p| p.source)) {
250 Err(()) => panic!("Source must be equal across all enabled PLLs."), 250 Err(()) => panic!("Source must be equal across all enabled PLLs."),
251 Ok(None) => {} 251 Ok(None) => {}
252 Ok(Some(source)) => RCC.pllcfgr().write(|w| { 252 Ok(Some(source)) => RCC.pllcfgr().write(|w| {
@@ -265,7 +265,7 @@ pub(crate) unsafe fn init(config: Config) {
265 ClockSrc::HSE => hse.unwrap(), 265 ClockSrc::HSE => hse.unwrap(),
266 ClockSrc::HSI => hsi.unwrap(), 266 ClockSrc::HSI => hsi.unwrap(),
267 ClockSrc::MSI => msi.unwrap(), 267 ClockSrc::MSI => msi.unwrap(),
268 ClockSrc::PLL1_R => pll._r.unwrap(), 268 ClockSrc::PLL1_R => pll.r.unwrap(),
269 }; 269 };
270 270
271 #[cfg(stm32l4)] 271 #[cfg(stm32l4)]
@@ -276,8 +276,8 @@ pub(crate) unsafe fn init(config: Config) {
276 let _clk48 = match config.clk48_src { 276 let _clk48 = match config.clk48_src {
277 Clk48Src::HSI48 => hsi48, 277 Clk48Src::HSI48 => hsi48,
278 Clk48Src::MSI => msi, 278 Clk48Src::MSI => msi,
279 Clk48Src::PLLSAI1_Q => pllsai1._q, 279 Clk48Src::PLLSAI1_Q => pllsai1.q,
280 Clk48Src::PLL1_Q => pll._q, 280 Clk48Src::PLL1_Q => pll.q,
281 }; 281 };
282 282
283 #[cfg(rcc_l4plus)] 283 #[cfg(rcc_l4plus)]
@@ -285,32 +285,21 @@ pub(crate) unsafe fn init(config: Config) {
285 #[cfg(all(stm32l4, not(rcc_l4plus)))] 285 #[cfg(all(stm32l4, not(rcc_l4plus)))]
286 assert!(sys_clk.0 <= 80_000_000); 286 assert!(sys_clk.0 <= 80_000_000);
287 287
288 let ahb_freq = sys_clk / config.ahb_pre; 288 let hclk1 = sys_clk / config.ahb_pre;
289 289 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
290 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 290 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
291 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 291 #[cfg(not(any(stm32wl5x, stm32wb)))]
292 pre => { 292 let hclk2 = hclk1;
293 let freq = ahb_freq / pre;
294 (freq, freq * 2u32)
295 }
296 };
297
298 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
299 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
300 pre => {
301 let freq = ahb_freq / pre;
302 (freq, freq * 2u32)
303 }
304 };
305
306 #[cfg(any(stm32wl5x, stm32wb))] 293 #[cfg(any(stm32wl5x, stm32wb))]
307 let _ahb2_freq = sys_clk / config.core2_ahb_pre; 294 let hclk2 = sys_clk / config.core2_ahb_pre;
295 #[cfg(not(any(stm32wl, stm32wb)))]
296 let hclk3 = hclk1;
308 #[cfg(any(stm32wl, stm32wb))] 297 #[cfg(any(stm32wl, stm32wb))]
309 let ahb3_freq = sys_clk / config.shared_ahb_pre; 298 let hclk3 = sys_clk / config.shared_ahb_pre;
310 299
311 // Set flash wait states 300 // Set flash wait states
312 #[cfg(stm32l4)] 301 #[cfg(stm32l4)]
313 let latency = match sys_clk.0 { 302 let latency = match hclk1.0 {
314 0..=16_000_000 => 0, 303 0..=16_000_000 => 0,
315 0..=32_000_000 => 1, 304 0..=32_000_000 => 1,
316 0..=48_000_000 => 2, 305 0..=48_000_000 => 2,
@@ -318,7 +307,7 @@ pub(crate) unsafe fn init(config: Config) {
318 _ => 4, 307 _ => 4,
319 }; 308 };
320 #[cfg(stm32l5)] 309 #[cfg(stm32l5)]
321 let latency = match sys_clk.0 { 310 let latency = match hclk1.0 {
322 // VCORE Range 0 (performance), others TODO 311 // VCORE Range 0 (performance), others TODO
323 0..=20_000_000 => 0, 312 0..=20_000_000 => 0,
324 0..=40_000_000 => 1, 313 0..=40_000_000 => 1,
@@ -328,14 +317,14 @@ pub(crate) unsafe fn init(config: Config) {
328 _ => 5, 317 _ => 5,
329 }; 318 };
330 #[cfg(stm32wl)] 319 #[cfg(stm32wl)]
331 let latency = match ahb3_freq.0 { 320 let latency = match hclk3.0 {
332 // VOS RANGE1, others TODO. 321 // VOS RANGE1, others TODO.
333 ..=18_000_000 => 0, 322 ..=18_000_000 => 0,
334 ..=36_000_000 => 1, 323 ..=36_000_000 => 1,
335 _ => 2, 324 _ => 2,
336 }; 325 };
337 #[cfg(stm32wb)] 326 #[cfg(stm32wb)]
338 let latency = match ahb3_freq.0 { 327 let latency = match hclk3.0 {
339 // VOS RANGE1, others TODO. 328 // VOS RANGE1, others TODO.
340 ..=18_000_000 => 0, 329 ..=18_000_000 => 0,
341 ..=36_000_000 => 1, 330 ..=36_000_000 => 1,
@@ -369,18 +358,15 @@ pub(crate) unsafe fn init(config: Config) {
369 358
370 set_freqs(Clocks { 359 set_freqs(Clocks {
371 sys: sys_clk, 360 sys: sys_clk,
372 hclk1: ahb_freq, 361 hclk1,
373 hclk2: ahb_freq, 362 hclk2,
374 #[cfg(not(stm32wl))] 363 hclk3,
375 hclk3: ahb_freq, 364 pclk1,
376 pclk1: apb1_freq, 365 pclk2,
377 pclk2: apb2_freq, 366 pclk1_tim,
378 pclk1_tim: apb1_tim_freq, 367 pclk2_tim,
379 pclk2_tim: apb2_tim_freq,
380 #[cfg(stm32wl)]
381 hclk3: ahb3_freq,
382 #[cfg(stm32wl)] 368 #[cfg(stm32wl)]
383 pclk3: ahb3_freq, 369 pclk3: hclk3,
384 #[cfg(rcc_l4)] 370 #[cfg(rcc_l4)]
385 hsi: None, 371 hsi: None,
386 #[cfg(rcc_l4)] 372 #[cfg(rcc_l4)]
@@ -419,26 +405,18 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz {
419 } 405 }
420} 406}
421 407
422#[allow(unused)]
423fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
424 let Some(x) = iter.next() else { return Ok(None) };
425 if !iter.all(|y| y == x) {
426 return Err(());
427 }
428 return Ok(Some(x));
429}
430
431struct PllInput { 408struct PllInput {
432 hsi: Option<Hertz>, 409 hsi: Option<Hertz>,
433 hse: Option<Hertz>, 410 hse: Option<Hertz>,
434 msi: Option<Hertz>, 411 msi: Option<Hertz>,
435} 412}
436 413
414#[allow(unused)]
437#[derive(Default)] 415#[derive(Default)]
438struct PllOutput { 416struct PllOutput {
439 _p: Option<Hertz>, 417 p: Option<Hertz>,
440 _q: Option<Hertz>, 418 q: Option<Hertz>,
441 _r: Option<Hertz>, 419 r: Option<Hertz>,
442} 420}
443 421
444#[derive(PartialEq, Eq, Clone, Copy)] 422#[derive(PartialEq, Eq, Clone, Copy)]
@@ -450,29 +428,33 @@ enum PllInstance {
450 Pllsai2, 428 Pllsai2,
451} 429}
452 430
453fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { 431fn pll_enable(instance: PllInstance, enabled: bool) {
454 // Disable PLL
455 match instance { 432 match instance {
456 PllInstance::Pll => { 433 PllInstance::Pll => {
457 RCC.cr().modify(|w| w.set_pllon(false)); 434 RCC.cr().modify(|w| w.set_pllon(enabled));
458 while RCC.cr().read().pllrdy() {} 435 while RCC.cr().read().pllrdy() != enabled {}
459 } 436 }
460 #[cfg(any(stm32l4, stm32l5, stm32wb))] 437 #[cfg(any(stm32l4, stm32l5, stm32wb))]
461 PllInstance::Pllsai1 => { 438 PllInstance::Pllsai1 => {
462 RCC.cr().modify(|w| w.set_pllsai1on(false)); 439 RCC.cr().modify(|w| w.set_pllsai1on(enabled));
463 while RCC.cr().read().pllsai1rdy() {} 440 while RCC.cr().read().pllsai1rdy() != enabled {}
464 } 441 }
465 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 442 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
466 PllInstance::Pllsai2 => { 443 PllInstance::Pllsai2 => {
467 RCC.cr().modify(|w| w.set_pllsai2on(false)); 444 RCC.cr().modify(|w| w.set_pllsai2on(enabled));
468 while RCC.cr().read().pllsai2rdy() {} 445 while RCC.cr().read().pllsai2rdy() != enabled {}
469 } 446 }
470 } 447 }
448}
449
450fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
451 // Disable PLL
452 pll_enable(instance, false);
471 453
472 let Some(pll) = config else { return PllOutput::default() }; 454 let Some(pll) = config else { return PllOutput::default() };
473 455
474 let pll_src = match pll.source { 456 let pll_src = match pll.source {
475 PLLSource::DISABLE => panic!("must not select PLL source as NONE"), 457 PLLSource::DISABLE => panic!("must not select PLL source as DISABLE"),
476 PLLSource::HSE => input.hse, 458 PLLSource::HSE => input.hse,
477 PLLSource::HSI => input.hsi, 459 PLLSource::HSI => input.hsi,
478 PLLSource::MSI => input.msi, 460 PLLSource::MSI => input.msi,
@@ -535,22 +517,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
535 } 517 }
536 518
537 // Enable PLL 519 // Enable PLL
538 match instance { 520 pll_enable(instance, true);
539 PllInstance::Pll => {
540 RCC.cr().modify(|w| w.set_pllon(true));
541 while !RCC.cr().read().pllrdy() {}
542 }
543 #[cfg(any(stm32l4, stm32l5, stm32wb))]
544 PllInstance::Pllsai1 => {
545 RCC.cr().modify(|w| w.set_pllsai1on(true));
546 while !RCC.cr().read().pllsai1rdy() {}
547 }
548 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
549 PllInstance::Pllsai2 => {
550 RCC.cr().modify(|w| w.set_pllsai2on(true));
551 while !RCC.cr().read().pllsai2rdy() {}
552 }
553 }
554 521
555 PllOutput { _p: p, _q: q, _r: r } 522 PllOutput { p, q, r }
556} 523}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 4f3d5b98b..8cf2d6ab0 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -246,3 +246,33 @@ pub(crate) mod sealed {
246} 246}
247 247
248pub trait RccPeripheral: sealed::RccPeripheral + 'static {} 248pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
249
250#[allow(unused)]
251mod util {
252 use crate::time::Hertz;
253
254 pub fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
255 where
256 Hertz: core::ops::Div<D, Output = Hertz>,
257 {
258 let pclk = hclk / ppre;
259 let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
260 (pclk, pclk_tim)
261 }
262
263 pub fn all_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> bool {
264 let Some(x) = iter.next() else { return true };
265 if !iter.all(|y| y == x) {
266 return false;
267 }
268 true
269 }
270
271 pub fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
272 let Some(x) = iter.next() else { return Ok(None) };
273 if !iter.all(|y| y == x) {
274 return Err(());
275 }
276 Ok(Some(x))
277 }
278}