aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-01-04 19:25:50 +0100
committerDario Nieuwenhuis <[email protected]>2022-01-04 19:28:15 +0100
commitb06e705a737a7b1d040ab415b4e7ecc71cd79094 (patch)
tree8c4ff244645f561cee4db194253613de949fcdef
parentb2a85ee519067d3290e328f9ad047184ff033cd7 (diff)
stm32/rcc: change family-specific code from dirs to single files.
Consistent with how other peripherals handle their versions.
-rw-r--r--embassy-stm32/src/rcc/f0.rs (renamed from embassy-stm32/src/rcc/f0/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/f1.rs (renamed from embassy-stm32/src/rcc/f1/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/f3.rs (renamed from embassy-stm32/src/rcc/f3/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/f4.rs (renamed from embassy-stm32/src/rcc/f4/mod.rs)37
-rw-r--r--embassy-stm32/src/rcc/f4/max.rs21
-rw-r--r--embassy-stm32/src/rcc/f7.rs (renamed from embassy-stm32/src/rcc/f7/mod.rs)26
-rw-r--r--embassy-stm32/src/rcc/f7/max.rs19
-rw-r--r--embassy-stm32/src/rcc/g0.rs (renamed from embassy-stm32/src/rcc/g0/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/g4.rs (renamed from embassy-stm32/src/rcc/g4/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/h7.rs (renamed from embassy-stm32/src/rcc/h7/mod.rs)158
-rw-r--r--embassy-stm32/src/rcc/h7/pll.rs145
-rw-r--r--embassy-stm32/src/rcc/l0.rs (renamed from embassy-stm32/src/rcc/l0/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/l1.rs (renamed from embassy-stm32/src/rcc/l1/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/l4.rs (renamed from embassy-stm32/src/rcc/l4/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/mod.rs67
-rw-r--r--embassy-stm32/src/rcc/u5.rs (renamed from embassy-stm32/src/rcc/u5/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/wb.rs (renamed from embassy-stm32/src/rcc/wb/mod.rs)2
-rw-r--r--embassy-stm32/src/rcc/wl5.rs (renamed from embassy-stm32/src/rcc/wl5x/mod.rs)2
18 files changed, 234 insertions, 261 deletions
diff --git a/embassy-stm32/src/rcc/f0/mod.rs b/embassy-stm32/src/rcc/f0.rs
index 916ed39fc..07a28cc3e 100644
--- a/embassy-stm32/src/rcc/f0/mod.rs
+++ b/embassy-stm32/src/rcc/f0.rs
@@ -201,7 +201,7 @@ impl<'d> Rcc<'d> {
201 } 201 }
202} 202}
203 203
204pub unsafe fn init(config: Config) { 204pub(crate) unsafe fn init(config: Config) {
205 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); 205 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config);
206 let clocks = rcc.freeze(); 206 let clocks = rcc.freeze();
207 set_freqs(clocks); 207 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/f1/mod.rs b/embassy-stm32/src/rcc/f1.rs
index d613f5a2f..c9d09ee33 100644
--- a/embassy-stm32/src/rcc/f1/mod.rs
+++ b/embassy-stm32/src/rcc/f1.rs
@@ -207,7 +207,7 @@ impl<'d> Rcc<'d> {
207 } 207 }
208} 208}
209 209
210pub unsafe fn init(config: Config) { 210pub(crate) unsafe fn init(config: Config) {
211 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); 211 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config);
212 let clocks = rcc.freeze(); 212 let clocks = rcc.freeze();
213 set_freqs(clocks); 213 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/f3/mod.rs b/embassy-stm32/src/rcc/f3.rs
index ab1bd7607..7b5e0cce7 100644
--- a/embassy-stm32/src/rcc/f3/mod.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -54,7 +54,7 @@ struct PllConfig {
54} 54}
55 55
56/// Initialize and Set the clock frequencies 56/// Initialize and Set the clock frequencies
57pub unsafe fn init(config: Config) { 57pub(crate) unsafe fn init(config: Config) {
58 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 58 let r = <peripherals::RCC as embassy::util::Steal>::steal();
59 let clocks = Rcc::new(r, config).freeze(); 59 let clocks = Rcc::new(r, config).freeze();
60 set_freqs(clocks); 60 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/f4/mod.rs b/embassy-stm32/src/rcc/f4.rs
index 04083dfa1..08a9bc9b4 100644
--- a/embassy-stm32/src/rcc/f4/mod.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -5,9 +5,6 @@ use crate::time::Hertz;
5use core::marker::PhantomData; 5use core::marker::PhantomData;
6use embassy::util::Unborrow; 6use embassy::util::Unborrow;
7 7
8mod max;
9use max::{PCLK1_MAX, PCLK2_MAX};
10
11const HSI: u32 = 16_000_000; 8const HSI: u32 = 16_000_000;
12 9
13/// Clocks configutation 10/// Clocks configutation
@@ -88,7 +85,7 @@ impl<'d> Rcc<'d> {
88 .config 85 .config
89 .pclk1 86 .pclk1
90 .map(|p| p.0) 87 .map(|p| p.0)
91 .unwrap_or_else(|| core::cmp::min(PCLK1_MAX, hclk)); 88 .unwrap_or_else(|| core::cmp::min(max::PCLK1_MAX, hclk));
92 let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 { 89 let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 {
93 0 => unreachable!(), 90 0 => unreachable!(),
94 1 => (0b000, 1), 91 1 => (0b000, 1),
@@ -101,13 +98,13 @@ impl<'d> Rcc<'d> {
101 98
102 // Calculate real APB1 clock 99 // Calculate real APB1 clock
103 let pclk1 = hclk / ppre1; 100 let pclk1 = hclk / ppre1;
104 assert!(pclk1 <= PCLK1_MAX); 101 assert!(pclk1 <= max::PCLK1_MAX);
105 102
106 let pclk2 = self 103 let pclk2 = self
107 .config 104 .config
108 .pclk2 105 .pclk2
109 .map(|p| p.0) 106 .map(|p| p.0)
110 .unwrap_or_else(|| core::cmp::min(PCLK2_MAX, hclk)); 107 .unwrap_or_else(|| core::cmp::min(max::PCLK2_MAX, hclk));
111 let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 { 108 let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 {
112 0 => unreachable!(), 109 0 => unreachable!(),
113 1 => (0b000, 1), 110 1 => (0b000, 1),
@@ -120,7 +117,7 @@ impl<'d> Rcc<'d> {
120 117
121 // Calculate real APB2 clock 118 // Calculate real APB2 clock
122 let pclk2 = hclk / ppre2; 119 let pclk2 = hclk / ppre2;
123 assert!(pclk2 <= PCLK2_MAX); 120 assert!(pclk2 <= max::PCLK2_MAX);
124 121
125 Self::flash_setup(sysclk); 122 Self::flash_setup(sysclk);
126 123
@@ -298,7 +295,7 @@ impl<'d> Rcc<'d> {
298 } 295 }
299} 296}
300 297
301pub unsafe fn init(config: Config) { 298pub(crate) unsafe fn init(config: Config) {
302 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 299 let r = <peripherals::RCC as embassy::util::Steal>::steal();
303 let clocks = Rcc::new(r, config).freeze(); 300 let clocks = Rcc::new(r, config).freeze();
304 set_freqs(clocks); 301 set_freqs(clocks);
@@ -309,3 +306,27 @@ struct PllResults {
309 pllsysclk: Option<u32>, 306 pllsysclk: Option<u32>,
310 pll48clk: Option<u32>, 307 pll48clk: Option<u32>,
311} 308}
309
310mod max {
311 #[cfg(stm32f401)]
312 pub(crate) const SYSCLK_MAX: u32 = 84_000_000;
313
314 #[cfg(any(stm32f405, stm32f407, stm32f415, stm32f417,))]
315 pub(crate) const SYSCLK_MAX: u32 = 168_000_000;
316
317 #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,))]
318 pub(crate) const SYSCLK_MAX: u32 = 100_000_000;
319
320 #[cfg(any(
321 stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479,
322 ))]
323 pub(crate) const SYSCLK_MAX: u32 = 180_000_000;
324
325 #[cfg(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,))]
326 pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX;
327
328 #[cfg(not(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,)))]
329 pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX / 2;
330
331 pub(crate) const PCLK1_MAX: u32 = PCLK2_MAX / 2;
332}
diff --git a/embassy-stm32/src/rcc/f4/max.rs b/embassy-stm32/src/rcc/f4/max.rs
deleted file mode 100644
index dd8de3da9..000000000
--- a/embassy-stm32/src/rcc/f4/max.rs
+++ /dev/null
@@ -1,21 +0,0 @@
1#[cfg(stm32f401)]
2pub(crate) const SYSCLK_MAX: u32 = 84_000_000;
3
4#[cfg(any(stm32f405, stm32f407, stm32f415, stm32f417,))]
5pub(crate) const SYSCLK_MAX: u32 = 168_000_000;
6
7#[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,))]
8pub(crate) const SYSCLK_MAX: u32 = 100_000_000;
9
10#[cfg(any(
11 stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479,
12))]
13pub(crate) const SYSCLK_MAX: u32 = 180_000_000;
14
15#[cfg(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,))]
16pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX;
17
18#[cfg(not(any(stm32f401, stm32f410, stm32f411, stm32f412, stm32f413, stm32f423,)))]
19pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX / 2;
20
21pub(crate) const PCLK1_MAX: u32 = PCLK2_MAX / 2;
diff --git a/embassy-stm32/src/rcc/f7/mod.rs b/embassy-stm32/src/rcc/f7.rs
index c13e20167..25f78c701 100644
--- a/embassy-stm32/src/rcc/f7/mod.rs
+++ b/embassy-stm32/src/rcc/f7.rs
@@ -1,5 +1,3 @@
1mod max;
2
3use crate::pac::{FLASH, PWR, RCC}; 1use crate::pac::{FLASH, PWR, RCC};
4use crate::peripherals; 2use crate::peripherals;
5use crate::rcc::{get_freqs, set_freqs, Clocks}; 3use crate::rcc::{get_freqs, set_freqs, Clocks};
@@ -334,7 +332,7 @@ impl<'d> Rcc<'d> {
334 } 332 }
335} 333}
336 334
337pub unsafe fn init(config: Config) { 335pub(crate) unsafe fn init(config: Config) {
338 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 336 let r = <peripherals::RCC as embassy::util::Steal>::steal();
339 let clocks = Rcc::new(r, config).freeze(); 337 let clocks = Rcc::new(r, config).freeze();
340 set_freqs(clocks); 338 set_freqs(clocks);
@@ -345,3 +343,25 @@ struct PllResults {
345 pllsysclk: Option<u32>, 343 pllsysclk: Option<u32>,
346 pll48clk: Option<u32>, 344 pll48clk: Option<u32>,
347} 345}
346
347mod max {
348 pub(crate) const HSE_OSC_MIN: u32 = 4_000_000;
349 pub(crate) const HSE_OSC_MAX: u32 = 26_000_000;
350 pub(crate) const HSE_BYPASS_MIN: u32 = 1_000_000;
351 pub(crate) const HSE_BYPASS_MAX: u32 = 50_000_000;
352
353 pub(crate) const HCLK_MAX: u32 = 216_000_000;
354 pub(crate) const HCLK_OVERDRIVE_FREQUENCY: u32 = 180_000_000;
355
356 pub(crate) const SYSCLK_MIN: u32 = 12_500_000;
357 pub(crate) const SYSCLK_MAX: u32 = 216_000_000;
358
359 pub(crate) const PCLK1_MIN: u32 = SYSCLK_MIN;
360 pub(crate) const PCLK1_MAX: u32 = SYSCLK_MAX / 4;
361
362 pub(crate) const PCLK2_MIN: u32 = SYSCLK_MIN;
363 pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX / 2;
364
365 pub(crate) const PLL_48_CLK: u32 = 48_000_000;
366 pub(crate) const PLL_48_TOLERANCE: u32 = 120_000;
367}
diff --git a/embassy-stm32/src/rcc/f7/max.rs b/embassy-stm32/src/rcc/f7/max.rs
deleted file mode 100644
index db00fdf3e..000000000
--- a/embassy-stm32/src/rcc/f7/max.rs
+++ /dev/null
@@ -1,19 +0,0 @@
1pub(crate) const HSE_OSC_MIN: u32 = 4_000_000;
2pub(crate) const HSE_OSC_MAX: u32 = 26_000_000;
3pub(crate) const HSE_BYPASS_MIN: u32 = 1_000_000;
4pub(crate) const HSE_BYPASS_MAX: u32 = 50_000_000;
5
6pub(crate) const HCLK_MAX: u32 = 216_000_000;
7pub(crate) const HCLK_OVERDRIVE_FREQUENCY: u32 = 180_000_000;
8
9pub(crate) const SYSCLK_MIN: u32 = 12_500_000;
10pub(crate) const SYSCLK_MAX: u32 = 216_000_000;
11
12pub(crate) const PCLK1_MIN: u32 = SYSCLK_MIN;
13pub(crate) const PCLK1_MAX: u32 = SYSCLK_MAX / 4;
14
15pub(crate) const PCLK2_MIN: u32 = SYSCLK_MIN;
16pub(crate) const PCLK2_MAX: u32 = SYSCLK_MAX / 2;
17
18pub(crate) const PLL_48_CLK: u32 = 48_000_000;
19pub(crate) const PLL_48_TOLERANCE: u32 = 120_000;
diff --git a/embassy-stm32/src/rcc/g0/mod.rs b/embassy-stm32/src/rcc/g0.rs
index 7f7af2fc9..df11ff36d 100644
--- a/embassy-stm32/src/rcc/g0/mod.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -227,7 +227,7 @@ impl RccExt for RCC {
227 } 227 }
228} 228}
229 229
230pub unsafe fn init(config: Config) { 230pub(crate) unsafe fn init(config: Config) {
231 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 231 let r = <peripherals::RCC as embassy::util::Steal>::steal();
232 let clocks = r.freeze(config); 232 let clocks = r.freeze(config);
233 set_freqs(clocks); 233 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/g4/mod.rs b/embassy-stm32/src/rcc/g4.rs
index 8a75b2e03..ee49e2ece 100644
--- a/embassy-stm32/src/rcc/g4/mod.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -203,7 +203,7 @@ impl RccExt for RCC {
203 } 203 }
204} 204}
205 205
206pub unsafe fn init(config: Config) { 206pub(crate) unsafe fn init(config: Config) {
207 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 207 let r = <peripherals::RCC as embassy::util::Steal>::steal();
208 let clocks = r.freeze(config); 208 let clocks = r.freeze(config);
209 set_freqs(clocks); 209 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/h7/mod.rs b/embassy-stm32/src/rcc/h7.rs
index cd493a80a..ac4d033ba 100644
--- a/embassy-stm32/src/rcc/h7/mod.rs
+++ b/embassy-stm32/src/rcc/h7.rs
@@ -13,8 +13,6 @@ use crate::pwr::{Power, VoltageScale};
13use crate::rcc::{set_freqs, Clocks}; 13use crate::rcc::{set_freqs, Clocks};
14use crate::time::Hertz; 14use crate::time::Hertz;
15 15
16mod pll;
17use pll::pll_setup;
18pub use pll::PllConfig; 16pub use pll::PllConfig;
19 17
20const HSI: Hertz = Hertz(64_000_000); 18const HSI: Hertz = Hertz(64_000_000);
@@ -116,11 +114,11 @@ impl<'d> Rcc<'d> {
116 114
117 // NOTE(unsafe) We have exclusive access to the RCC 115 // NOTE(unsafe) We have exclusive access to the RCC
118 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = 116 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) =
119 unsafe { pll_setup(srcclk.0, &self.config.pll1, 0) }; 117 unsafe { pll::pll_setup(srcclk.0, &self.config.pll1, 0) };
120 let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = 118 let (pll2_p_ck, pll2_q_ck, pll2_r_ck) =
121 unsafe { pll_setup(srcclk.0, &self.config.pll2, 1) }; 119 unsafe { pll::pll_setup(srcclk.0, &self.config.pll2, 1) };
122 let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = 120 let (pll3_p_ck, pll3_q_ck, pll3_r_ck) =
123 unsafe { pll_setup(srcclk.0, &self.config.pll3, 2) }; 121 unsafe { pll::pll_setup(srcclk.0, &self.config.pll3, 2) };
124 122
125 let sys_ck = if sys_use_pll1_p { 123 let sys_ck = if sys_use_pll1_p {
126 Hertz(unwrap!(pll1_p_ck)) // Must have been set by sys_ck_setup 124 Hertz(unwrap!(pll1_p_ck)) // Must have been set by sys_ck_setup
@@ -683,7 +681,7 @@ impl<'d, T: McoInstance> Mco<'d, T> {
683 } 681 }
684} 682}
685 683
686pub unsafe fn init(config: Config) { 684pub(crate) unsafe fn init(config: Config) {
687 let mut power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal(), false); 685 let mut power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal(), false);
688 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); 686 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config);
689 let core_clocks = rcc.freeze(&mut power); 687 let core_clocks = rcc.freeze(&mut power);
@@ -700,3 +698,151 @@ pub unsafe fn init(config: Config) {
700 apb2_tim: core_clocks.timy_ker_ck.unwrap_or(core_clocks.pclk2), 698 apb2_tim: core_clocks.timy_ker_ck.unwrap_or(core_clocks.pclk2),
701 }); 699 });
702} 700}
701
702mod pll {
703 use super::{Hertz, RCC};
704
705 const VCO_MIN: u32 = 150_000_000;
706 const VCO_MAX: u32 = 420_000_000;
707
708 #[derive(Default)]
709 pub struct PllConfig {
710 pub p_ck: Option<Hertz>,
711 pub q_ck: Option<Hertz>,
712 pub r_ck: Option<Hertz>,
713 }
714
715 pub(super) struct PllConfigResults {
716 pub ref_x_ck: u32,
717 pub pll_x_m: u32,
718 pub pll_x_p: u32,
719 pub vco_ck_target: u32,
720 }
721
722 fn vco_output_divider_setup(output: u32, plln: usize) -> (u32, u32) {
723 let pll_x_p = if plln == 0 {
724 if output > VCO_MAX / 2 {
725 1
726 } else {
727 ((VCO_MAX / output) | 1) - 1 // Must be even or unity
728 }
729 } else {
730 // Specific to PLL2/3, will subtract 1 later
731 if output > VCO_MAX / 2 {
732 1
733 } else {
734 VCO_MAX / output
735 }
736 };
737
738 let vco_ck = output + pll_x_p;
739
740 assert!(pll_x_p < 128);
741 assert!(vco_ck >= VCO_MIN);
742 assert!(vco_ck <= VCO_MAX);
743
744 (vco_ck, pll_x_p)
745 }
746
747 /// # Safety
748 ///
749 /// Must have exclusive access to the RCC register block
750 unsafe fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults {
751 use crate::pac::rcc::vals::{Pllrge, Pllvcosel};
752
753 let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln);
754
755 // Input divisor, resulting in a reference clock in the range
756 // 1 to 2 MHz. Choose the highest reference clock (lowest m)
757 let pll_x_m = (pll_src + 1_999_999) / 2_000_000;
758 assert!(pll_x_m < 64);
759
760 // Calculate resulting reference clock
761 let ref_x_ck = pll_src / pll_x_m;
762 assert!((1_000_000..=2_000_000).contains(&ref_x_ck));
763
764 RCC.pllcfgr().modify(|w| {
765 w.set_pllvcosel(plln, Pllvcosel::MEDIUMVCO);
766 w.set_pllrge(plln, Pllrge::RANGE1);
767 });
768 PllConfigResults {
769 ref_x_ck,
770 pll_x_m,
771 pll_x_p,
772 vco_ck_target,
773 }
774 }
775
776 /// # Safety
777 ///
778 /// Must have exclusive access to the RCC register block
779 pub(super) unsafe fn pll_setup(
780 pll_src: u32,
781 config: &PllConfig,
782 plln: usize,
783 ) -> (Option<u32>, Option<u32>, Option<u32>) {
784 use crate::pac::rcc::vals::Divp;
785
786 match config.p_ck {
787 Some(requested_output) => {
788 let config_results = vco_setup(pll_src, requested_output.0, plln);
789 let PllConfigResults {
790 ref_x_ck,
791 pll_x_m,
792 pll_x_p,
793 vco_ck_target,
794 } = config_results;
795
796 RCC.pllckselr().modify(|w| w.set_divm(plln, pll_x_m as u8));
797
798 // Feedback divider. Integer only
799 let pll_x_n = vco_ck_target / ref_x_ck;
800 assert!(pll_x_n >= 4);
801 assert!(pll_x_n <= 512);
802 RCC.plldivr(plln)
803 .modify(|w| w.set_divn1((pll_x_n - 1) as u16));
804
805 // No FRACN
806 RCC.pllcfgr().modify(|w| w.set_pllfracen(plln, false));
807 let vco_ck = ref_x_ck * pll_x_n;
808
809 RCC.plldivr(plln)
810 .modify(|w| w.set_divp1(Divp((pll_x_p - 1) as u8)));
811 RCC.pllcfgr().modify(|w| w.set_divpen(plln, true));
812
813 // Calulate additional output dividers
814 let q_ck = match config.q_ck {
815 Some(Hertz(ck)) if ck > 0 => {
816 let div = (vco_ck + ck - 1) / ck;
817 RCC.plldivr(plln).modify(|w| w.set_divq1((div - 1) as u8));
818 RCC.pllcfgr().modify(|w| w.set_divqen(plln, true));
819 Some(vco_ck / div)
820 }
821 _ => None,
822 };
823 let r_ck = match config.r_ck {
824 Some(Hertz(ck)) if ck > 0 => {
825 let div = (vco_ck + ck - 1) / ck;
826 RCC.plldivr(plln).modify(|w| w.set_divr1((div - 1) as u8));
827 RCC.pllcfgr().modify(|w| w.set_divren(plln, true));
828 Some(vco_ck / div)
829 }
830 _ => None,
831 };
832
833 (Some(vco_ck / pll_x_p), q_ck, r_ck)
834 }
835 None => {
836 assert!(
837 config.q_ck.is_none(),
838 "Must set PLL P clock for Q clock to take effect!"
839 );
840 assert!(
841 config.r_ck.is_none(),
842 "Must set PLL P clock for R clock to take effect!"
843 );
844 (None, None, None)
845 }
846 }
847 }
848}
diff --git a/embassy-stm32/src/rcc/h7/pll.rs b/embassy-stm32/src/rcc/h7/pll.rs
deleted file mode 100644
index d3709378b..000000000
--- a/embassy-stm32/src/rcc/h7/pll.rs
+++ /dev/null
@@ -1,145 +0,0 @@
1use super::{Hertz, RCC};
2
3const VCO_MIN: u32 = 150_000_000;
4const VCO_MAX: u32 = 420_000_000;
5
6#[derive(Default)]
7pub struct PllConfig {
8 pub p_ck: Option<Hertz>,
9 pub q_ck: Option<Hertz>,
10 pub r_ck: Option<Hertz>,
11}
12
13pub(super) struct PllConfigResults {
14 pub ref_x_ck: u32,
15 pub pll_x_m: u32,
16 pub pll_x_p: u32,
17 pub vco_ck_target: u32,
18}
19
20fn vco_output_divider_setup(output: u32, plln: usize) -> (u32, u32) {
21 let pll_x_p = if plln == 0 {
22 if output > VCO_MAX / 2 {
23 1
24 } else {
25 ((VCO_MAX / output) | 1) - 1 // Must be even or unity
26 }
27 } else {
28 // Specific to PLL2/3, will subtract 1 later
29 if output > VCO_MAX / 2 {
30 1
31 } else {
32 VCO_MAX / output
33 }
34 };
35
36 let vco_ck = output + pll_x_p;
37
38 assert!(pll_x_p < 128);
39 assert!(vco_ck >= VCO_MIN);
40 assert!(vco_ck <= VCO_MAX);
41
42 (vco_ck, pll_x_p)
43}
44
45/// # Safety
46///
47/// Must have exclusive access to the RCC register block
48unsafe fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults {
49 use crate::pac::rcc::vals::{Pllrge, Pllvcosel};
50
51 let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln);
52
53 // Input divisor, resulting in a reference clock in the range
54 // 1 to 2 MHz. Choose the highest reference clock (lowest m)
55 let pll_x_m = (pll_src + 1_999_999) / 2_000_000;
56 assert!(pll_x_m < 64);
57
58 // Calculate resulting reference clock
59 let ref_x_ck = pll_src / pll_x_m;
60 assert!((1_000_000..=2_000_000).contains(&ref_x_ck));
61
62 RCC.pllcfgr().modify(|w| {
63 w.set_pllvcosel(plln, Pllvcosel::MEDIUMVCO);
64 w.set_pllrge(plln, Pllrge::RANGE1);
65 });
66 PllConfigResults {
67 ref_x_ck,
68 pll_x_m,
69 pll_x_p,
70 vco_ck_target,
71 }
72}
73
74/// # Safety
75///
76/// Must have exclusive access to the RCC register block
77pub(super) unsafe fn pll_setup(
78 pll_src: u32,
79 config: &PllConfig,
80 plln: usize,
81) -> (Option<u32>, Option<u32>, Option<u32>) {
82 use crate::pac::rcc::vals::Divp;
83
84 match config.p_ck {
85 Some(requested_output) => {
86 let config_results = vco_setup(pll_src, requested_output.0, plln);
87 let PllConfigResults {
88 ref_x_ck,
89 pll_x_m,
90 pll_x_p,
91 vco_ck_target,
92 } = config_results;
93
94 RCC.pllckselr().modify(|w| w.set_divm(plln, pll_x_m as u8));
95
96 // Feedback divider. Integer only
97 let pll_x_n = vco_ck_target / ref_x_ck;
98 assert!(pll_x_n >= 4);
99 assert!(pll_x_n <= 512);
100 RCC.plldivr(plln)
101 .modify(|w| w.set_divn1((pll_x_n - 1) as u16));
102
103 // No FRACN
104 RCC.pllcfgr().modify(|w| w.set_pllfracen(plln, false));
105 let vco_ck = ref_x_ck * pll_x_n;
106
107 RCC.plldivr(plln)
108 .modify(|w| w.set_divp1(Divp((pll_x_p - 1) as u8)));
109 RCC.pllcfgr().modify(|w| w.set_divpen(plln, true));
110
111 // Calulate additional output dividers
112 let q_ck = match config.q_ck {
113 Some(Hertz(ck)) if ck > 0 => {
114 let div = (vco_ck + ck - 1) / ck;
115 RCC.plldivr(plln).modify(|w| w.set_divq1((div - 1) as u8));
116 RCC.pllcfgr().modify(|w| w.set_divqen(plln, true));
117 Some(vco_ck / div)
118 }
119 _ => None,
120 };
121 let r_ck = match config.r_ck {
122 Some(Hertz(ck)) if ck > 0 => {
123 let div = (vco_ck + ck - 1) / ck;
124 RCC.plldivr(plln).modify(|w| w.set_divr1((div - 1) as u8));
125 RCC.pllcfgr().modify(|w| w.set_divren(plln, true));
126 Some(vco_ck / div)
127 }
128 _ => None,
129 };
130
131 (Some(vco_ck / pll_x_p), q_ck, r_ck)
132 }
133 None => {
134 assert!(
135 config.q_ck.is_none(),
136 "Must set PLL P clock for Q clock to take effect!"
137 );
138 assert!(
139 config.r_ck.is_none(),
140 "Must set PLL P clock for R clock to take effect!"
141 );
142 (None, None, None)
143 }
144 }
145}
diff --git a/embassy-stm32/src/rcc/l0/mod.rs b/embassy-stm32/src/rcc/l0.rs
index fd84f09c5..fc70ef0ac 100644
--- a/embassy-stm32/src/rcc/l0/mod.rs
+++ b/embassy-stm32/src/rcc/l0.rs
@@ -430,7 +430,7 @@ impl RccExt for RCC {
430#[derive(Clone, Copy)] 430#[derive(Clone, Copy)]
431pub struct HSI48(()); 431pub struct HSI48(());
432 432
433pub unsafe fn init(config: Config) { 433pub(crate) unsafe fn init(config: Config) {
434 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 434 let r = <peripherals::RCC as embassy::util::Steal>::steal();
435 let clocks = r.freeze(config); 435 let clocks = r.freeze(config);
436 set_freqs(clocks); 436 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/l1/mod.rs b/embassy-stm32/src/rcc/l1.rs
index e46bee323..746433c12 100644
--- a/embassy-stm32/src/rcc/l1/mod.rs
+++ b/embassy-stm32/src/rcc/l1.rs
@@ -254,7 +254,7 @@ impl RccExt for RCC {
254 } 254 }
255} 255}
256 256
257pub unsafe fn init(config: Config) { 257pub(crate) unsafe fn init(config: Config) {
258 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 258 let r = <peripherals::RCC as embassy::util::Steal>::steal();
259 let clocks = r.freeze(config); 259 let clocks = r.freeze(config);
260 set_freqs(clocks); 260 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/l4/mod.rs b/embassy-stm32/src/rcc/l4.rs
index a0eedf0b6..510cbddfa 100644
--- a/embassy-stm32/src/rcc/l4/mod.rs
+++ b/embassy-stm32/src/rcc/l4.rs
@@ -482,7 +482,7 @@ impl RccExt for RCC {
482 } 482 }
483} 483}
484 484
485pub unsafe fn init(config: Config) { 485pub(crate) unsafe fn init(config: Config) {
486 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 486 let r = <peripherals::RCC as embassy::util::Steal>::steal();
487 let clocks = r.freeze(config); 487 let clocks = r.freeze(config);
488 set_freqs(clocks); 488 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 0a7edb37a..bf612464f 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -4,6 +4,23 @@ use crate::peripherals;
4use crate::time::Hertz; 4use crate::time::Hertz;
5use core::mem::MaybeUninit; 5use core::mem::MaybeUninit;
6 6
7#[cfg_attr(any(rcc_f0, rcc_f0x0), path = "f0.rs")]
8#[cfg_attr(rcc_f1, path = "f1.rs")]
9#[cfg_attr(rcc_f3, path = "f3.rs")]
10#[cfg_attr(any(rcc_f4, rcc_f410), path = "f4.rs")]
11#[cfg_attr(rcc_f7, path = "f7.rs")]
12#[cfg_attr(rcc_g0, path = "g0.rs")]
13#[cfg_attr(rcc_g4, path = "g4.rs")]
14#[cfg_attr(any(rcc_h7, rcc_h7ab), path = "h7.rs")]
15#[cfg_attr(rcc_l0, path = "l0.rs")]
16#[cfg_attr(rcc_l1, path = "l1.rs")]
17#[cfg_attr(rcc_l4, path = "l4.rs")]
18#[cfg_attr(rcc_u5, path = "u5.rs")]
19#[cfg_attr(rcc_wb, path = "wb.rs")]
20#[cfg_attr(rcc_wl5, path = "wl5.rs")]
21mod _version;
22pub use _version::*;
23
7#[derive(Clone, Copy)] 24#[derive(Clone, Copy)]
8pub struct Clocks { 25pub struct Clocks {
9 pub sys: Hertz, 26 pub sys: Hertz,
@@ -59,61 +76,15 @@ static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
59/// Sets the clock frequencies 76/// Sets the clock frequencies
60/// 77///
61/// Safety: Sets a mutable global. 78/// Safety: Sets a mutable global.
62pub unsafe fn set_freqs(freqs: Clocks) { 79pub(crate) unsafe fn set_freqs(freqs: Clocks) {
63 CLOCK_FREQS.as_mut_ptr().write(freqs); 80 CLOCK_FREQS.as_mut_ptr().write(freqs);
64} 81}
65 82
66/// Safety: Reads a mutable global. 83/// Safety: Reads a mutable global.
67pub unsafe fn get_freqs() -> &'static Clocks { 84pub(crate) unsafe fn get_freqs() -> &'static Clocks {
68 &*CLOCK_FREQS.as_ptr() 85 &*CLOCK_FREQS.as_ptr()
69} 86}
70 87
71cfg_if::cfg_if! {
72 if #[cfg(rcc_h7)] {
73 mod h7;
74 pub use h7::*;
75 } else if #[cfg(rcc_l0)] {
76 mod l0;
77 pub use l0::*;
78 } else if #[cfg(rcc_l1)] {
79 mod l1;
80 pub use l1::*;
81 } else if #[cfg(rcc_l4)] {
82 mod l4;
83 pub use l4::*;
84 } else if #[cfg(rcc_f1)] {
85 mod f1;
86 pub use f1::*;
87 } else if #[cfg(rcc_f3)] {
88 mod f3;
89 pub use f3::*;
90 } else if #[cfg(rcc_f4)] {
91 mod f4;
92 pub use f4::*;
93 } else if #[cfg(rcc_f7)] {
94 mod f7;
95 pub use f7::*;
96 } else if #[cfg(rcc_wb)] {
97 mod wb;
98 pub use wb::*;
99 } else if #[cfg(rcc_wl5)] {
100 mod wl5x;
101 pub use wl5x::*;
102 } else if #[cfg(any(rcc_f0, rcc_f0x0))] {
103 mod f0;
104 pub use f0::*;
105 } else if #[cfg(any(rcc_g0))] {
106 mod g0;
107 pub use g0::*;
108 } else if #[cfg(any(rcc_g4))] {
109 mod g4;
110 pub use g4::*;
111 } else if #[cfg(any(rcc_u5))] {
112 mod u5;
113 pub use u5::*;
114 }
115}
116
117pub(crate) mod sealed { 88pub(crate) mod sealed {
118 pub trait RccPeripheral { 89 pub trait RccPeripheral {
119 fn frequency() -> crate::time::Hertz; 90 fn frequency() -> crate::time::Hertz;
diff --git a/embassy-stm32/src/rcc/u5/mod.rs b/embassy-stm32/src/rcc/u5.rs
index a3df3a02d..e8bd82718 100644
--- a/embassy-stm32/src/rcc/u5/mod.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -502,7 +502,7 @@ impl RccExt for RCC {
502 } 502 }
503} 503}
504 504
505pub unsafe fn init(config: Config) { 505pub(crate) unsafe fn init(config: Config) {
506 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 506 let r = <peripherals::RCC as embassy::util::Steal>::steal();
507 let power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal()); 507 let power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal());
508 let clocks = r.freeze(config, &power); 508 let clocks = r.freeze(config, &power);
diff --git a/embassy-stm32/src/rcc/wb/mod.rs b/embassy-stm32/src/rcc/wb.rs
index 73835cacd..58146d4bd 100644
--- a/embassy-stm32/src/rcc/wb/mod.rs
+++ b/embassy-stm32/src/rcc/wb.rs
@@ -206,7 +206,7 @@ impl RccExt for RCC {
206 } 206 }
207} 207}
208 208
209pub unsafe fn init(config: Config) { 209pub(crate) unsafe fn init(config: Config) {
210 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 210 let r = <peripherals::RCC as embassy::util::Steal>::steal();
211 let clocks = r.freeze(config); 211 let clocks = r.freeze(config);
212 set_freqs(clocks); 212 set_freqs(clocks);
diff --git a/embassy-stm32/src/rcc/wl5x/mod.rs b/embassy-stm32/src/rcc/wl5.rs
index edf603ee6..00b91dfec 100644
--- a/embassy-stm32/src/rcc/wl5x/mod.rs
+++ b/embassy-stm32/src/rcc/wl5.rs
@@ -229,7 +229,7 @@ impl RccExt for RCC {
229 } 229 }
230} 230}
231 231
232pub unsafe fn init(config: Config) { 232pub(crate) unsafe fn init(config: Config) {
233 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 233 let r = <peripherals::RCC as embassy::util::Steal>::steal();
234 let clocks = r.freeze(config); 234 let clocks = r.freeze(config);
235 set_freqs(clocks); 235 set_freqs(clocks);