aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-01-04 23:58:13 +0100
committerDario Nieuwenhuis <[email protected]>2022-01-05 00:00:44 +0100
commit2eb0cc5df78b2abd38228ee1f07b7c446e17d362 (patch)
treea9df2ed2c0acc481e19275473f981da098b541f1
parentc3fd9a0f44ae898c5cf1272dab6b8f46e119fab3 (diff)
stm32/rcc: remove Rcc struct, RccExt trait.
All the RCC configuration is executed in init().
-rw-r--r--embassy-stm32/src/lib.rs2
-rw-r--r--embassy-stm32/src/pwr/f3.rs1
-rw-r--r--embassy-stm32/src/pwr/f4.rs1
-rw-r--r--embassy-stm32/src/pwr/f7.rs1
-rw-r--r--embassy-stm32/src/pwr/g0.rs1
-rw-r--r--embassy-stm32/src/pwr/g4.rs1
-rw-r--r--embassy-stm32/src/pwr/h7.rs78
-rw-r--r--embassy-stm32/src/pwr/l1.rs1
-rw-r--r--embassy-stm32/src/pwr/mod.rs13
-rw-r--r--embassy-stm32/src/pwr/u5.rs32
-rw-r--r--embassy-stm32/src/pwr/wb55.rs0
-rw-r--r--embassy-stm32/src/pwr/wl5.rs1
-rw-r--r--embassy-stm32/src/rcc/f0.rs294
-rw-r--r--embassy-stm32/src/rcc/f1.rs337
-rw-r--r--embassy-stm32/src/rcc/f3.rs453
-rw-r--r--embassy-stm32/src/rcc/f4.rs475
-rw-r--r--embassy-stm32/src/rcc/f7.rs524
-rw-r--r--embassy-stm32/src/rcc/g0.rs167
-rw-r--r--embassy-stm32/src/rcc/g4.rs173
-rw-r--r--embassy-stm32/src/rcc/h7.rs881
-rw-r--r--embassy-stm32/src/rcc/l0.rs413
-rw-r--r--embassy-stm32/src/rcc/l1.rs354
-rw-r--r--embassy-stm32/src/rcc/l4.rs458
-rw-r--r--embassy-stm32/src/rcc/u5.rs388
-rw-r--r--embassy-stm32/src/rcc/wb.rs168
-rw-r--r--embassy-stm32/src/rcc/wl5.rs203
-rw-r--r--examples/stm32l0/src/bin/button_exti.rs14
-rw-r--r--examples/stm32l0/src/bin/lorawan.rs12
-rw-r--r--examples/stm32wl55/src/bin/lorawan.rs13
-rw-r--r--examples/stm32wl55/src/bin/subghz.rs5
m---------stm32-data0
31 files changed, 2427 insertions, 3037 deletions
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index c8a0e1705..117f3ed2a 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -43,8 +43,6 @@ pub mod i2c;
43#[cfg(crc)] 43#[cfg(crc)]
44pub mod crc; 44pub mod crc;
45pub mod pwm; 45pub mod pwm;
46#[cfg(pwr)]
47pub mod pwr;
48#[cfg(rng)] 46#[cfg(rng)]
49pub mod rng; 47pub mod rng;
50#[cfg(sdmmc)] 48#[cfg(sdmmc)]
diff --git a/embassy-stm32/src/pwr/f3.rs b/embassy-stm32/src/pwr/f3.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/pwr/f3.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/embassy-stm32/src/pwr/f4.rs b/embassy-stm32/src/pwr/f4.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/pwr/f4.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/embassy-stm32/src/pwr/f7.rs b/embassy-stm32/src/pwr/f7.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/pwr/f7.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/embassy-stm32/src/pwr/g0.rs b/embassy-stm32/src/pwr/g0.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/pwr/g0.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/embassy-stm32/src/pwr/g4.rs b/embassy-stm32/src/pwr/g4.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/pwr/g4.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/embassy-stm32/src/pwr/h7.rs b/embassy-stm32/src/pwr/h7.rs
deleted file mode 100644
index 37b049a85..000000000
--- a/embassy-stm32/src/pwr/h7.rs
+++ /dev/null
@@ -1,78 +0,0 @@
1use crate::pac::{PWR, RCC, SYSCFG};
2use crate::peripherals;
3
4/// Voltage Scale
5///
6/// Represents the voltage range feeding the CPU core. The maximum core
7/// clock frequency depends on this value.
8#[derive(Copy, Clone, PartialEq)]
9pub enum VoltageScale {
10 /// VOS 0 range VCORE 1.26V - 1.40V
11 Scale0,
12 /// VOS 1 range VCORE 1.15V - 1.26V
13 Scale1,
14 /// VOS 2 range VCORE 1.05V - 1.15V
15 Scale2,
16 /// VOS 3 range VCORE 0.95V - 1.05V
17 Scale3,
18}
19
20/// Power Configuration
21///
22/// Generated when the PWR peripheral is frozen. The existence of this
23/// value indicates that the voltage scaling configuration can no
24/// longer be changed.
25pub struct Power {
26 pub(crate) vos: VoltageScale,
27}
28
29impl Power {
30 pub fn new(_peri: peripherals::PWR, enable_overdrive: bool) -> Self {
31 // NOTE(unsafe) we have the PWR singleton
32 unsafe {
33 // NB. The lower bytes of CR3 can only be written once after
34 // POR, and must be written with a valid combination. Refer to
35 // RM0433 Rev 7 6.8.4. This is partially enforced by dropping
36 // `self` at the end of this method, but of course we cannot
37 // know what happened between the previous POR and here.
38 #[cfg(pwr_h7)]
39 PWR.cr3().modify(|w| {
40 w.set_scuen(true);
41 w.set_ldoen(true);
42 w.set_bypass(false);
43 });
44
45 #[cfg(pwr_h7smps)]
46 PWR.cr3().modify(|w| {
47 // hardcode "Direct SPMS" for now, this is what works on nucleos with the
48 // default solderbridge configuration.
49 w.set_sden(true);
50 w.set_ldoen(false);
51 });
52
53 // Validate the supply configuration. If you are stuck here, it is
54 // because the voltages on your board do not match those specified
55 // in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset
56 // VOS = Scale 3, so check that the voltage on the VCAP pins =
57 // 1.0V.
58 while !PWR.csr1().read().actvosrdy() {}
59
60 // Go to Scale 1
61 PWR.d3cr().modify(|w| w.set_vos(0b11));
62 while !PWR.d3cr().read().vosrdy() {}
63
64 let vos = if !enable_overdrive {
65 VoltageScale::Scale1
66 } else {
67 critical_section::with(|_| {
68 RCC.apb4enr().modify(|w| w.set_syscfgen(true));
69
70 SYSCFG.pwrcr().modify(|w| w.set_oden(1));
71 });
72 while !PWR.d3cr().read().vosrdy() {}
73 VoltageScale::Scale0
74 };
75 Self { vos }
76 }
77 }
78}
diff --git a/embassy-stm32/src/pwr/l1.rs b/embassy-stm32/src/pwr/l1.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/pwr/l1.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/embassy-stm32/src/pwr/mod.rs b/embassy-stm32/src/pwr/mod.rs
deleted file mode 100644
index d948c398d..000000000
--- a/embassy-stm32/src/pwr/mod.rs
+++ /dev/null
@@ -1,13 +0,0 @@
1#[cfg_attr(any(pwr_h7, pwr_h7smps), path = "h7.rs")]
2#[cfg_attr(pwr_f3, path = "f3.rs")]
3#[cfg_attr(pwr_f4, path = "f4.rs")]
4#[cfg_attr(pwr_f7, path = "f7.rs")]
5#[cfg_attr(pwr_wl5, path = "wl5.rs")]
6#[cfg_attr(pwr_g0, path = "g0.rs")]
7#[cfg_attr(pwr_g4, path = "g4.rs")]
8#[cfg_attr(pwr_l1, path = "l1.rs")]
9#[cfg_attr(pwr_u5, path = "u5.rs")]
10#[cfg_attr(pwr_wb55, path = "wb55.rs")]
11mod _version;
12
13pub use _version::*;
diff --git a/embassy-stm32/src/pwr/u5.rs b/embassy-stm32/src/pwr/u5.rs
deleted file mode 100644
index a90659d9c..000000000
--- a/embassy-stm32/src/pwr/u5.rs
+++ /dev/null
@@ -1,32 +0,0 @@
1use crate::peripherals;
2
3/// Voltage Scale
4///
5/// Represents the voltage range feeding the CPU core. The maximum core
6/// clock frequency depends on this value.
7#[derive(Copy, Clone, PartialEq)]
8pub enum VoltageScale {
9 // Highest frequency
10 Range1,
11 Range2,
12 Range3,
13 // Lowest power
14 Range4,
15}
16
17/// Power Configuration
18///
19/// Generated when the PWR peripheral is frozen. The existence of this
20/// value indicates that the voltage scaling configuration can no
21/// longer be changed.
22pub struct Power {
23 pub(crate) vos: VoltageScale,
24}
25
26impl Power {
27 pub fn new(_peri: peripherals::PWR) -> Self {
28 Self {
29 vos: VoltageScale::Range4,
30 }
31 }
32}
diff --git a/embassy-stm32/src/pwr/wb55.rs b/embassy-stm32/src/pwr/wb55.rs
deleted file mode 100644
index e69de29bb..000000000
--- a/embassy-stm32/src/pwr/wb55.rs
+++ /dev/null
diff --git a/embassy-stm32/src/pwr/wl5.rs b/embassy-stm32/src/pwr/wl5.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/pwr/wl5.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/embassy-stm32/src/rcc/f0.rs b/embassy-stm32/src/rcc/f0.rs
index 07a28cc3e..1527afa05 100644
--- a/embassy-stm32/src/rcc/f0.rs
+++ b/embassy-stm32/src/rcc/f0.rs
@@ -1,9 +1,5 @@
1use core::marker::PhantomData; 1use crate::pac::rcc::vals::{Hpre, Hsebyp, Pllmul, Pllsrc, Ppre, Sw, Usbsw};
2
3use embassy::util::Unborrow;
4
5use crate::pac::{FLASH, RCC}; 2use crate::pac::{FLASH, RCC};
6use crate::peripherals;
7use crate::time::Hertz; 3use crate::time::Hertz;
8 4
9use super::{set_freqs, Clocks}; 5use super::{set_freqs, Clocks};
@@ -28,181 +24,151 @@ pub struct Config {
28 pub pclk: Option<Hertz>, 24 pub pclk: Option<Hertz>,
29} 25}
30 26
31pub struct Rcc<'d> { 27pub(crate) unsafe fn init(config: Config) {
32 inner: PhantomData<&'d ()>, 28 let sysclk = config.sys_ck.map(|v| v.0).unwrap_or(HSI);
33 config: Config,
34}
35 29
36impl<'d> Rcc<'d> { 30 let (src_clk, use_hsi48) = config.hse.map(|v| (v.0, false)).unwrap_or_else(|| {
37 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { 31 #[cfg(rcc_f0)]
38 Self { 32 if config.hsi48 {
39 inner: PhantomData, 33 return (48_000_000, true);
40 config,
41 } 34 }
42 } 35 (HSI, false)
43 36 });
44 pub fn freeze(self) -> Clocks { 37
45 use crate::pac::rcc::vals::{Hpre, Hsebyp, Pllmul, Pllsrc, Ppre, Sw, Usbsw}; 38 let (pllmul_bits, real_sysclk) = if sysclk == src_clk {
46 39 (None, sysclk)
47 let sysclk = self.config.sys_ck.map(|v| v.0).unwrap_or(HSI); 40 } else {
48 41 let prediv = if config.hse.is_some() { 1 } else { 2 };
49 let (src_clk, use_hsi48) = self.config.hse.map(|v| (v.0, false)).unwrap_or_else(|| { 42 let pllmul = (2 * prediv * sysclk + src_clk) / src_clk / 2;
50 #[cfg(rcc_f0)] 43 let pllmul = pllmul.max(2).min(16);
51 if self.config.hsi48 { 44
52 return (48_000_000, true); 45 let pllmul_bits = pllmul as u8 - 2;
53 } 46 let real_sysclk = pllmul * src_clk / prediv;
54 (HSI, false) 47 (Some(pllmul_bits), real_sysclk)
55 }); 48 };
56 49
57 let (pllmul_bits, real_sysclk) = if sysclk == src_clk { 50 let hpre_bits = config
58 (None, sysclk) 51 .hclk
52 .map(|hclk| match real_sysclk / hclk.0 {
53 0 => unreachable!(),
54 1 => 0b0111,
55 2 => 0b1000,
56 3..=5 => 0b1001,
57 6..=11 => 0b1010,
58 12..=39 => 0b1011,
59 40..=95 => 0b1100,
60 96..=191 => 0b1101,
61 192..=383 => 0b1110,
62 _ => 0b1111,
63 })
64 .unwrap_or(0b0111);
65 let hclk = real_sysclk / (1 << (hpre_bits - 0b0111));
66
67 let ppre_bits = config
68 .pclk
69 .map(|pclk| match hclk / pclk.0 {
70 0 => unreachable!(),
71 1 => 0b011,
72 2 => 0b100,
73 3..=5 => 0b101,
74 6..=11 => 0b110,
75 _ => 0b111,
76 })
77 .unwrap_or(0b011);
78
79 let ppre: u8 = 1 << (ppre_bits - 0b011);
80 let pclk = hclk / u32::from(ppre);
81
82 let timer_mul = if ppre == 1 { 1 } else { 2 };
83
84 FLASH.acr().write(|w| {
85 let latency = if real_sysclk <= 24_000_000 {
86 0
87 } else if real_sysclk <= 48_000_000 {
88 1
59 } else { 89 } else {
60 let prediv = if self.config.hse.is_some() { 1 } else { 2 }; 90 2
61 let pllmul = (2 * prediv * sysclk + src_clk) / src_clk / 2;
62 let pllmul = pllmul.max(2).min(16);
63
64 let pllmul_bits = pllmul as u8 - 2;
65 let real_sysclk = pllmul * src_clk / prediv;
66 (Some(pllmul_bits), real_sysclk)
67 }; 91 };
92 w.latency().0 = latency;
93 });
68 94
69 let hpre_bits = self 95 match (config.hse.is_some(), use_hsi48) {
70 .config 96 (true, _) => {
71 .hclk 97 RCC.cr().modify(|w| {
72 .map(|hclk| match real_sysclk / hclk.0 { 98 w.set_csson(true);
73 0 => unreachable!(), 99 w.set_hseon(true);
74 1 => 0b0111,
75 2 => 0b1000,
76 3..=5 => 0b1001,
77 6..=11 => 0b1010,
78 12..=39 => 0b1011,
79 40..=95 => 0b1100,
80 96..=191 => 0b1101,
81 192..=383 => 0b1110,
82 _ => 0b1111,
83 })
84 .unwrap_or(0b0111);
85 let hclk = real_sysclk / (1 << (hpre_bits - 0b0111));
86
87 let ppre_bits = self
88 .config
89 .pclk
90 .map(|pclk| match hclk / pclk.0 {
91 0 => unreachable!(),
92 1 => 0b011,
93 2 => 0b100,
94 3..=5 => 0b101,
95 6..=11 => 0b110,
96 _ => 0b111,
97 })
98 .unwrap_or(0b011);
99
100 let ppre: u8 = 1 << (ppre_bits - 0b011);
101 let pclk = hclk / u32::from(ppre);
102
103 let timer_mul = if ppre == 1 { 1 } else { 2 };
104
105 // NOTE(safety) Atomic write
106 unsafe {
107 FLASH.acr().write(|w| {
108 let latency = if real_sysclk <= 24_000_000 {
109 0
110 } else if real_sysclk <= 48_000_000 {
111 1
112 } else {
113 2
114 };
115 w.latency().0 = latency;
116 });
117 }
118 100
119 // NOTE(unsafe) We have exclusive access to the RCC 101 if config.bypass_hse {
120 unsafe { 102 w.set_hsebyp(Hsebyp::BYPASSED);
121 match (self.config.hse.is_some(), use_hsi48) {
122 (true, _) => {
123 RCC.cr().modify(|w| {
124 w.set_csson(true);
125 w.set_hseon(true);
126
127 if self.config.bypass_hse {
128 w.set_hsebyp(Hsebyp::BYPASSED);
129 }
130 });
131 while !RCC.cr().read().hserdy() {}
132
133 if pllmul_bits.is_some() {
134 RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSE_DIV_PREDIV))
135 }
136 }
137 (false, true) => {
138 // use_hsi48 will always be false for rcc_f0x0
139 #[cfg(rcc_f0)]
140 RCC.cr2().modify(|w| w.set_hsi48on(true));
141 #[cfg(rcc_f0)]
142 while !RCC.cr2().read().hsi48rdy() {}
143
144 #[cfg(rcc_f0)]
145 if pllmul_bits.is_some() {
146 RCC.cfgr()
147 .modify(|w| w.set_pllsrc(Pllsrc::HSI48_DIV_PREDIV))
148 }
149 } 103 }
150 _ => { 104 });
151 RCC.cr().modify(|w| w.set_hsion(true)); 105 while !RCC.cr().read().hserdy() {}
152 while !RCC.cr().read().hsirdy() {}
153 106
154 if pllmul_bits.is_some() { 107 if pllmul_bits.is_some() {
155 RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSI_DIV2)) 108 RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSE_DIV_PREDIV))
156 }
157 }
158 } 109 }
110 }
111 (false, true) => {
112 // use_hsi48 will always be false for rcc_f0x0
113 #[cfg(rcc_f0)]
114 RCC.cr2().modify(|w| w.set_hsi48on(true));
115 #[cfg(rcc_f0)]
116 while !RCC.cr2().read().hsi48rdy() {}
159 117
160 if self.config.usb_pll { 118 #[cfg(rcc_f0)]
161 RCC.cfgr3().modify(|w| w.set_usbsw(Usbsw::PLLCLK)); 119 if pllmul_bits.is_some() {
120 RCC.cfgr()
121 .modify(|w| w.set_pllsrc(Pllsrc::HSI48_DIV_PREDIV))
162 } 122 }
163 // TODO: Option to use CRS (Clock Recovery) 123 }
124 _ => {
125 RCC.cr().modify(|w| w.set_hsion(true));
126 while !RCC.cr().read().hsirdy() {}
164 127
165 if let Some(pllmul_bits) = pllmul_bits { 128 if pllmul_bits.is_some() {
166 RCC.cfgr().modify(|w| w.set_pllmul(Pllmul(pllmul_bits))); 129 RCC.cfgr().modify(|w| w.set_pllsrc(Pllsrc::HSI_DIV2))
130 }
131 }
132 }
167 133
168 RCC.cr().modify(|w| w.set_pllon(true)); 134 if config.usb_pll {
169 while !RCC.cr().read().pllrdy() {} 135 RCC.cfgr3().modify(|w| w.set_usbsw(Usbsw::PLLCLK));
136 }
137 // TODO: Option to use CRS (Clock Recovery)
170 138
171 RCC.cfgr().modify(|w| { 139 if let Some(pllmul_bits) = pllmul_bits {
172 w.set_ppre(Ppre(ppre_bits)); 140 RCC.cfgr().modify(|w| w.set_pllmul(Pllmul(pllmul_bits)));
173 w.set_hpre(Hpre(hpre_bits)); 141
174 w.set_sw(Sw::PLL) 142 RCC.cr().modify(|w| w.set_pllon(true));
175 }); 143 while !RCC.cr().read().pllrdy() {}
144
145 RCC.cfgr().modify(|w| {
146 w.set_ppre(Ppre(ppre_bits));
147 w.set_hpre(Hpre(hpre_bits));
148 w.set_sw(Sw::PLL)
149 });
150 } else {
151 RCC.cfgr().modify(|w| {
152 w.set_ppre(Ppre(ppre_bits));
153 w.set_hpre(Hpre(hpre_bits));
154
155 if config.hse.is_some() {
156 w.set_sw(Sw::HSE);
157 } else if use_hsi48 {
158 #[cfg(rcc_f0)]
159 w.set_sw(Sw::HSI48);
176 } else { 160 } else {
177 RCC.cfgr().modify(|w| { 161 w.set_sw(Sw::HSI)
178 w.set_ppre(Ppre(ppre_bits));
179 w.set_hpre(Hpre(hpre_bits));
180
181 if self.config.hse.is_some() {
182 w.set_sw(Sw::HSE);
183 } else if use_hsi48 {
184 #[cfg(rcc_f0)]
185 w.set_sw(Sw::HSI48);
186 } else {
187 w.set_sw(Sw::HSI)
188 }
189 })
190 } 162 }
191 } 163 })
192
193 Clocks {
194 sys: Hertz(real_sysclk),
195 apb1: Hertz(pclk),
196 apb2: Hertz(pclk),
197 apb1_tim: Hertz(pclk * timer_mul),
198 apb2_tim: Hertz(pclk * timer_mul),
199 ahb: Hertz(hclk),
200 }
201 } 164 }
202}
203 165
204pub(crate) unsafe fn init(config: Config) { 166 set_freqs(Clocks {
205 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); 167 sys: Hertz(real_sysclk),
206 let clocks = rcc.freeze(); 168 apb1: Hertz(pclk),
207 set_freqs(clocks); 169 apb2: Hertz(pclk),
170 apb1_tim: Hertz(pclk * timer_mul),
171 apb2_tim: Hertz(pclk * timer_mul),
172 ahb: Hertz(hclk),
173 });
208} 174}
diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs
index c9d09ee33..d44544d28 100644
--- a/embassy-stm32/src/rcc/f1.rs
+++ b/embassy-stm32/src/rcc/f1.rs
@@ -1,15 +1,11 @@
1use core::convert::TryFrom; 1use core::convert::TryFrom;
2use core::marker::PhantomData;
3
4use embassy::util::Unborrow;
5 2
3use super::{set_freqs, Clocks};
6use crate::pac::flash::vals::Latency; 4use crate::pac::flash::vals::Latency;
5use crate::pac::rcc::vals::{Adcpre, Hpre, Pllmul, Pllsrc, Ppre1, Sw, Usbpre};
7use crate::pac::{FLASH, RCC}; 6use crate::pac::{FLASH, RCC};
8use crate::peripherals;
9use crate::time::Hertz; 7use crate::time::Hertz;
10 8
11use super::{set_freqs, Clocks};
12
13const HSI: u32 = 8_000_000; 9const HSI: u32 = 8_000_000;
14 10
15/// Configuration of the clocks 11/// Configuration of the clocks
@@ -26,189 +22,158 @@ pub struct Config {
26 pub adcclk: Option<Hertz>, 22 pub adcclk: Option<Hertz>,
27} 23}
28 24
29pub struct Rcc<'d> { 25pub(crate) unsafe fn init(config: Config) {
30 inner: PhantomData<&'d ()>, 26 let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI / 2);
31 config: Config, 27 let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk);
32} 28 let pllmul = sysclk / pllsrcclk;
33 29
34impl<'d> Rcc<'d> { 30 let (pllmul_bits, real_sysclk) = if pllmul == 1 {
35 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { 31 (None, config.hse.map(|hse| hse.0).unwrap_or(HSI))
36 Self { 32 } else {
37 inner: PhantomData, 33 let pllmul = core::cmp::min(core::cmp::max(pllmul, 1), 16);
38 config, 34 (Some(pllmul as u8 - 2), pllsrcclk * pllmul)
39 } 35 };
36
37 assert!(real_sysclk <= 72_000_000);
38
39 let hpre_bits = config
40 .hclk
41 .map(|hclk| match real_sysclk / hclk.0 {
42 0 => unreachable!(),
43 1 => 0b0111,
44 2 => 0b1000,
45 3..=5 => 0b1001,
46 6..=11 => 0b1010,
47 12..=39 => 0b1011,
48 40..=95 => 0b1100,
49 96..=191 => 0b1101,
50 192..=383 => 0b1110,
51 _ => 0b1111,
52 })
53 .unwrap_or(0b0111);
54
55 let hclk = if hpre_bits >= 0b1100 {
56 real_sysclk / (1 << (hpre_bits - 0b0110))
57 } else {
58 real_sysclk / (1 << (hpre_bits - 0b0111))
59 };
60
61 assert!(hclk <= 72_000_000);
62
63 let ppre1_bits = config
64 .pclk1
65 .map(|pclk1| match hclk / pclk1.0 {
66 0 => unreachable!(),
67 1 => 0b011,
68 2 => 0b100,
69 3..=5 => 0b101,
70 6..=11 => 0b110,
71 _ => 0b111,
72 })
73 .unwrap_or(0b011);
74
75 let ppre1 = 1 << (ppre1_bits - 0b011);
76 let pclk1 = hclk / u32::try_from(ppre1).unwrap();
77 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
78
79 assert!(pclk1 <= 36_000_000);
80
81 let ppre2_bits = config
82 .pclk2
83 .map(|pclk2| match hclk / pclk2.0 {
84 0 => unreachable!(),
85 1 => 0b011,
86 2 => 0b100,
87 3..=5 => 0b101,
88 6..=11 => 0b110,
89 _ => 0b111,
90 })
91 .unwrap_or(0b011);
92
93 let ppre2 = 1 << (ppre2_bits - 0b011);
94 let pclk2 = hclk / u32::try_from(ppre2).unwrap();
95 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
96
97 assert!(pclk2 <= 72_000_000);
98
99 // Only needed for stm32f103?
100 FLASH.acr().write(|w| {
101 w.set_latency(if real_sysclk <= 24_000_000 {
102 Latency(0b000)
103 } else if real_sysclk <= 48_000_000 {
104 Latency(0b001)
105 } else {
106 Latency(0b010)
107 });
108 });
109
110 // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
111 // PLL output frequency is a supported one.
112 // usbpre == false: divide clock by 1.5, otherwise no division
113 let (usbpre, _usbclk_valid) = match (config.hse, pllmul_bits, real_sysclk) {
114 (Some(_), Some(_), 72_000_000) => (false, true),
115 (Some(_), Some(_), 48_000_000) => (true, true),
116 _ => (true, false),
117 };
118
119 let apre_bits: u8 = config
120 .adcclk
121 .map(|adcclk| match pclk2 / adcclk.0 {
122 0..=2 => 0b00,
123 3..=4 => 0b01,
124 5..=7 => 0b10,
125 _ => 0b11,
126 })
127 .unwrap_or(0b11);
128
129 let apre = (apre_bits + 1) << 1;
130 let adcclk = pclk2 / unwrap!(u32::try_from(apre));
131
132 assert!(adcclk <= 14_000_000);
133
134 if config.hse.is_some() {
135 // enable HSE and wait for it to be ready
136 RCC.cr().modify(|w| w.set_hseon(true));
137 while !RCC.cr().read().hserdy() {}
40 } 138 }
41 139
42 pub fn freeze(self) -> Clocks { 140 if let Some(pllmul_bits) = pllmul_bits {
43 use crate::pac::rcc::vals::{Adcpre, Hpre, Pllmul, Pllsrc, Ppre1, Sw, Usbpre}; 141 // enable PLL and wait for it to be ready
44 142 RCC.cfgr().modify(|w| {
45 let pllsrcclk = self.config.hse.map(|hse| hse.0).unwrap_or(HSI / 2); 143 w.set_pllmul(Pllmul(pllmul_bits));
46 let sysclk = self.config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk); 144 w.set_pllsrc(Pllsrc(config.hse.is_some() as u8));
47 let pllmul = sysclk / pllsrcclk; 145 });
48 146
49 let (pllmul_bits, real_sysclk) = if pllmul == 1 { 147 RCC.cr().modify(|w| w.set_pllon(true));
50 (None, self.config.hse.map(|hse| hse.0).unwrap_or(HSI)) 148 while !RCC.cr().read().pllrdy() {}
51 } else {
52 let pllmul = core::cmp::min(core::cmp::max(pllmul, 1), 16);
53 (Some(pllmul as u8 - 2), pllsrcclk * pllmul)
54 };
55
56 assert!(real_sysclk <= 72_000_000);
57
58 let hpre_bits = self
59 .config
60 .hclk
61 .map(|hclk| match real_sysclk / hclk.0 {
62 0 => unreachable!(),
63 1 => 0b0111,
64 2 => 0b1000,
65 3..=5 => 0b1001,
66 6..=11 => 0b1010,
67 12..=39 => 0b1011,
68 40..=95 => 0b1100,
69 96..=191 => 0b1101,
70 192..=383 => 0b1110,
71 _ => 0b1111,
72 })
73 .unwrap_or(0b0111);
74
75 let hclk = if hpre_bits >= 0b1100 {
76 real_sysclk / (1 << (hpre_bits - 0b0110))
77 } else {
78 real_sysclk / (1 << (hpre_bits - 0b0111))
79 };
80
81 assert!(hclk <= 72_000_000);
82
83 let ppre1_bits = self
84 .config
85 .pclk1
86 .map(|pclk1| match hclk / pclk1.0 {
87 0 => unreachable!(),
88 1 => 0b011,
89 2 => 0b100,
90 3..=5 => 0b101,
91 6..=11 => 0b110,
92 _ => 0b111,
93 })
94 .unwrap_or(0b011);
95
96 let ppre1 = 1 << (ppre1_bits - 0b011);
97 let pclk1 = hclk / u32::try_from(ppre1).unwrap();
98 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
99
100 assert!(pclk1 <= 36_000_000);
101
102 let ppre2_bits = self
103 .config
104 .pclk2
105 .map(|pclk2| match hclk / pclk2.0 {
106 0 => unreachable!(),
107 1 => 0b011,
108 2 => 0b100,
109 3..=5 => 0b101,
110 6..=11 => 0b110,
111 _ => 0b111,
112 })
113 .unwrap_or(0b011);
114
115 let ppre2 = 1 << (ppre2_bits - 0b011);
116 let pclk2 = hclk / u32::try_from(ppre2).unwrap();
117 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
118
119 assert!(pclk2 <= 72_000_000);
120
121 // Only needed for stm32f103?
122 // NOTE(safety) Atomic write
123 unsafe {
124 FLASH.acr().write(|w| {
125 w.set_latency(if real_sysclk <= 24_000_000 {
126 Latency(0b000)
127 } else if real_sysclk <= 48_000_000 {
128 Latency(0b001)
129 } else {
130 Latency(0b010)
131 });
132 })
133 }
134
135 // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the
136 // PLL output frequency is a supported one.
137 // usbpre == false: divide clock by 1.5, otherwise no division
138 let (usbpre, _usbclk_valid) = match (self.config.hse, pllmul_bits, real_sysclk) {
139 (Some(_), Some(_), 72_000_000) => (false, true),
140 (Some(_), Some(_), 48_000_000) => (true, true),
141 _ => (true, false),
142 };
143
144 let apre_bits: u8 = self
145 .config
146 .adcclk
147 .map(|adcclk| match pclk2 / adcclk.0 {
148 0..=2 => 0b00,
149 3..=4 => 0b01,
150 5..=7 => 0b10,
151 _ => 0b11,
152 })
153 .unwrap_or(0b11);
154
155 let apre = (apre_bits + 1) << 1;
156 let adcclk = pclk2 / unwrap!(u32::try_from(apre));
157
158 assert!(adcclk <= 14_000_000);
159
160 unsafe {
161 if self.config.hse.is_some() {
162 // enable HSE and wait for it to be ready
163 RCC.cr().modify(|w| w.set_hseon(true));
164 while !RCC.cr().read().hserdy() {}
165 }
166
167 if let Some(pllmul_bits) = pllmul_bits {
168 // enable PLL and wait for it to be ready
169 RCC.cfgr().modify(|w| {
170 w.set_pllmul(Pllmul(pllmul_bits));
171 w.set_pllsrc(Pllsrc(self.config.hse.is_some() as u8));
172 });
173
174 RCC.cr().modify(|w| w.set_pllon(true));
175 while !RCC.cr().read().pllrdy() {}
176 }
177
178 // Only needed for stm32f103?
179 RCC.cfgr().modify(|w| {
180 w.set_adcpre(Adcpre(apre_bits));
181 w.set_ppre2(Ppre1(ppre2_bits));
182 w.set_ppre1(Ppre1(ppre1_bits));
183 w.set_hpre(Hpre(hpre_bits));
184 w.set_usbpre(Usbpre(usbpre as u8));
185 w.set_sw(Sw(if pllmul_bits.is_some() {
186 // PLL
187 0b10
188 } else if self.config.hse.is_some() {
189 // HSE
190 0b1
191 } else {
192 // HSI
193 0b0
194 }));
195 });
196 }
197
198 Clocks {
199 sys: Hertz(real_sysclk),
200 apb1: Hertz(pclk1),
201 apb2: Hertz(pclk2),
202 apb1_tim: Hertz(pclk1 * timer_mul1),
203 apb2_tim: Hertz(pclk2 * timer_mul2),
204 ahb: Hertz(hclk),
205 adc: Hertz(adcclk),
206 }
207 } 149 }
208}
209 150
210pub(crate) unsafe fn init(config: Config) { 151 // Only needed for stm32f103?
211 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); 152 RCC.cfgr().modify(|w| {
212 let clocks = rcc.freeze(); 153 w.set_adcpre(Adcpre(apre_bits));
213 set_freqs(clocks); 154 w.set_ppre2(Ppre1(ppre2_bits));
155 w.set_ppre1(Ppre1(ppre1_bits));
156 w.set_hpre(Hpre(hpre_bits));
157 w.set_usbpre(Usbpre(usbpre as u8));
158 w.set_sw(Sw(if pllmul_bits.is_some() {
159 // PLL
160 0b10
161 } else if config.hse.is_some() {
162 // HSE
163 0b1
164 } else {
165 // HSI
166 0b0
167 }));
168 });
169
170 set_freqs(Clocks {
171 sys: Hertz(real_sysclk),
172 apb1: Hertz(pclk1),
173 apb2: Hertz(pclk2),
174 apb1_tim: Hertz(pclk1 * timer_mul1),
175 apb2_tim: Hertz(pclk2 * timer_mul2),
176 ahb: Hertz(hclk),
177 adc: Hertz(adcclk),
178 });
214} 179}
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index 7b5e0cce7..e16e1e499 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -1,23 +1,11 @@
1use core::marker::PhantomData; 1use crate::pac::flash::vals::Latency;
2use embassy::util::Unborrow; 2use crate::pac::rcc::vals::{Hpre, Hsebyp, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
3 3use crate::pac::{FLASH, RCC};
4use crate::pac::{
5 flash::vals::Latency,
6 rcc::vals::{Hpre, Hsebyp, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre},
7 FLASH, RCC,
8};
9use crate::peripherals;
10use crate::rcc::{set_freqs, Clocks}; 4use crate::rcc::{set_freqs, Clocks};
11use crate::time::Hertz; 5use crate::time::Hertz;
12 6
13const HSI: u32 = 8_000_000; 7const HSI: u32 = 8_000_000;
14 8
15/// RCC peripheral
16pub struct Rcc<'d> {
17 config: Config,
18 phantom: PhantomData<&'d mut peripherals::RCC>,
19}
20
21/// Clocks configutation 9/// Clocks configutation
22#[non_exhaustive] 10#[non_exhaustive]
23#[derive(Default)] 11#[derive(Default)]
@@ -55,259 +43,228 @@ struct PllConfig {
55 43
56/// Initialize and Set the clock frequencies 44/// Initialize and Set the clock frequencies
57pub(crate) unsafe fn init(config: Config) { 45pub(crate) unsafe fn init(config: Config) {
58 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 46 // Calculate the real System clock, and PLL configuration if applicable
59 let clocks = Rcc::new(r, config).freeze(); 47 let (Hertz(sysclk), pll_config) = get_sysclk(&config);
60 set_freqs(clocks); 48 assert!(sysclk <= 72_000_000);
61}
62
63impl<'d> Rcc<'d> {
64 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self {
65 Self {
66 config,
67 phantom: PhantomData,
68 }
69 }
70 49
71 fn freeze(self) -> Clocks { 50 // Calculate real AHB clock
72 // Calculate the real System clock, and PLL configuration if applicable 51 let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk);
73 let (Hertz(sysclk), pll_config) = self.get_sysclk(); 52 let (hpre_bits, hpre_div) = match sysclk / hclk {
74 assert!(sysclk <= 72_000_000); 53 0 => unreachable!(),
54 1 => (Hpre::DIV1, 1),
55 2 => (Hpre::DIV2, 2),
56 3..=5 => (Hpre::DIV4, 4),
57 6..=11 => (Hpre::DIV8, 8),
58 12..=39 => (Hpre::DIV16, 16),
59 40..=95 => (Hpre::DIV64, 64),
60 96..=191 => (Hpre::DIV128, 128),
61 192..=383 => (Hpre::DIV256, 256),
62 _ => (Hpre::DIV512, 512),
63 };
64 let hclk = sysclk / hpre_div;
65 assert!(hclk <= 72_000_000);
75 66
76 // Calculate real AHB clock 67 // Calculate real APB1 clock
77 let hclk = self.config.hclk.map(|h| h.0).unwrap_or(sysclk); 68 let pclk1 = config.pclk1.map(|p| p.0).unwrap_or(hclk);
78 let (hpre_bits, hpre_div) = match sysclk / hclk { 69 let (ppre1_bits, ppre1) = match hclk / pclk1 {
79 0 => unreachable!(), 70 0 => unreachable!(),
80 1 => (Hpre::DIV1, 1), 71 1 => (Ppre::DIV1, 1),
81 2 => (Hpre::DIV2, 2), 72 2 => (Ppre::DIV2, 2),
82 3..=5 => (Hpre::DIV4, 4), 73 3..=5 => (Ppre::DIV4, 4),
83 6..=11 => (Hpre::DIV8, 8), 74 6..=11 => (Ppre::DIV8, 8),
84 12..=39 => (Hpre::DIV16, 16), 75 _ => (Ppre::DIV16, 16),
85 40..=95 => (Hpre::DIV64, 64), 76 };
86 96..=191 => (Hpre::DIV128, 128), 77 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
87 192..=383 => (Hpre::DIV256, 256), 78 let pclk1 = hclk / ppre1;
88 _ => (Hpre::DIV512, 512), 79 assert!(pclk1 <= 36_000_000);
89 };
90 let hclk = sysclk / hpre_div;
91 assert!(hclk <= 72_000_000);
92 80
93 // Calculate real APB1 clock 81 // Calculate real APB2 clock
94 let pclk1 = self.config.pclk1.map(|p| p.0).unwrap_or(hclk); 82 let pclk2 = config.pclk2.map(|p| p.0).unwrap_or(hclk);
95 let (ppre1_bits, ppre1) = match hclk / pclk1 { 83 let (ppre2_bits, ppre2) = match hclk / pclk2 {
96 0 => unreachable!(), 84 0 => unreachable!(),
97 1 => (Ppre::DIV1, 1), 85 1 => (Ppre::DIV1, 1),
98 2 => (Ppre::DIV2, 2), 86 2 => (Ppre::DIV2, 2),
99 3..=5 => (Ppre::DIV4, 4), 87 3..=5 => (Ppre::DIV4, 4),
100 6..=11 => (Ppre::DIV8, 8), 88 6..=11 => (Ppre::DIV8, 8),
101 _ => (Ppre::DIV16, 16), 89 _ => (Ppre::DIV16, 16),
102 }; 90 };
103 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 }; 91 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
104 let pclk1 = hclk / ppre1; 92 let pclk2 = hclk / ppre2;
105 assert!(pclk1 <= 36_000_000); 93 assert!(pclk2 <= 72_000_000);
106 94
107 // Calculate real APB2 clock 95 // Set latency based on HCLK frquency
108 let pclk2 = self.config.pclk2.map(|p| p.0).unwrap_or(hclk); 96 FLASH.acr().write(|w| {
109 let (ppre2_bits, ppre2) = match hclk / pclk2 { 97 w.set_latency(if hclk <= 24_000_000 {
110 0 => unreachable!(), 98 Latency::WS0
111 1 => (Ppre::DIV1, 1), 99 } else if hclk <= 48_000_000 {
112 2 => (Ppre::DIV2, 2), 100 Latency::WS1
113 3..=5 => (Ppre::DIV4, 4), 101 } else {
114 6..=11 => (Ppre::DIV8, 8), 102 Latency::WS2
115 _ => (Ppre::DIV16, 16), 103 });
116 }; 104 });
117 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
118 let pclk2 = hclk / ppre2;
119 assert!(pclk2 <= 72_000_000);
120 105
121 // Set latency based on HCLK frquency 106 // Enable HSE
122 // NOTE(safety) Atomic write 107 if config.hse.is_some() {
123 unsafe { 108 RCC.cr().write(|w| {
124 FLASH.acr().write(|w| { 109 w.set_hsebyp(if config.bypass_hse {
125 w.set_latency(if hclk <= 24_000_000 { 110 Hsebyp::BYPASSED
126 Latency::WS0 111 } else {
127 } else if hclk <= 48_000_000 { 112 Hsebyp::NOTBYPASSED
128 Latency::WS1 113 });
129 } else { 114 // We turn on clock security to switch to HSI when HSE fails
130 Latency::WS2 115 w.set_csson(true);
131 }); 116 w.set_hseon(true);
132 }) 117 });
133 } 118 while !RCC.cr().read().hserdy() {}
119 }
134 120
135 // Enable HSE 121 // Enable PLL
136 if self.config.hse.is_some() { 122 if let Some(ref pll_config) = pll_config {
137 // NOTE(unsafe) We own the peripheral block 123 RCC.cfgr().write(|w| {
138 unsafe { 124 w.set_pllmul(pll_config.pll_mul);
139 RCC.cr().write(|w| { 125 w.set_pllsrc(pll_config.pll_src);
140 w.set_hsebyp(if self.config.bypass_hse { 126 });
141 Hsebyp::BYPASSED 127 if let Some(pll_div) = pll_config.pll_div {
142 } else { 128 RCC.cfgr2().write(|w| w.set_prediv(pll_div));
143 Hsebyp::NOTBYPASSED
144 });
145 // We turn on clock security to switch to HSI when HSE fails
146 w.set_csson(true);
147 w.set_hseon(true);
148 });
149 while !RCC.cr().read().hserdy() {}
150 }
151 } 129 }
130 RCC.cr().modify(|w| w.set_pllon(true));
131 while !RCC.cr().read().pllrdy() {}
132 }
152 133
153 // Enable PLL 134 if config.pll48 {
154 if let Some(ref pll_config) = pll_config { 135 let usb_pre = get_usb_pre(&config, sysclk, pclk1, &pll_config);
155 // NOTE(unsafe) We own the peripheral block 136 RCC.cfgr().write(|w| {
156 unsafe { 137 w.set_usbpre(usb_pre);
157 RCC.cfgr().write(|w| { 138 });
158 w.set_pllmul(pll_config.pll_mul); 139 }
159 w.set_pllsrc(pll_config.pll_src);
160 });
161 if let Some(pll_div) = pll_config.pll_div {
162 RCC.cfgr2().write(|w| w.set_prediv(pll_div));
163 }
164 RCC.cr().modify(|w| w.set_pllon(true));
165 while !RCC.cr().read().pllrdy() {}
166 }
167 }
168 140
169 if self.config.pll48 { 141 // Set prescalers
170 let usb_pre = self.get_usb_pre(sysclk, pclk1, &pll_config); 142 RCC.cfgr().write(|w| {
171 // NOTE(unsafe) We own the peripheral block 143 w.set_ppre2(ppre2_bits);
172 unsafe { 144 w.set_ppre1(ppre1_bits);
173 RCC.cfgr().write(|w| { 145 w.set_hpre(hpre_bits);
174 w.set_usbpre(usb_pre); 146 });
175 });
176 }
177 }
178 147
179 // Set prescalers 148 // Wait for the new prescalers to kick in
180 unsafe { 149 // "The clocks are divided with the new prescaler factor from
181 // NOTE(unsafe) We own the peripheral block 150 // 1 to 16 AHB cycles after write"
182 RCC.cfgr().write(|w| { 151 cortex_m::asm::delay(16);
183 w.set_ppre2(ppre2_bits);
184 w.set_ppre1(ppre1_bits);
185 w.set_hpre(hpre_bits);
186 });
187 152
188 // Wait for the new prescalers to kick in 153 RCC.cfgr().write(|w| {
189 // "The clocks are divided with the new prescaler factor from 154 w.set_sw(match (pll_config, config.hse) {
190 // 1 to 16 AHB cycles after write" 155 (Some(_), _) => Sw::PLL,
191 cortex_m::asm::delay(16); 156 (None, Some(_)) => Sw::HSE,
157 (None, None) => Sw::HSI,
158 })
159 });
192 160
193 // NOTE(unsafe) We own the peripheral block 161 set_freqs(Clocks {
194 RCC.cfgr().write(|w| { 162 sys: Hertz(sysclk),
195 w.set_sw(match (pll_config, self.config.hse) { 163 apb1: Hertz(pclk1),
196 (Some(_), _) => Sw::PLL, 164 apb2: Hertz(pclk2),
197 (None, Some(_)) => Sw::HSE, 165 apb1_tim: Hertz(pclk1 * timer_mul1),
198 (None, None) => Sw::HSI, 166 apb2_tim: Hertz(pclk2 * timer_mul2),
199 }) 167 ahb: Hertz(hclk),
200 }); 168 });
201 } 169}
202 170
203 Clocks { 171#[inline]
204 sys: Hertz(sysclk), 172fn get_sysclk(config: &Config) -> (Hertz, Option<PllConfig>) {
205 apb1: Hertz(pclk1), 173 match (config.sysclk, config.hse) {
206 apb2: Hertz(pclk2), 174 (Some(sysclk), Some(hse)) if sysclk == hse => (hse, None),
207 apb1_tim: Hertz(pclk1 * timer_mul1), 175 (Some(sysclk), None) if sysclk.0 == HSI => (Hertz(HSI), None),
208 apb2_tim: Hertz(pclk2 * timer_mul2), 176 // If the user selected System clock is different from HSI or HSE
209 ahb: Hertz(hclk), 177 // we will have to setup PLL clock source
178 (Some(sysclk), _) => {
179 let (sysclk, pll_config) = calc_pll(config, sysclk);
180 (sysclk, Some(pll_config))
210 } 181 }
182 (None, Some(hse)) => (hse, None),
183 (None, None) => (Hertz(HSI), None),
211 } 184 }
185}
212 186
213 #[inline] 187#[inline]
214 fn get_sysclk(&self) -> (Hertz, Option<PllConfig>) { 188fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
215 match (self.config.sysclk, self.config.hse) { 189 // Calculates the Multiplier and the Divisor to arrive at
216 (Some(sysclk), Some(hse)) if sysclk == hse => (hse, None), 190 // the required System clock from PLL source frequency
217 (Some(sysclk), None) if sysclk.0 == HSI => (Hertz(HSI), None), 191 let get_mul_div = |sysclk, pllsrcclk| {
218 // If the user selected System clock is different from HSI or HSE 192 let common_div = gcd(sysclk, pllsrcclk);
219 // we will have to setup PLL clock source 193 let mut multiplier = sysclk / common_div;
220 (Some(sysclk), _) => { 194 let mut divisor = pllsrcclk / common_div;
221 let (sysclk, pll_config) = self.calc_pll(sysclk); 195 // Minimum PLL multiplier is two
222 (sysclk, Some(pll_config)) 196 if multiplier == 1 {
223 } 197 multiplier *= 2;
224 (None, Some(hse)) => (hse, None), 198 divisor *= 2;
225 (None, None) => (Hertz(HSI), None),
226 } 199 }
227 } 200 assert!(multiplier <= 16);
228 201 assert!(divisor <= 16);
229 #[inline] 202 (multiplier, divisor)
230 fn calc_pll(&self, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) { 203 };
231 // Calculates the Multiplier and the Divisor to arrive at 204 // Based on the source of Pll, we calculate the actual system clock
232 // the required System clock from PLL source frequency 205 // frequency, PLL's source identifier, multiplier and divisor
233 let get_mul_div = |sysclk, pllsrcclk| { 206 let (act_sysclk, pll_src, pll_mul, pll_div) = match config.hse {
234 let common_div = gcd(sysclk, pllsrcclk); 207 Some(Hertz(hse)) => {
235 let mut multiplier = sysclk / common_div; 208 let (multiplier, divisor) = get_mul_div(sysclk, hse);
236 let mut divisor = pllsrcclk / common_div; 209 (
237 // Minimum PLL multiplier is two 210 Hertz((hse / divisor) * multiplier),
238 if multiplier == 1 { 211 Pllsrc::HSE_DIV_PREDIV,
239 multiplier *= 2; 212 into_pll_mul(multiplier),
240 divisor *= 2; 213 Some(into_pre_div(divisor)),
241 } 214 )
242 assert!(multiplier <= 16); 215 }
243 assert!(divisor <= 16); 216 None => {
244 (multiplier, divisor) 217 cfg_if::cfg_if! {
245 }; 218 // For some chips PREDIV is always two, and cannot be changed
246 // Based on the source of Pll, we calculate the actual system clock 219 if #[cfg(any(
247 // frequency, PLL's source identifier, multiplier and divisor 220 feature="stm32f302xd", feature="stm32f302xe", feature="stm32f303xd",
248 let (act_sysclk, pll_src, pll_mul, pll_div) = match self.config.hse { 221 feature="stm32f303xe", feature="stm32f398xe"
249 Some(Hertz(hse)) => { 222 ))] {
250 let (multiplier, divisor) = get_mul_div(sysclk, hse); 223 let (multiplier, divisor) = get_mul_div(sysclk, HSI);
251 ( 224 (
252 Hertz((hse / divisor) * multiplier), 225 Hertz((hse / divisor) * multiplier),
253 Pllsrc::HSE_DIV_PREDIV, 226 Pllsrc::HSI_DIV_PREDIV,
254 into_pll_mul(multiplier), 227 into_pll_mul(multiplier),
255 Some(into_pre_div(divisor)), 228 Some(into_pre_div(divisor)),
256 ) 229 )
257 } 230 } else {
258 None => { 231 let pllsrcclk = HSI / 2;
259 cfg_if::cfg_if! { 232 let multiplier = sysclk / pllsrcclk;
260 // For some chips PREDIV is always two, and cannot be changed 233 assert!(multiplier <= 16);
261 if #[cfg(any( 234 (
262 feature="stm32f302xd", feature="stm32f302xe", feature="stm32f303xd", 235 Hertz(pllsrcclk * multiplier),
263 feature="stm32f303xe", feature="stm32f398xe" 236 Pllsrc::HSI_DIV2,
264 ))] { 237 into_pll_mul(multiplier),
265 let (multiplier, divisor) = get_mul_div(sysclk, HSI); 238 None,
266 ( 239 )
267 Hertz((hse / divisor) * multiplier),
268 Pllsrc::HSI_DIV_PREDIV,
269 into_pll_mul(multiplier),
270 Some(into_pre_div(divisor)),
271 )
272 } else {
273 let pllsrcclk = HSI / 2;
274 let multiplier = sysclk / pllsrcclk;
275 assert!(multiplier <= 16);
276 (
277 Hertz(pllsrcclk * multiplier),
278 Pllsrc::HSI_DIV2,
279 into_pll_mul(multiplier),
280 None,
281 )
282 }
283 } 240 }
284 } 241 }
285 }; 242 }
286 ( 243 };
287 act_sysclk, 244 (
288 PllConfig { 245 act_sysclk,
289 pll_src, 246 PllConfig {
290 pll_mul, 247 pll_src,
291 pll_div, 248 pll_mul,
292 }, 249 pll_div,
293 ) 250 },
294 } 251 )
252}
295 253
296 #[inline] 254#[inline]
297 fn get_usb_pre(&self, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre { 255fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option<PllConfig>) -> Usbpre {
298 cfg_if::cfg_if! { 256 cfg_if::cfg_if! {
299 // Some chips do not have USB 257 // Some chips do not have USB
300 if #[cfg(any(stm32f301, stm32f318, stm32f334))] { 258 if #[cfg(any(stm32f301, stm32f318, stm32f334))] {
301 panic!("USB clock not supported by the chip"); 259 panic!("USB clock not supported by the chip");
302 } else { 260 } else {
303 let usb_ok = self.config.hse.is_some() && pll_config.is_some() && (pclk1 >= 10_000_000); 261 let usb_ok = config.hse.is_some() && pll_config.is_some() && (pclk1 >= 10_000_000);
304 match (usb_ok, sysclk) { 262 match (usb_ok, sysclk) {
305 (true, 72_000_000) => Usbpre::DIV1_5, 263 (true, 72_000_000) => Usbpre::DIV1_5,
306 (true, 48_000_000) => Usbpre::DIV1, 264 (true, 48_000_000) => Usbpre::DIV1,
307 _ => panic!( 265 _ => panic!(
308 "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz" 266 "USB clock is only valid if the PLL output frequency is either 48MHz or 72MHz"
309 ), 267 ),
310 }
311 } 268 }
312 } 269 }
313 } 270 }
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
index 58a08adbf..aba8fc0ef 100644
--- a/embassy-stm32/src/rcc/f4.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -1,9 +1,8 @@
1use super::sealed::RccPeripheral;
2use crate::pac::rcc::vals::{Hpre, Hsebyp, Ppre, Sw};
1use crate::pac::{FLASH, PWR, RCC}; 3use crate::pac::{FLASH, PWR, RCC};
2use crate::peripherals; 4use crate::rcc::{set_freqs, Clocks};
3use crate::rcc::{get_freqs, set_freqs, Clocks};
4use crate::time::Hertz; 5use crate::time::Hertz;
5use core::marker::PhantomData;
6use embassy::util::Unborrow;
7 6
8const HSI: u32 = 16_000_000; 7const HSI: u32 = 16_000_000;
9 8
@@ -21,284 +20,240 @@ pub struct Config {
21 pub pll48: bool, 20 pub pll48: bool,
22} 21}
23 22
24/// RCC peripheral 23unsafe fn setup_pll(
25pub struct Rcc<'d> { 24 pllsrcclk: u32,
26 config: Config, 25 use_hse: bool,
27 phantom: PhantomData<&'d mut peripherals::RCC>, 26 pllsysclk: Option<u32>,
28} 27 pll48clk: bool,
29 28) -> PllResults {
30impl<'d> Rcc<'d> { 29 use crate::pac::rcc::vals::{Pllp, Pllsrc};
31 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { 30
32 Self { 31 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
33 config, 32 if pllsysclk.is_none() && !pll48clk {
34 phantom: PhantomData, 33 RCC.pllcfgr()
35 } 34 .modify(|w| w.set_pllsrc(Pllsrc(use_hse as u8)));
36 } 35
37 36 return PllResults {
38 fn freeze(mut self) -> Clocks { 37 use_pll: false,
39 use super::sealed::RccPeripheral; 38 pllsysclk: None,
40 use crate::pac::rcc::vals::{Hpre, Hsebyp, Ppre, Sw}; 39 pll48clk: None,
41
42 peripherals::PWR::enable();
43
44 let pllsrcclk = self.config.hse.map(|hse| hse.0).unwrap_or(HSI);
45 let sysclk = self.config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk);
46 let sysclk_on_pll = sysclk != pllsrcclk;
47
48 let plls = self.setup_pll(
49 pllsrcclk,
50 self.config.hse.is_some(),
51 if sysclk_on_pll { Some(sysclk) } else { None },
52 self.config.pll48,
53 );
54
55 if self.config.pll48 {
56 let freq = unwrap!(plls.pll48clk);
57
58 assert!((max::PLL_48_CLK as i32 - freq as i32).abs() <= max::PLL_48_TOLERANCE as i32);
59 }
60
61 let sysclk = if sysclk_on_pll {
62 unwrap!(plls.pllsysclk)
63 } else {
64 sysclk
65 };
66
67 // AHB prescaler
68 let hclk = self.config.hclk.map(|h| h.0).unwrap_or(sysclk);
69 let (hpre_bits, hpre_div) = match (sysclk + hclk - 1) / hclk {
70 0 => unreachable!(),
71 1 => (Hpre::DIV1, 1),
72 2 => (Hpre::DIV2, 2),
73 3..=5 => (Hpre::DIV4, 4),
74 6..=11 => (Hpre::DIV8, 8),
75 12..=39 => (Hpre::DIV16, 16),
76 40..=95 => (Hpre::DIV64, 64),
77 96..=191 => (Hpre::DIV128, 128),
78 192..=383 => (Hpre::DIV256, 256),
79 _ => (Hpre::DIV512, 512),
80 };
81
82 // Calculate real AHB clock
83 let hclk = sysclk / hpre_div;
84
85 let pclk1 = self
86 .config
87 .pclk1
88 .map(|p| p.0)
89 .unwrap_or_else(|| core::cmp::min(max::PCLK1_MAX, hclk));
90
91 let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 {
92 0 => unreachable!(),
93 1 => (0b000, 1),
94 2 => (0b100, 2),
95 3..=5 => (0b101, 4),
96 6..=11 => (0b110, 8),
97 _ => (0b111, 16),
98 };
99 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
100
101 // Calculate real APB1 clock
102 let pclk1 = hclk / ppre1;
103 assert!(pclk1 <= max::PCLK1_MAX);
104
105 let pclk2 = self
106 .config
107 .pclk2
108 .map(|p| p.0)
109 .unwrap_or_else(|| core::cmp::min(max::PCLK2_MAX, hclk));
110 let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 {
111 0 => unreachable!(),
112 1 => (0b000, 1),
113 2 => (0b100, 2),
114 3..=5 => (0b101, 4),
115 6..=11 => (0b110, 8),
116 _ => (0b111, 16),
117 }; 40 };
118 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 }; 41 }
119 42 // Input divisor from PLL source clock, must result to frequency in
120 // Calculate real APB2 clock 43 // the range from 1 to 2 MHz
121 let pclk2 = hclk / ppre2; 44 let pllm_min = (pllsrcclk + 1_999_999) / 2_000_000;
122 assert!(pclk2 <= max::PCLK2_MAX); 45 let pllm_max = pllsrcclk / 1_000_000;
123 46
124 Self::flash_setup(sysclk); 47 // Sysclk output divisor must be one of 2, 4, 6 or 8
125 48 let sysclk_div = core::cmp::min(8, (432_000_000 / sysclk) & !1);
126 if self.config.hse.is_some() { 49
127 // NOTE(unsafe) We own the peripheral block 50 let target_freq = if pll48clk {
128 unsafe { 51 48_000_000
129 RCC.cr().modify(|w| { 52 } else {
130 w.set_hsebyp(Hsebyp(self.config.bypass_hse as u8)); 53 sysclk * sysclk_div
131 w.set_hseon(true); 54 };
132 }); 55
133 while !RCC.cr().read().hserdy() {} 56 // Find the lowest pllm value that minimize the difference between
134 } 57 // target frequency and the real vco_out frequency.
135 } 58 let pllm = unwrap!((pllm_min..=pllm_max).min_by_key(|pllm| {
136 59 let vco_in = pllsrcclk / pllm;
137 if plls.use_pll { 60 let plln = target_freq / vco_in;
138 unsafe { 61 target_freq - vco_in * plln
139 RCC.cr().modify(|w| w.set_pllon(true)); 62 }));
63
64 let vco_in = pllsrcclk / pllm;
65 assert!((1_000_000..=2_000_000).contains(&vco_in));
66
67 // Main scaler, must result in >= 100MHz (>= 192MHz for F401)
68 // and <= 432MHz, min 50, max 432
69 let plln = if pll48clk {
70 // try the different valid pllq according to the valid
71 // main scaller values, and take the best
72 let pllq = unwrap!((4..=9).min_by_key(|pllq| {
73 let plln = 48_000_000 * pllq / vco_in;
74 let pll48_diff = 48_000_000 - vco_in * plln / pllq;
75 let sysclk_diff = (sysclk as i32 - (vco_in * plln / sysclk_div) as i32).abs();
76 (pll48_diff, sysclk_diff)
77 }));
78 48_000_000 * pllq / vco_in
79 } else {
80 sysclk * sysclk_div / vco_in
81 };
82
83 let pllp = (sysclk_div / 2) - 1;
84
85 let pllq = (vco_in * plln + 47_999_999) / 48_000_000;
86 let real_pll48clk = vco_in * plln / pllq;
87
88 RCC.pllcfgr().modify(|w| {
89 w.set_pllm(pllm as u8);
90 w.set_plln(plln as u16);
91 w.set_pllp(Pllp(pllp as u8));
92 w.set_pllq(pllq as u8);
93 w.set_pllsrc(Pllsrc(use_hse as u8));
94 });
95
96 let real_pllsysclk = vco_in * plln / sysclk_div;
97
98 PllResults {
99 use_pll: true,
100 pllsysclk: Some(real_pllsysclk),
101 pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
102 }
103}
140 104
141 if hclk > max::HCLK_OVERDRIVE_FREQUENCY { 105unsafe fn flash_setup(sysclk: u32) {
142 PWR.cr1().modify(|w| w.set_oden(true)); 106 use crate::pac::flash::vals::Latency;
143 while !PWR.csr1().read().odrdy() {}
144 107
145 PWR.cr1().modify(|w| w.set_odswen(true)); 108 // Be conservative with voltage ranges
146 while !PWR.csr1().read().odswrdy() {} 109 const FLASH_LATENCY_STEP: u32 = 30_000_000;
147 }
148 110
149 while !RCC.cr().read().pllrdy() {} 111 critical_section::with(|_| {
150 } 112 FLASH
151 } 113 .acr()
114 .modify(|w| w.set_latency(Latency(((sysclk - 1) / FLASH_LATENCY_STEP) as u8)));
115 });
116}
152 117
153 unsafe { 118pub(crate) unsafe fn init(config: Config) {
154 RCC.cfgr().modify(|w| { 119 crate::peripherals::PWR::enable();
155 w.set_ppre2(Ppre(ppre2_bits));
156 w.set_ppre1(Ppre(ppre1_bits));
157 w.set_hpre(hpre_bits);
158 });
159
160 // Wait for the new prescalers to kick in
161 // "The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after write"
162 cortex_m::asm::delay(16);
163
164 RCC.cfgr().modify(|w| {
165 w.set_sw(if sysclk_on_pll {
166 Sw::PLL
167 } else if self.config.hse.is_some() {
168 Sw::HSE
169 } else {
170 Sw::HSI
171 })
172 });
173 }
174 120
175 Clocks { 121 let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI);
176 sys: Hertz(sysclk), 122 let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk);
177 apb1: Hertz(pclk1), 123 let sysclk_on_pll = sysclk != pllsrcclk;
178 apb2: Hertz(pclk2),
179 124
180 apb1_tim: Hertz(pclk1 * timer_mul1), 125 let plls = setup_pll(
181 apb2_tim: Hertz(pclk2 * timer_mul2), 126 pllsrcclk,
127 config.hse.is_some(),
128 if sysclk_on_pll { Some(sysclk) } else { None },
129 config.pll48,
130 );
182 131
183 ahb1: Hertz(hclk), 132 if config.pll48 {
184 ahb2: Hertz(hclk), 133 let freq = unwrap!(plls.pll48clk);
185 ahb3: Hertz(hclk),
186 134
187 pll48: plls.pll48clk.map(Hertz), 135 assert!((max::PLL_48_CLK as i32 - freq as i32).abs() <= max::PLL_48_TOLERANCE as i32);
188 }
189 } 136 }
190 137
191 // Safety: RCC init must have been called 138 let sysclk = if sysclk_on_pll {
192 pub fn clocks(&self) -> &'static Clocks { 139 unwrap!(plls.pllsysclk)
193 unsafe { get_freqs() } 140 } else {
141 sysclk
142 };
143
144 // AHB prescaler
145 let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk);
146 let (hpre_bits, hpre_div) = match (sysclk + hclk - 1) / hclk {
147 0 => unreachable!(),
148 1 => (Hpre::DIV1, 1),
149 2 => (Hpre::DIV2, 2),
150 3..=5 => (Hpre::DIV4, 4),
151 6..=11 => (Hpre::DIV8, 8),
152 12..=39 => (Hpre::DIV16, 16),
153 40..=95 => (Hpre::DIV64, 64),
154 96..=191 => (Hpre::DIV128, 128),
155 192..=383 => (Hpre::DIV256, 256),
156 _ => (Hpre::DIV512, 512),
157 };
158
159 // Calculate real AHB clock
160 let hclk = sysclk / hpre_div;
161
162 let pclk1 = config
163 .pclk1
164 .map(|p| p.0)
165 .unwrap_or_else(|| core::cmp::min(max::PCLK1_MAX, hclk));
166
167 let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 {
168 0 => unreachable!(),
169 1 => (0b000, 1),
170 2 => (0b100, 2),
171 3..=5 => (0b101, 4),
172 6..=11 => (0b110, 8),
173 _ => (0b111, 16),
174 };
175 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
176
177 // Calculate real APB1 clock
178 let pclk1 = hclk / ppre1;
179 assert!(pclk1 <= max::PCLK1_MAX);
180
181 let pclk2 = config
182 .pclk2
183 .map(|p| p.0)
184 .unwrap_or_else(|| core::cmp::min(max::PCLK2_MAX, hclk));
185 let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 {
186 0 => unreachable!(),
187 1 => (0b000, 1),
188 2 => (0b100, 2),
189 3..=5 => (0b101, 4),
190 6..=11 => (0b110, 8),
191 _ => (0b111, 16),
192 };
193 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
194
195 // Calculate real APB2 clock
196 let pclk2 = hclk / ppre2;
197 assert!(pclk2 <= max::PCLK2_MAX);
198
199 flash_setup(sysclk);
200
201 if config.hse.is_some() {
202 RCC.cr().modify(|w| {
203 w.set_hsebyp(Hsebyp(config.bypass_hse as u8));
204 w.set_hseon(true);
205 });
206 while !RCC.cr().read().hserdy() {}
194 } 207 }
195 208
196 fn setup_pll( 209 if plls.use_pll {
197 &mut self, 210 RCC.cr().modify(|w| w.set_pllon(true));
198 pllsrcclk: u32,
199 use_hse: bool,
200 pllsysclk: Option<u32>,
201 pll48clk: bool,
202 ) -> PllResults {
203 use crate::pac::rcc::vals::{Pllp, Pllsrc};
204
205 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
206 if pllsysclk.is_none() && !pll48clk {
207 // NOTE(unsafe) We have a mutable borrow to the owner of the RegBlock
208 unsafe {
209 RCC.pllcfgr()
210 .modify(|w| w.set_pllsrc(Pllsrc(use_hse as u8)));
211 }
212
213 return PllResults {
214 use_pll: false,
215 pllsysclk: None,
216 pll48clk: None,
217 };
218 }
219 // Input divisor from PLL source clock, must result to frequency in
220 // the range from 1 to 2 MHz
221 let pllm_min = (pllsrcclk + 1_999_999) / 2_000_000;
222 let pllm_max = pllsrcclk / 1_000_000;
223
224 // Sysclk output divisor must be one of 2, 4, 6 or 8
225 let sysclk_div = core::cmp::min(8, (432_000_000 / sysclk) & !1);
226
227 let target_freq = if pll48clk {
228 48_000_000
229 } else {
230 sysclk * sysclk_div
231 };
232
233 // Find the lowest pllm value that minimize the difference between
234 // target frequency and the real vco_out frequency.
235 let pllm = unwrap!((pllm_min..=pllm_max).min_by_key(|pllm| {
236 let vco_in = pllsrcclk / pllm;
237 let plln = target_freq / vco_in;
238 target_freq - vco_in * plln
239 }));
240
241 let vco_in = pllsrcclk / pllm;
242 assert!((1_000_000..=2_000_000).contains(&vco_in));
243
244 // Main scaler, must result in >= 100MHz (>= 192MHz for F401)
245 // and <= 432MHz, min 50, max 432
246 let plln = if pll48clk {
247 // try the different valid pllq according to the valid
248 // main scaller values, and take the best
249 let pllq = unwrap!((4..=9).min_by_key(|pllq| {
250 let plln = 48_000_000 * pllq / vco_in;
251 let pll48_diff = 48_000_000 - vco_in * plln / pllq;
252 let sysclk_diff = (sysclk as i32 - (vco_in * plln / sysclk_div) as i32).abs();
253 (pll48_diff, sysclk_diff)
254 }));
255 48_000_000 * pllq / vco_in
256 } else {
257 sysclk * sysclk_div / vco_in
258 };
259 211
260 let pllp = (sysclk_div / 2) - 1; 212 if hclk > max::HCLK_OVERDRIVE_FREQUENCY {
213 PWR.cr1().modify(|w| w.set_oden(true));
214 while !PWR.csr1().read().odrdy() {}
261 215
262 let pllq = (vco_in * plln + 47_999_999) / 48_000_000; 216 PWR.cr1().modify(|w| w.set_odswen(true));
263 let real_pll48clk = vco_in * plln / pllq; 217 while !PWR.csr1().read().odswrdy() {}
264
265 unsafe {
266 RCC.pllcfgr().modify(|w| {
267 w.set_pllm(pllm as u8);
268 w.set_plln(plln as u16);
269 w.set_pllp(Pllp(pllp as u8));
270 w.set_pllq(pllq as u8);
271 w.set_pllsrc(Pllsrc(use_hse as u8));
272 });
273 } 218 }
274 219
275 let real_pllsysclk = vco_in * plln / sysclk_div; 220 while !RCC.cr().read().pllrdy() {}
276
277 PllResults {
278 use_pll: true,
279 pllsysclk: Some(real_pllsysclk),
280 pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
281 }
282 } 221 }
283 222
284 fn flash_setup(sysclk: u32) { 223 RCC.cfgr().modify(|w| {
285 use crate::pac::flash::vals::Latency; 224 w.set_ppre2(Ppre(ppre2_bits));
225 w.set_ppre1(Ppre(ppre1_bits));
226 w.set_hpre(hpre_bits);
227 });
228
229 // Wait for the new prescalers to kick in
230 // "The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after write"
231 cortex_m::asm::delay(16);
232
233 RCC.cfgr().modify(|w| {
234 w.set_sw(if sysclk_on_pll {
235 Sw::PLL
236 } else if config.hse.is_some() {
237 Sw::HSE
238 } else {
239 Sw::HSI
240 })
241 });
286 242
287 // Be conservative with voltage ranges 243 set_freqs(Clocks {
288 const FLASH_LATENCY_STEP: u32 = 30_000_000; 244 sys: Hertz(sysclk),
245 apb1: Hertz(pclk1),
246 apb2: Hertz(pclk2),
289 247
290 critical_section::with(|_| unsafe { 248 apb1_tim: Hertz(pclk1 * timer_mul1),
291 FLASH 249 apb2_tim: Hertz(pclk2 * timer_mul2),
292 .acr()
293 .modify(|w| w.set_latency(Latency(((sysclk - 1) / FLASH_LATENCY_STEP) as u8)));
294 });
295 }
296}
297 250
298pub(crate) unsafe fn init(config: Config) { 251 ahb1: Hertz(hclk),
299 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 252 ahb2: Hertz(hclk),
300 let clocks = Rcc::new(r, config).freeze(); 253 ahb3: Hertz(hclk),
301 set_freqs(clocks); 254
255 pll48: plls.pll48clk.map(Hertz),
256 });
302} 257}
303 258
304struct PllResults { 259struct PllResults {
diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs
index d29ba31f0..1a0530296 100644
--- a/embassy-stm32/src/rcc/f7.rs
+++ b/embassy-stm32/src/rcc/f7.rs
@@ -1,9 +1,9 @@
1use super::sealed::RccPeripheral;
2use crate::pac::pwr::vals::Vos;
3use crate::pac::rcc::vals::{Hpre, Hsebyp, Ppre, Sw};
1use crate::pac::{FLASH, PWR, RCC}; 4use crate::pac::{FLASH, PWR, RCC};
2use crate::peripherals; 5use crate::rcc::{set_freqs, Clocks};
3use crate::rcc::{get_freqs, set_freqs, Clocks};
4use crate::time::Hertz; 6use crate::time::Hertz;
5use core::marker::PhantomData;
6use embassy::util::Unborrow;
7 7
8const HSI: u32 = 16_000_000; 8const HSI: u32 = 16_000_000;
9 9
@@ -21,318 +21,274 @@ pub struct Config {
21 pub pll48: bool, 21 pub pll48: bool,
22} 22}
23 23
24/// RCC peripheral 24unsafe fn setup_pll(
25pub struct Rcc<'d> { 25 pllsrcclk: u32,
26 config: Config, 26 use_hse: bool,
27 phantom: PhantomData<&'d mut peripherals::RCC>, 27 pllsysclk: Option<u32>,
28} 28 pll48clk: bool,
29 29) -> PllResults {
30impl<'d> Rcc<'d> { 30 use crate::pac::rcc::vals::{Pllp, Pllsrc};
31 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { 31
32 if let Some(hse) = config.hse { 32 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
33 if config.bypass_hse { 33 if pllsysclk.is_none() && !pll48clk {
34 assert!((max::HSE_BYPASS_MIN..=max::HSE_BYPASS_MAX).contains(&hse.0)); 34 RCC.pllcfgr()
35 } else { 35 .modify(|w| w.set_pllsrc(Pllsrc(use_hse as u8)));
36 assert!((max::HSE_OSC_MIN..=max::HSE_OSC_MAX).contains(&hse.0)); 36
37 } 37 return PllResults {
38 } 38 use_pll: false,
39 Self { 39 pllsysclk: None,
40 config, 40 pll48clk: None,
41 phantom: PhantomData, 41 };
42 }
43 } 42 }
43 // Input divisor from PLL source clock, must result to frequency in
44 // the range from 1 to 2 MHz
45 let pllm_min = (pllsrcclk + 1_999_999) / 2_000_000;
46 let pllm_max = pllsrcclk / 1_000_000;
47
48 // Sysclk output divisor must be one of 2, 4, 6 or 8
49 let sysclk_div = core::cmp::min(8, (432_000_000 / sysclk) & !1);
50
51 let target_freq = if pll48clk {
52 48_000_000
53 } else {
54 sysclk * sysclk_div
55 };
56
57 // Find the lowest pllm value that minimize the difference between
58 // target frequency and the real vco_out frequency.
59 let pllm = unwrap!((pllm_min..=pllm_max).min_by_key(|pllm| {
60 let vco_in = pllsrcclk / pllm;
61 let plln = target_freq / vco_in;
62 target_freq - vco_in * plln
63 }));
64
65 let vco_in = pllsrcclk / pllm;
66 assert!((1_000_000..=2_000_000).contains(&vco_in));
67
68 // Main scaler, must result in >= 100MHz (>= 192MHz for F401)
69 // and <= 432MHz, min 50, max 432
70 let plln = if pll48clk {
71 // try the different valid pllq according to the valid
72 // main scaller values, and take the best
73 let pllq = unwrap!((4..=9).min_by_key(|pllq| {
74 let plln = 48_000_000 * pllq / vco_in;
75 let pll48_diff = 48_000_000 - vco_in * plln / pllq;
76 let sysclk_diff = (sysclk as i32 - (vco_in * plln / sysclk_div) as i32).abs();
77 (pll48_diff, sysclk_diff)
78 }));
79 48_000_000 * pllq / vco_in
80 } else {
81 sysclk * sysclk_div / vco_in
82 };
83
84 let pllp = (sysclk_div / 2) - 1;
85
86 let pllq = (vco_in * plln + 47_999_999) / 48_000_000;
87 let real_pll48clk = vco_in * plln / pllq;
88
89 RCC.pllcfgr().modify(|w| {
90 w.set_pllm(pllm as u8);
91 w.set_plln(plln as u16);
92 w.set_pllp(Pllp(pllp as u8));
93 w.set_pllq(pllq as u8);
94 w.set_pllsrc(Pllsrc(use_hse as u8));
95 });
96
97 let real_pllsysclk = vco_in * plln / sysclk_div;
98
99 PllResults {
100 use_pll: true,
101 pllsysclk: Some(real_pllsysclk),
102 pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
103 }
104}
44 105
45 fn freeze(mut self) -> Clocks { 106unsafe fn flash_setup(sysclk: u32) {
46 use super::sealed::RccPeripheral; 107 use crate::pac::flash::vals::Latency;
47 use crate::pac::pwr::vals::Vos;
48 use crate::pac::rcc::vals::{Hpre, Hsebyp, Ppre, Sw};
49
50 peripherals::PWR::enable();
51
52 let pllsrcclk = self.config.hse.map(|hse| hse.0).unwrap_or(HSI);
53 let sysclk = self.config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk);
54 let sysclk_on_pll = sysclk != pllsrcclk;
55
56 assert!((max::SYSCLK_MIN..=max::SYSCLK_MAX).contains(&sysclk));
57 108
58 let plls = self.setup_pll( 109 // Be conservative with voltage ranges
59 pllsrcclk, 110 const FLASH_LATENCY_STEP: u32 = 30_000_000;
60 self.config.hse.is_some(),
61 if sysclk_on_pll { Some(sysclk) } else { None },
62 self.config.pll48,
63 );
64 111
65 if self.config.pll48 { 112 critical_section::with(|_| {
66 let freq = unwrap!(plls.pll48clk); 113 FLASH
114 .acr()
115 .modify(|w| w.set_latency(Latency(((sysclk - 1) / FLASH_LATENCY_STEP) as u8)));
116 });
117}
67 118
68 assert!((max::PLL_48_CLK as i32 - freq as i32).abs() <= max::PLL_48_TOLERANCE as i32); 119pub(crate) unsafe fn init(config: Config) {
69 } 120 crate::peripherals::PWR::enable();
70 121
71 let sysclk = if sysclk_on_pll { 122 if let Some(hse) = config.hse {
72 unwrap!(plls.pllsysclk) 123 if config.bypass_hse {
124 assert!((max::HSE_BYPASS_MIN..=max::HSE_BYPASS_MAX).contains(&hse.0));
73 } else { 125 } else {
74 sysclk 126 assert!((max::HSE_OSC_MIN..=max::HSE_OSC_MAX).contains(&hse.0));
75 };
76
77 // AHB prescaler
78 let hclk = self.config.hclk.map(|h| h.0).unwrap_or(sysclk);
79 let (hpre_bits, hpre_div) = match (sysclk + hclk - 1) / hclk {
80 0 => unreachable!(),
81 1 => (Hpre::DIV1, 1),
82 2 => (Hpre::DIV2, 2),
83 3..=5 => (Hpre::DIV4, 4),
84 6..=11 => (Hpre::DIV8, 8),
85 12..=39 => (Hpre::DIV16, 16),
86 40..=95 => (Hpre::DIV64, 64),
87 96..=191 => (Hpre::DIV128, 128),
88 192..=383 => (Hpre::DIV256, 256),
89 _ => (Hpre::DIV512, 512),
90 };
91
92 // Calculate real AHB clock
93 let hclk = sysclk / hpre_div;
94
95 assert!(hclk < max::HCLK_MAX);
96
97 let pclk1 = self
98 .config
99 .pclk1
100 .map(|p| p.0)
101 .unwrap_or_else(|| core::cmp::min(max::PCLK1_MAX, hclk));
102
103 let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 {
104 0 => unreachable!(),
105 1 => (0b000, 1),
106 2 => (0b100, 2),
107 3..=5 => (0b101, 4),
108 6..=11 => (0b110, 8),
109 _ => (0b111, 16),
110 };
111 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
112
113 // Calculate real APB1 clock
114 let pclk1 = hclk / ppre1;
115 assert!((max::PCLK1_MIN..=max::PCLK1_MAX).contains(&pclk1));
116
117 let pclk2 = self
118 .config
119 .pclk2
120 .map(|p| p.0)
121 .unwrap_or_else(|| core::cmp::min(max::PCLK2_MAX, hclk));
122 let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 {
123 0 => unreachable!(),
124 1 => (0b000, 1),
125 2 => (0b100, 2),
126 3..=5 => (0b101, 4),
127 6..=11 => (0b110, 8),
128 _ => (0b111, 16),
129 };
130 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
131
132 // Calculate real APB2 clock
133 let pclk2 = hclk / ppre2;
134 assert!((max::PCLK2_MIN..=max::PCLK2_MAX).contains(&pclk2));
135
136 Self::flash_setup(sysclk);
137
138 if self.config.hse.is_some() {
139 // NOTE(unsafe) We own the peripheral block
140 unsafe {
141 RCC.cr().modify(|w| {
142 w.set_hsebyp(Hsebyp(self.config.bypass_hse as u8));
143 w.set_hseon(true);
144 });
145 while !RCC.cr().read().hserdy() {}
146 }
147 }
148
149 if plls.use_pll {
150 unsafe {
151 RCC.cr().modify(|w| w.set_pllon(false));
152
153 // enable PWR and setup VOSScale
154
155 RCC.apb1enr().modify(|w| w.set_pwren(true));
156
157 let vos_scale = if sysclk <= 144_000_000 {
158 3
159 } else if sysclk <= 168_000_000 {
160 2
161 } else {
162 1
163 };
164 PWR.cr1().modify(|w| {
165 w.set_vos(match vos_scale {
166 3 => Vos::SCALE3,
167 2 => Vos::SCALE2,
168 1 => Vos::SCALE1,
169 _ => panic!("Invalid VOS Scale."),
170 })
171 });
172
173 RCC.cr().modify(|w| w.set_pllon(true));
174
175 if hclk > max::HCLK_OVERDRIVE_FREQUENCY {
176 PWR.cr1().modify(|w| w.set_oden(true));
177 while !PWR.csr1().read().odrdy() {}
178
179 PWR.cr1().modify(|w| w.set_odswen(true));
180 while !PWR.csr1().read().odswrdy() {}
181 }
182
183 while !RCC.cr().read().pllrdy() {}
184 }
185 } 127 }
128 }
186 129
187 unsafe { 130 let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI);
188 RCC.cfgr().modify(|w| { 131 let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk);
189 w.set_ppre2(Ppre(ppre2_bits)); 132 let sysclk_on_pll = sysclk != pllsrcclk;
190 w.set_ppre1(Ppre(ppre1_bits));
191 w.set_hpre(hpre_bits);
192 });
193
194 // Wait for the new prescalers to kick in
195 // "The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after write"
196 cortex_m::asm::delay(16);
197
198 RCC.cfgr().modify(|w| {
199 w.set_sw(if sysclk_on_pll {
200 Sw::PLL
201 } else if self.config.hse.is_some() {
202 Sw::HSE
203 } else {
204 Sw::HSI
205 })
206 });
207 }
208 133
209 Clocks { 134 assert!((max::SYSCLK_MIN..=max::SYSCLK_MAX).contains(&sysclk));
210 sys: Hertz(sysclk),
211 apb1: Hertz(pclk1),
212 apb2: Hertz(pclk2),
213 135
214 apb1_tim: Hertz(pclk1 * timer_mul1), 136 let plls = setup_pll(
215 apb2_tim: Hertz(pclk2 * timer_mul2), 137 pllsrcclk,
138 config.hse.is_some(),
139 if sysclk_on_pll { Some(sysclk) } else { None },
140 config.pll48,
141 );
216 142
217 ahb1: Hertz(hclk), 143 if config.pll48 {
218 ahb2: Hertz(hclk), 144 let freq = unwrap!(plls.pll48clk);
219 ahb3: Hertz(hclk),
220 145
221 pll48: plls.pll48clk.map(Hertz), 146 assert!((max::PLL_48_CLK as i32 - freq as i32).abs() <= max::PLL_48_TOLERANCE as i32);
222 }
223 } 147 }
224 148
225 // Safety: RCC init must have been called 149 let sysclk = if sysclk_on_pll {
226 pub fn clocks(&self) -> &'static Clocks { 150 unwrap!(plls.pllsysclk)
227 unsafe { get_freqs() } 151 } else {
152 sysclk
153 };
154
155 // AHB prescaler
156 let hclk = config.hclk.map(|h| h.0).unwrap_or(sysclk);
157 let (hpre_bits, hpre_div) = match (sysclk + hclk - 1) / hclk {
158 0 => unreachable!(),
159 1 => (Hpre::DIV1, 1),
160 2 => (Hpre::DIV2, 2),
161 3..=5 => (Hpre::DIV4, 4),
162 6..=11 => (Hpre::DIV8, 8),
163 12..=39 => (Hpre::DIV16, 16),
164 40..=95 => (Hpre::DIV64, 64),
165 96..=191 => (Hpre::DIV128, 128),
166 192..=383 => (Hpre::DIV256, 256),
167 _ => (Hpre::DIV512, 512),
168 };
169
170 // Calculate real AHB clock
171 let hclk = sysclk / hpre_div;
172
173 assert!(hclk < max::HCLK_MAX);
174
175 let pclk1 = config
176 .pclk1
177 .map(|p| p.0)
178 .unwrap_or_else(|| core::cmp::min(max::PCLK1_MAX, hclk));
179
180 let (ppre1_bits, ppre1) = match (hclk + pclk1 - 1) / pclk1 {
181 0 => unreachable!(),
182 1 => (0b000, 1),
183 2 => (0b100, 2),
184 3..=5 => (0b101, 4),
185 6..=11 => (0b110, 8),
186 _ => (0b111, 16),
187 };
188 let timer_mul1 = if ppre1 == 1 { 1 } else { 2 };
189
190 // Calculate real APB1 clock
191 let pclk1 = hclk / ppre1;
192 assert!((max::PCLK1_MIN..=max::PCLK1_MAX).contains(&pclk1));
193
194 let pclk2 = config
195 .pclk2
196 .map(|p| p.0)
197 .unwrap_or_else(|| core::cmp::min(max::PCLK2_MAX, hclk));
198 let (ppre2_bits, ppre2) = match (hclk + pclk2 - 1) / pclk2 {
199 0 => unreachable!(),
200 1 => (0b000, 1),
201 2 => (0b100, 2),
202 3..=5 => (0b101, 4),
203 6..=11 => (0b110, 8),
204 _ => (0b111, 16),
205 };
206 let timer_mul2 = if ppre2 == 1 { 1 } else { 2 };
207
208 // Calculate real APB2 clock
209 let pclk2 = hclk / ppre2;
210 assert!((max::PCLK2_MIN..=max::PCLK2_MAX).contains(&pclk2));
211
212 flash_setup(sysclk);
213
214 if config.hse.is_some() {
215 RCC.cr().modify(|w| {
216 w.set_hsebyp(Hsebyp(config.bypass_hse as u8));
217 w.set_hseon(true);
218 });
219 while !RCC.cr().read().hserdy() {}
228 } 220 }
229 221
230 fn setup_pll( 222 if plls.use_pll {
231 &mut self, 223 RCC.cr().modify(|w| w.set_pllon(false));
232 pllsrcclk: u32,
233 use_hse: bool,
234 pllsysclk: Option<u32>,
235 pll48clk: bool,
236 ) -> PllResults {
237 use crate::pac::rcc::vals::{Pllp, Pllsrc};
238
239 let sysclk = pllsysclk.unwrap_or(pllsrcclk);
240 if pllsysclk.is_none() && !pll48clk {
241 // NOTE(unsafe) We have a mutable borrow to the owner of the RegBlock
242 unsafe {
243 RCC.pllcfgr()
244 .modify(|w| w.set_pllsrc(Pllsrc(use_hse as u8)));
245 }
246
247 return PllResults {
248 use_pll: false,
249 pllsysclk: None,
250 pll48clk: None,
251 };
252 }
253 // Input divisor from PLL source clock, must result to frequency in
254 // the range from 1 to 2 MHz
255 let pllm_min = (pllsrcclk + 1_999_999) / 2_000_000;
256 let pllm_max = pllsrcclk / 1_000_000;
257 224
258 // Sysclk output divisor must be one of 2, 4, 6 or 8 225 // enable PWR and setup VOSScale
259 let sysclk_div = core::cmp::min(8, (432_000_000 / sysclk) & !1);
260 226
261 let target_freq = if pll48clk { 227 RCC.apb1enr().modify(|w| w.set_pwren(true));
262 48_000_000
263 } else {
264 sysclk * sysclk_div
265 };
266 228
267 // Find the lowest pllm value that minimize the difference between 229 let vos_scale = if sysclk <= 144_000_000 {
268 // target frequency and the real vco_out frequency. 230 3
269 let pllm = unwrap!((pllm_min..=pllm_max).min_by_key(|pllm| { 231 } else if sysclk <= 168_000_000 {
270 let vco_in = pllsrcclk / pllm; 232 2
271 let plln = target_freq / vco_in;
272 target_freq - vco_in * plln
273 }));
274
275 let vco_in = pllsrcclk / pllm;
276 assert!((1_000_000..=2_000_000).contains(&vco_in));
277
278 // Main scaler, must result in >= 100MHz (>= 192MHz for F401)
279 // and <= 432MHz, min 50, max 432
280 let plln = if pll48clk {
281 // try the different valid pllq according to the valid
282 // main scaller values, and take the best
283 let pllq = unwrap!((4..=9).min_by_key(|pllq| {
284 let plln = 48_000_000 * pllq / vco_in;
285 let pll48_diff = 48_000_000 - vco_in * plln / pllq;
286 let sysclk_diff = (sysclk as i32 - (vco_in * plln / sysclk_div) as i32).abs();
287 (pll48_diff, sysclk_diff)
288 }));
289 48_000_000 * pllq / vco_in
290 } else { 233 } else {
291 sysclk * sysclk_div / vco_in 234 1
292 }; 235 };
236 PWR.cr1().modify(|w| {
237 w.set_vos(match vos_scale {
238 3 => Vos::SCALE3,
239 2 => Vos::SCALE2,
240 1 => Vos::SCALE1,
241 _ => panic!("Invalid VOS Scale."),
242 })
243 });
293 244
294 let pllp = (sysclk_div / 2) - 1; 245 RCC.cr().modify(|w| w.set_pllon(true));
295 246
296 let pllq = (vco_in * plln + 47_999_999) / 48_000_000; 247 if hclk > max::HCLK_OVERDRIVE_FREQUENCY {
297 let real_pll48clk = vco_in * plln / pllq; 248 PWR.cr1().modify(|w| w.set_oden(true));
249 while !PWR.csr1().read().odrdy() {}
298 250
299 unsafe { 251 PWR.cr1().modify(|w| w.set_odswen(true));
300 RCC.pllcfgr().modify(|w| { 252 while !PWR.csr1().read().odswrdy() {}
301 w.set_pllm(pllm as u8);
302 w.set_plln(plln as u16);
303 w.set_pllp(Pllp(pllp as u8));
304 w.set_pllq(pllq as u8);
305 w.set_pllsrc(Pllsrc(use_hse as u8));
306 });
307 } 253 }
308 254
309 let real_pllsysclk = vco_in * plln / sysclk_div; 255 while !RCC.cr().read().pllrdy() {}
310
311 PllResults {
312 use_pll: true,
313 pllsysclk: Some(real_pllsysclk),
314 pll48clk: if pll48clk { Some(real_pll48clk) } else { None },
315 }
316 } 256 }
317 257
318 fn flash_setup(sysclk: u32) { 258 RCC.cfgr().modify(|w| {
319 use crate::pac::flash::vals::Latency; 259 w.set_ppre2(Ppre(ppre2_bits));
260 w.set_ppre1(Ppre(ppre1_bits));
261 w.set_hpre(hpre_bits);
262 });
263
264 // Wait for the new prescalers to kick in
265 // "The clocks are divided with the new prescaler factor from 1 to 16 AHB cycles after write"
266 cortex_m::asm::delay(16);
267
268 RCC.cfgr().modify(|w| {
269 w.set_sw(if sysclk_on_pll {
270 Sw::PLL
271 } else if config.hse.is_some() {
272 Sw::HSE
273 } else {
274 Sw::HSI
275 })
276 });
320 277
321 // Be conservative with voltage ranges 278 set_freqs(Clocks {
322 const FLASH_LATENCY_STEP: u32 = 30_000_000; 279 sys: Hertz(sysclk),
280 apb1: Hertz(pclk1),
281 apb2: Hertz(pclk2),
323 282
324 critical_section::with(|_| unsafe { 283 apb1_tim: Hertz(pclk1 * timer_mul1),
325 FLASH 284 apb2_tim: Hertz(pclk2 * timer_mul2),
326 .acr()
327 .modify(|w| w.set_latency(Latency(((sysclk - 1) / FLASH_LATENCY_STEP) as u8)));
328 });
329 }
330}
331 285
332pub(crate) unsafe fn init(config: Config) { 286 ahb1: Hertz(hclk),
333 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 287 ahb2: Hertz(hclk),
334 let clocks = Rcc::new(r, config).freeze(); 288 ahb3: Hertz(hclk),
335 set_freqs(clocks); 289
290 pll48: plls.pll48clk.map(Hertz),
291 });
336} 292}
337 293
338struct PllResults { 294struct PllResults {
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index df11ff36d..a3a4c197f 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -1,11 +1,7 @@
1use crate::pac; 1use crate::pac::{PWR, RCC};
2use crate::peripherals::{self, RCC}; 2use crate::rcc::{set_freqs, Clocks};
3use crate::rcc::{get_freqs, set_freqs, Clocks};
4use crate::time::Hertz; 3use crate::time::Hertz;
5use crate::time::U32Ext; 4use crate::time::U32Ext;
6use core::marker::PhantomData;
7use embassy::util::Unborrow;
8use embassy_hal_common::unborrow;
9 5
10/// HSI speed 6/// HSI speed
11pub const HSI_FREQ: u32 = 16_000_000; 7pub const HSI_FREQ: u32 = 16_000_000;
@@ -120,115 +116,68 @@ impl Default for Config {
120 } 116 }
121} 117}
122 118
123/// RCC peripheral 119pub(crate) unsafe fn init(config: Config) {
124pub struct Rcc<'d> { 120 let (sys_clk, sw) = match config.mux {
125 _rb: peripherals::RCC, 121 ClockSrc::HSI16(div) => {
126 phantom: PhantomData<&'d mut peripherals::RCC>, 122 // Enable HSI16
127} 123 let div: u8 = div.into();
124 RCC.cr().write(|w| {
125 w.set_hsidiv(div);
126 w.set_hsion(true)
127 });
128 while !RCC.cr().read().hsirdy() {}
128 129
129impl<'d> Rcc<'d> { 130 (HSI_FREQ >> div, 0x00)
130 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
131 unborrow!(rcc);
132 Self {
133 _rb: rcc,
134 phantom: PhantomData,
135 } 131 }
136 } 132 ClockSrc::HSE(freq) => {
137 133 // Enable HSE
138 // Safety: RCC init must have been called 134 RCC.cr().write(|w| w.set_hseon(true));
139 pub fn clocks(&self) -> &'static Clocks { 135 while !RCC.cr().read().hserdy() {}
140 unsafe { get_freqs() }
141 }
142}
143
144/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
145pub trait RccExt {
146 fn freeze(self, config: Config) -> Clocks;
147}
148 136
149impl RccExt for RCC { 137 (freq.0, 0x01)
150 #[inline]
151 fn freeze(self, cfgr: Config) -> Clocks {
152 let rcc = pac::RCC;
153 let (sys_clk, sw) = match cfgr.mux {
154 ClockSrc::HSI16(div) => {
155 // Enable HSI16
156 let div: u8 = div.into();
157 unsafe {
158 rcc.cr().write(|w| {
159 w.set_hsidiv(div);
160 w.set_hsion(true)
161 });
162 while !rcc.cr().read().hsirdy() {}
163 }
164
165 (HSI_FREQ >> div, 0x00)
166 }
167 ClockSrc::HSE(freq) => {
168 // Enable HSE
169 unsafe {
170 rcc.cr().write(|w| w.set_hseon(true));
171 while !rcc.cr().read().hserdy() {}
172 }
173
174 (freq.0, 0x01)
175 }
176 ClockSrc::LSI => {
177 // Enable LSI
178 unsafe {
179 rcc.csr().write(|w| w.set_lsion(true));
180 while !rcc.csr().read().lsirdy() {}
181 }
182 (LSI_FREQ, 0x03)
183 }
184 };
185
186 unsafe {
187 rcc.cfgr().modify(|w| {
188 w.set_sw(sw.into());
189 w.set_hpre(cfgr.ahb_pre.into());
190 w.set_ppre(cfgr.apb_pre.into());
191 });
192 } 138 }
193 139 ClockSrc::LSI => {
194 let ahb_freq: u32 = match cfgr.ahb_pre { 140 // Enable LSI
195 AHBPrescaler::NotDivided => sys_clk, 141 RCC.csr().write(|w| w.set_lsion(true));
196 pre => { 142 while !RCC.csr().read().lsirdy() {}
197 let pre: u8 = pre.into(); 143 (LSI_FREQ, 0x03)
198 let pre = 1 << (pre as u32 - 7);
199 sys_clk / pre
200 }
201 };
202
203 let (apb_freq, apb_tim_freq) = match cfgr.apb_pre {
204 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
205 pre => {
206 let pre: u8 = pre.into();
207 let pre: u8 = 1 << (pre - 3);
208 let freq = ahb_freq / pre as u32;
209 (freq, freq * 2)
210 }
211 };
212
213 let pwr = pac::PWR;
214 if cfgr.low_power_run {
215 assert!(sys_clk.hz() <= 2_000_000.hz());
216 unsafe {
217 pwr.cr1().modify(|w| w.set_lpr(true));
218 }
219 } 144 }
220 145 };
221 Clocks { 146
222 sys: sys_clk.hz(), 147 RCC.cfgr().modify(|w| {
223 ahb: ahb_freq.hz(), 148 w.set_sw(sw.into());
224 apb: apb_freq.hz(), 149 w.set_hpre(config.ahb_pre.into());
225 apb_tim: apb_tim_freq.hz(), 150 w.set_ppre(config.apb_pre.into());
151 });
152
153 let ahb_freq: u32 = match config.ahb_pre {
154 AHBPrescaler::NotDivided => sys_clk,
155 pre => {
156 let pre: u8 = pre.into();
157 let pre = 1 << (pre as u32 - 7);
158 sys_clk / pre
226 } 159 }
160 };
161
162 let (apb_freq, apb_tim_freq) = match config.apb_pre {
163 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
164 pre => {
165 let pre: u8 = pre.into();
166 let pre: u8 = 1 << (pre - 3);
167 let freq = ahb_freq / pre as u32;
168 (freq, freq * 2)
169 }
170 };
171
172 if config.low_power_run {
173 assert!(sys_clk.hz() <= 2_000_000.hz());
174 PWR.cr1().modify(|w| w.set_lpr(true));
227 } 175 }
228}
229 176
230pub(crate) unsafe fn init(config: Config) { 177 set_freqs(Clocks {
231 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 178 sys: sys_clk.hz(),
232 let clocks = r.freeze(config); 179 ahb: ahb_freq.hz(),
233 set_freqs(clocks); 180 apb: apb_freq.hz(),
181 apb_tim: apb_tim_freq.hz(),
182 });
234} 183}
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs
index ee49e2ece..ce8cca45d 100644
--- a/embassy-stm32/src/rcc/g4.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -1,11 +1,7 @@
1use crate::pac; 1use crate::pac::{PWR, RCC};
2use crate::peripherals::{self, RCC}; 2use crate::rcc::{set_freqs, Clocks};
3use crate::rcc::{get_freqs, set_freqs, Clocks};
4use crate::time::Hertz; 3use crate::time::Hertz;
5use crate::time::U32Ext; 4use crate::time::U32Ext;
6use core::marker::PhantomData;
7use embassy::util::Unborrow;
8use embassy_hal_common::unborrow;
9 5
10/// HSI speed 6/// HSI speed
11pub const HSI_FREQ: u32 = 16_000_000; 7pub const HSI_FREQ: u32 = 16_000_000;
@@ -94,117 +90,72 @@ impl Default for Config {
94 } 90 }
95} 91}
96 92
97/// RCC peripheral 93pub(crate) unsafe fn init(config: Config) {
98pub struct Rcc<'d> { 94 let (sys_clk, sw) = match config.mux {
99 _rb: peripherals::RCC, 95 ClockSrc::HSI16 => {
100 phantom: PhantomData<&'d mut peripherals::RCC>, 96 // Enable HSI16
101} 97 RCC.cr().write(|w| w.set_hsion(true));
98 while !RCC.cr().read().hsirdy() {}
102 99
103impl<'d> Rcc<'d> { 100 (HSI_FREQ, 0x01)
104 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
105 unborrow!(rcc);
106 Self {
107 _rb: rcc,
108 phantom: PhantomData,
109 } 101 }
110 } 102 ClockSrc::HSE(freq) => {
111 103 // Enable HSE
112 // Safety: RCC init must have been called 104 RCC.cr().write(|w| w.set_hseon(true));
113 pub fn clocks(&self) -> &'static Clocks { 105 while !RCC.cr().read().hserdy() {}
114 unsafe { get_freqs() }
115 }
116}
117
118/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
119pub trait RccExt {
120 fn freeze(self, config: Config) -> Clocks;
121}
122 106
123impl RccExt for RCC { 107 (freq.0, 0x02)
124 #[inline]
125 fn freeze(self, cfgr: Config) -> Clocks {
126 let rcc = pac::RCC;
127 let (sys_clk, sw) = match cfgr.mux {
128 ClockSrc::HSI16 => {
129 // Enable HSI16
130 unsafe {
131 rcc.cr().write(|w| w.set_hsion(true));
132 while !rcc.cr().read().hsirdy() {}
133 }
134
135 (HSI_FREQ, 0x01)
136 }
137 ClockSrc::HSE(freq) => {
138 // Enable HSE
139 unsafe {
140 rcc.cr().write(|w| w.set_hseon(true));
141 while !rcc.cr().read().hserdy() {}
142 }
143
144 (freq.0, 0x02)
145 }
146 };
147
148 unsafe {
149 rcc.cfgr().modify(|w| {
150 w.set_sw(sw.into());
151 w.set_hpre(cfgr.ahb_pre.into());
152 w.set_ppre1(cfgr.apb1_pre.into());
153 w.set_ppre2(cfgr.apb2_pre.into());
154 });
155 } 108 }
156 109 };
157 let ahb_freq: u32 = match cfgr.ahb_pre { 110
158 AHBPrescaler::NotDivided => sys_clk, 111 RCC.cfgr().modify(|w| {
159 pre => { 112 w.set_sw(sw.into());
160 let pre: u8 = pre.into(); 113 w.set_hpre(config.ahb_pre.into());
161 let pre = 1 << (pre as u32 - 7); 114 w.set_ppre1(config.apb1_pre.into());
162 sys_clk / pre 115 w.set_ppre2(config.apb2_pre.into());
163 } 116 });
164 }; 117
165 118 let ahb_freq: u32 = match config.ahb_pre {
166 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre { 119 AHBPrescaler::NotDivided => sys_clk,
167 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 120 pre => {
168 pre => { 121 let pre: u8 = pre.into();
169 let pre: u8 = pre.into(); 122 let pre = 1 << (pre as u32 - 7);
170 let pre: u8 = 1 << (pre - 3); 123 sys_clk / pre
171 let freq = ahb_freq / pre as u32;
172 (freq, freq * 2)
173 }
174 };
175
176 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre {
177 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
178 pre => {
179 let pre: u8 = pre.into();
180 let pre: u8 = 1 << (pre - 3);
181 let freq = ahb_freq / pre as u32;
182 (freq, freq * 2)
183 }
184 };
185
186 let pwr = pac::PWR;
187 if cfgr.low_power_run {
188 assert!(sys_clk.hz() <= 2_000_000.hz());
189 unsafe {
190 pwr.cr1().modify(|w| w.set_lpr(true));
191 }
192 } 124 }
193 125 };
194 Clocks { 126
195 sys: sys_clk.hz(), 127 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
196 ahb1: ahb_freq.hz(), 128 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
197 ahb2: ahb_freq.hz(), 129 pre => {
198 apb1: apb1_freq.hz(), 130 let pre: u8 = pre.into();
199 apb1_tim: apb1_tim_freq.hz(), 131 let pre: u8 = 1 << (pre - 3);
200 apb2: apb2_freq.hz(), 132 let freq = ahb_freq / pre as u32;
201 apb2_tim: apb2_tim_freq.hz(), 133 (freq, freq * 2)
134 }
135 };
136
137 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
138 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
139 pre => {
140 let pre: u8 = pre.into();
141 let pre: u8 = 1 << (pre - 3);
142 let freq = ahb_freq / pre as u32;
143 (freq, freq * 2)
202 } 144 }
145 };
146
147 if config.low_power_run {
148 assert!(sys_clk.hz() <= 2_000_000.hz());
149 PWR.cr1().modify(|w| w.set_lpr(true));
203 } 150 }
204}
205 151
206pub(crate) unsafe fn init(config: Config) { 152 set_freqs(Clocks {
207 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 153 sys: sys_clk.hz(),
208 let clocks = r.freeze(config); 154 ahb1: ahb_freq.hz(),
209 set_freqs(clocks); 155 ahb2: ahb_freq.hz(),
156 apb1: apb1_freq.hz(),
157 apb1_tim: apb1_tim_freq.hz(),
158 apb2: apb2_freq.hz(),
159 apb2_tim: apb2_tim_freq.hz(),
160 });
210} 161}
diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs
index ac4d033ba..55ddf073a 100644
--- a/embassy-stm32/src/rcc/h7.rs
+++ b/embassy-stm32/src/rcc/h7.rs
@@ -7,9 +7,9 @@ use stm32_metapac::rcc::vals::{Mco1, Mco2};
7use crate::gpio::sealed::Pin as __GpioPin; 7use crate::gpio::sealed::Pin as __GpioPin;
8use crate::gpio::Pin; 8use crate::gpio::Pin;
9use crate::pac::rcc::vals::Timpre; 9use crate::pac::rcc::vals::Timpre;
10use crate::pac::{RCC, SYSCFG}; 10use crate::pac::rcc::vals::{Ckpersel, Dppre, Hpre, Hsebyp, Hsidiv, Pllsrc, Sw};
11use crate::pac::{PWR, RCC, SYSCFG};
11use crate::peripherals; 12use crate::peripherals;
12use 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
@@ -20,6 +20,22 @@ const CSI: Hertz = Hertz(4_000_000);
20const HSI48: Hertz = Hertz(48_000_000); 20const HSI48: Hertz = Hertz(48_000_000);
21const LSI: Hertz = Hertz(32_000); 21const LSI: Hertz = Hertz(32_000);
22 22
23/// Voltage Scale
24///
25/// Represents the voltage range feeding the CPU core. The maximum core
26/// clock frequency depends on this value.
27#[derive(Copy, Clone, PartialEq)]
28pub enum VoltageScale {
29 /// VOS 0 range VCORE 1.26V - 1.40V
30 Scale0,
31 /// VOS 1 range VCORE 1.15V - 1.26V
32 Scale1,
33 /// VOS 2 range VCORE 1.05V - 1.15V
34 Scale2,
35 /// VOS 3 range VCORE 0.95V - 1.05V
36 Scale3,
37}
38
23/// Core clock frequencies 39/// Core clock frequencies
24#[derive(Clone, Copy)] 40#[derive(Clone, Copy)]
25pub struct CoreClocks { 41pub struct CoreClocks {
@@ -72,439 +88,151 @@ pub struct Config {
72 pub pll3: PllConfig, 88 pub pll3: PllConfig,
73} 89}
74 90
75pub struct Rcc<'d> { 91/// Setup traceclk
76 inner: PhantomData<&'d ()>, 92/// Returns a pll1_r_ck
77 config: Config, 93fn traceclk_setup(config: &mut Config, sys_use_pll1_p: bool) {
94 let pll1_r_ck = match (sys_use_pll1_p, config.pll1.r_ck) {
95 // pll1_p_ck selected as system clock but pll1_r_ck not
96 // set. The traceclk mux is synchronous with the system
97 // clock mux, but has pll1_r_ck as an input. In order to
98 // keep traceclk running, we force a pll1_r_ck.
99 (true, None) => Some(Hertz(unwrap!(config.pll1.p_ck).0 / 2)),
100
101 // Either pll1 not selected as system clock, free choice
102 // of pll1_r_ck. Or pll1 is selected, assume user has set
103 // a suitable pll1_r_ck frequency.
104 _ => config.pll1.r_ck,
105 };
106 config.pll1.r_ck = pll1_r_ck;
78} 107}
79 108
80impl<'d> Rcc<'d> { 109/// Divider calculator for pclk 1 - 4
81 pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { 110///
82 Self { 111/// Returns real pclk, bits, ppre and the timer kernel clock
83 inner: PhantomData, 112fn ppre_calculate(
84 config, 113 requested_pclk: u32,
85 } 114 hclk: u32,
86 } 115 max_pclk: u32,
87 116 tim_pre: Option<Timpre>,
88 /// Freeze the core clocks, returning a Core Clocks Distribution 117) -> (u32, u8, u8, Option<u32>) {
89 /// and Reset (CCDR) structure. The actual frequency of the clocks 118 let (bits, ppre) = match (hclk + requested_pclk - 1) / requested_pclk {
90 /// configured is returned in the `clocks` member of the CCDR 119 0 => panic!(),
91 /// structure. 120 1 => (0b000, 1),
92 /// 121 2 => (0b100, 2),
93 /// Note that `freeze` will never result in a clock _faster_ than 122 3..=5 => (0b101, 4),
94 /// that specified. It may result in a clock that is a factor of [1, 123 6..=11 => (0b110, 8),
95 /// 2) slower. 124 _ => (0b111, 16),
96 /// 125 };
97 /// `syscfg` is required to enable the I/O compensation cell. 126 let real_pclk = hclk / u32::from(ppre);
98 /// 127 assert!(real_pclk <= max_pclk);
99 /// # Panics 128
100 /// 129 let tim_ker_clk = if let Some(tim_pre) = tim_pre {
101 /// If a clock specification cannot be achieved within the 130 let clk = match (bits, tim_pre) {
102 /// hardware specification then this function will panic. This 131 (0b101, Timpre::DEFAULTX2) => hclk / 2,
103 /// function may also panic if a clock specification can be 132 (0b110, Timpre::DEFAULTX4) => hclk / 2,
104 /// achieved, but the mechanism for doing so is not yet 133 (0b110, Timpre::DEFAULTX2) => hclk / 4,
105 /// implemented here. 134 (0b111, Timpre::DEFAULTX4) => hclk / 4,
106 pub fn freeze(mut self, pwr: &Power) -> CoreClocks { 135 (0b111, Timpre::DEFAULTX2) => hclk / 8,
107 use crate::pac::rcc::vals::{Ckpersel, Dppre, Hpre, Hsebyp, Hsidiv, Pllsrc, Sw}; 136 _ => hclk,
108
109 let srcclk = self.config.hse.unwrap_or(HSI); // Available clocks
110 let (sys_ck, sys_use_pll1_p) = self.sys_ck_setup(srcclk);
111
112 // Configure traceclk from PLL if needed
113 self.traceclk_setup(sys_use_pll1_p);
114
115 // NOTE(unsafe) We have exclusive access to the RCC
116 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) =
117 unsafe { pll::pll_setup(srcclk.0, &self.config.pll1, 0) };
118 let (pll2_p_ck, pll2_q_ck, pll2_r_ck) =
119 unsafe { pll::pll_setup(srcclk.0, &self.config.pll2, 1) };
120 let (pll3_p_ck, pll3_q_ck, pll3_r_ck) =
121 unsafe { pll::pll_setup(srcclk.0, &self.config.pll3, 2) };
122
123 let sys_ck = if sys_use_pll1_p {
124 Hertz(unwrap!(pll1_p_ck)) // Must have been set by sys_ck_setup
125 } else {
126 sys_ck
127 };
128
129 // NOTE(unsafe) We own the regblock
130 unsafe {
131 // This routine does not support HSIDIV != 1. To
132 // do so it would need to ensure all PLLxON bits are clear
133 // before changing the value of HSIDIV
134 let cr = RCC.cr().read();
135 assert!(cr.hsion());
136 assert!(cr.hsidiv() == Hsidiv::DIV1);
137
138 RCC.csr().modify(|w| w.set_lsion(true));
139 while !RCC.csr().read().lsirdy() {}
140 }
141
142 // per_ck from HSI by default
143 let (per_ck, ckpersel) = match (self.config.per_ck == self.config.hse, self.config.per_ck) {
144 (true, Some(hse)) => (hse, Ckpersel::HSE), // HSE
145 (_, Some(CSI)) => (CSI, Ckpersel::CSI), // CSI
146 _ => (HSI, Ckpersel::HSI), // HSI
147 };
148
149 // D1 Core Prescaler
150 // Set to 1
151 let d1cpre_bits = 0;
152 let d1cpre_div = 1;
153 let sys_d1cpre_ck = sys_ck.0 / d1cpre_div;
154
155 // Refer to part datasheet "General operating conditions"
156 // table for (rev V). We do not assert checks for earlier
157 // revisions which may have lower limits.
158 let (sys_d1cpre_ck_max, rcc_hclk_max, pclk_max) = match pwr.vos {
159 VoltageScale::Scale0 => (480_000_000, 240_000_000, 120_000_000),
160 VoltageScale::Scale1 => (400_000_000, 200_000_000, 100_000_000),
161 VoltageScale::Scale2 => (300_000_000, 150_000_000, 75_000_000),
162 _ => (200_000_000, 100_000_000, 50_000_000),
163 };
164 assert!(sys_d1cpre_ck <= sys_d1cpre_ck_max);
165
166 let rcc_hclk = self
167 .config
168 .rcc_hclk
169 .map(|v| v.0)
170 .unwrap_or(sys_d1cpre_ck / 2);
171 assert!(rcc_hclk <= rcc_hclk_max);
172
173 // Estimate divisor
174 let (hpre_bits, hpre_div) = match (sys_d1cpre_ck + rcc_hclk - 1) / rcc_hclk {
175 0 => panic!(),
176 1 => (Hpre::DIV1, 1),
177 2 => (Hpre::DIV2, 2),
178 3..=5 => (Hpre::DIV4, 4),
179 6..=11 => (Hpre::DIV8, 8),
180 12..=39 => (Hpre::DIV16, 16),
181 40..=95 => (Hpre::DIV64, 64),
182 96..=191 => (Hpre::DIV128, 128),
183 192..=383 => (Hpre::DIV256, 256),
184 _ => (Hpre::DIV512, 512),
185 }; 137 };
186 // Calculate real AXI and AHB clock 138 Some(clk)
187 let rcc_hclk = sys_d1cpre_ck / hpre_div; 139 } else {
188 assert!(rcc_hclk <= rcc_hclk_max); 140 None
189 let rcc_aclk = rcc_hclk; // AXI clock is always equal to AHB clock on H7 141 };
190 // Timer prescaler selection 142 (real_pclk, bits, ppre, tim_ker_clk)
191 let timpre = Timpre::DEFAULTX2; 143}
192
193 let requested_pclk1 = self
194 .config
195 .pclk1
196 .map(|v| v.0)
197 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
198 let (rcc_pclk1, ppre1_bits, ppre1, rcc_timerx_ker_ck) =
199 Self::ppre_calculate(requested_pclk1, rcc_hclk, pclk_max, Some(timpre));
200
201 let requested_pclk2 = self
202 .config
203 .pclk2
204 .map(|v| v.0)
205 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
206 let (rcc_pclk2, ppre2_bits, ppre2, rcc_timery_ker_ck) =
207 Self::ppre_calculate(requested_pclk2, rcc_hclk, pclk_max, Some(timpre));
208
209 let requested_pclk3 = self
210 .config
211 .pclk3
212 .map(|v| v.0)
213 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
214 let (rcc_pclk3, ppre3_bits, ppre3, _) =
215 Self::ppre_calculate(requested_pclk3, rcc_hclk, pclk_max, None);
216
217 let requested_pclk4 = self
218 .config
219 .pclk4
220 .map(|v| v.0)
221 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
222 let (rcc_pclk4, ppre4_bits, ppre4, _) =
223 Self::ppre_calculate(requested_pclk4, rcc_hclk, pclk_max, None);
224
225 Self::flash_setup(rcc_aclk, pwr.vos);
226
227 // Start switching clocks -------------------
228 // NOTE(unsafe) We have the RCC singleton
229 unsafe {
230 // Ensure CSI is on and stable
231 RCC.cr().modify(|w| w.set_csion(true));
232 while !RCC.cr().read().csirdy() {}
233
234 // Ensure HSI48 is on and stable
235 RCC.cr().modify(|w| w.set_hsi48on(true));
236 while !RCC.cr().read().hsi48on() {}
237
238 // XXX: support MCO ?
239
240 let hse_ck = match self.config.hse {
241 Some(hse) => {
242 // Ensure HSE is on and stable
243 RCC.cr().modify(|w| {
244 w.set_hseon(true);
245 w.set_hsebyp(if self.config.bypass_hse {
246 Hsebyp::BYPASSED
247 } else {
248 Hsebyp::NOTBYPASSED
249 });
250 });
251 while !RCC.cr().read().hserdy() {}
252 Some(hse)
253 }
254 None => None,
255 };
256
257 let pllsrc = if self.config.hse.is_some() {
258 Pllsrc::HSE
259 } else {
260 Pllsrc::HSI
261 };
262 RCC.pllckselr().modify(|w| w.set_pllsrc(pllsrc));
263
264 let enable_pll = |pll| {
265 RCC.cr().modify(|w| w.set_pllon(pll, true));
266 while !RCC.cr().read().pllrdy(pll) {}
267 };
268
269 if pll1_p_ck.is_some() {
270 enable_pll(0);
271 }
272
273 if pll2_p_ck.is_some() {
274 enable_pll(1);
275 }
276
277 if pll3_p_ck.is_some() {
278 enable_pll(2);
279 }
280
281 // Core Prescaler / AHB Prescaler / APB3 Prescaler
282 RCC.d1cfgr().modify(|w| {
283 w.set_d1cpre(Hpre(d1cpre_bits));
284 w.set_d1ppre(Dppre(ppre3_bits));
285 w.set_hpre(hpre_bits)
286 });
287 // Ensure core prescaler value is valid before future lower
288 // core voltage
289 while RCC.d1cfgr().read().d1cpre().0 != d1cpre_bits {}
290
291 // APB1 / APB2 Prescaler
292 RCC.d2cfgr().modify(|w| {
293 w.set_d2ppre1(Dppre(ppre1_bits));
294 w.set_d2ppre2(Dppre(ppre2_bits));
295 });
296
297 // APB4 Prescaler
298 RCC.d3cfgr().modify(|w| w.set_d3ppre(Dppre(ppre4_bits)));
299
300 // Peripheral Clock (per_ck)
301 RCC.d1ccipr().modify(|w| w.set_ckpersel(ckpersel));
302
303 // Set timer clocks prescaler setting
304 RCC.cfgr().modify(|w| w.set_timpre(timpre));
305
306 // Select system clock source
307 let sw = match (sys_use_pll1_p, self.config.hse.is_some()) {
308 (true, _) => Sw::PLL1,
309 (false, true) => Sw::HSE,
310 _ => Sw::HSI,
311 };
312 RCC.cfgr().modify(|w| w.set_sw(sw));
313 while RCC.cfgr().read().sws() != sw.0 {}
314
315 // IO compensation cell - Requires CSI clock and SYSCFG
316 assert!(RCC.cr().read().csirdy());
317 RCC.apb4enr().modify(|w| w.set_syscfgen(true));
318 144
319 // Enable the compensation cell, using back-bias voltage code 145/// Setup sys_ck
320 // provide by the cell. 146/// Returns sys_ck frequency, and a pll1_p_ck
321 critical_section::with(|_| { 147fn sys_ck_setup(config: &mut Config, srcclk: Hertz) -> (Hertz, bool) {
322 SYSCFG.cccsr().modify(|w| { 148 // Compare available with wanted clocks
323 w.set_en(true); 149 let sys_ck = config.sys_ck.unwrap_or(srcclk);
324 w.set_cs(false); 150
325 w.set_hslv(false); 151 if sys_ck != srcclk {
326 }) 152 // The requested system clock is not the immediately available
327 }); 153 // HSE/HSI clock. Perhaps there are other ways of obtaining
328 while !SYSCFG.cccsr().read().ready() {} 154 // the requested system clock (such as `HSIDIV`) but we will
329 155 // ignore those for now.
330 CoreClocks { 156 //
331 hclk: Hertz(rcc_hclk), 157 // Therefore we must use pll1_p_ck
332 pclk1: Hertz(rcc_pclk1), 158 let pll1_p_ck = match config.pll1.p_ck {
333 pclk2: Hertz(rcc_pclk2), 159 Some(p_ck) => {
334 pclk3: Hertz(rcc_pclk3), 160 assert!(p_ck == sys_ck,
335 pclk4: Hertz(rcc_pclk4), 161 "Error: Cannot set pll1_p_ck independently as it must be used to generate sys_ck");
336 ppre1, 162 Some(p_ck)
337 ppre2,
338 ppre3,
339 ppre4,
340 csi_ck: Some(CSI),
341 hsi_ck: Some(HSI),
342 hsi48_ck: Some(HSI48),
343 lsi_ck: Some(LSI),
344 per_ck: Some(per_ck),
345 hse_ck,
346 pll1_p_ck: pll1_p_ck.map(Hertz),
347 pll1_q_ck: pll1_q_ck.map(Hertz),
348 pll1_r_ck: pll1_r_ck.map(Hertz),
349 pll2_p_ck: pll2_p_ck.map(Hertz),
350 pll2_q_ck: pll2_q_ck.map(Hertz),
351 pll2_r_ck: pll2_r_ck.map(Hertz),
352 pll3_p_ck: pll3_p_ck.map(Hertz),
353 pll3_q_ck: pll3_q_ck.map(Hertz),
354 pll3_r_ck: pll3_r_ck.map(Hertz),
355 timx_ker_ck: rcc_timerx_ker_ck.map(Hertz),
356 timy_ker_ck: rcc_timery_ker_ck.map(Hertz),
357 sys_ck,
358 c_ck: Hertz(sys_d1cpre_ck),
359 } 163 }
360 } 164 None => Some(sys_ck),
361 }
362
363 /// Setup traceclk
364 /// Returns a pll1_r_ck
365 fn traceclk_setup(&mut self, sys_use_pll1_p: bool) {
366 let pll1_r_ck = match (sys_use_pll1_p, self.config.pll1.r_ck) {
367 // pll1_p_ck selected as system clock but pll1_r_ck not
368 // set. The traceclk mux is synchronous with the system
369 // clock mux, but has pll1_r_ck as an input. In order to
370 // keep traceclk running, we force a pll1_r_ck.
371 (true, None) => Some(Hertz(unwrap!(self.config.pll1.p_ck).0 / 2)),
372
373 // Either pll1 not selected as system clock, free choice
374 // of pll1_r_ck. Or pll1 is selected, assume user has set
375 // a suitable pll1_r_ck frequency.
376 _ => self.config.pll1.r_ck,
377 };
378 self.config.pll1.r_ck = pll1_r_ck;
379 }
380
381 /// Divider calculator for pclk 1 - 4
382 ///
383 /// Returns real pclk, bits, ppre and the timer kernel clock
384 fn ppre_calculate(
385 requested_pclk: u32,
386 hclk: u32,
387 max_pclk: u32,
388 tim_pre: Option<Timpre>,
389 ) -> (u32, u8, u8, Option<u32>) {
390 let (bits, ppre) = match (hclk + requested_pclk - 1) / requested_pclk {
391 0 => panic!(),
392 1 => (0b000, 1),
393 2 => (0b100, 2),
394 3..=5 => (0b101, 4),
395 6..=11 => (0b110, 8),
396 _ => (0b111, 16),
397 };
398 let real_pclk = hclk / u32::from(ppre);
399 assert!(real_pclk <= max_pclk);
400
401 let tim_ker_clk = if let Some(tim_pre) = tim_pre {
402 let clk = match (bits, tim_pre) {
403 (0b101, Timpre::DEFAULTX2) => hclk / 2,
404 (0b110, Timpre::DEFAULTX4) => hclk / 2,
405 (0b110, Timpre::DEFAULTX2) => hclk / 4,
406 (0b111, Timpre::DEFAULTX4) => hclk / 4,
407 (0b111, Timpre::DEFAULTX2) => hclk / 8,
408 _ => hclk,
409 };
410 Some(clk)
411 } else {
412 None
413 }; 165 };
414 (real_pclk, bits, ppre, tim_ker_clk) 166 config.pll1.p_ck = pll1_p_ck;
415 }
416 167
417 /// Setup sys_ck 168 (sys_ck, true)
418 /// Returns sys_ck frequency, and a pll1_p_ck 169 } else {
419 fn sys_ck_setup(&mut self, srcclk: Hertz) -> (Hertz, bool) { 170 // sys_ck is derived directly from a source clock
420 // Compare available with wanted clocks 171 // (HSE/HSI). pll1_p_ck can be as requested
421 let sys_ck = self.config.sys_ck.unwrap_or(srcclk); 172 (sys_ck, false)
422
423 if sys_ck != srcclk {
424 // The requested system clock is not the immediately available
425 // HSE/HSI clock. Perhaps there are other ways of obtaining
426 // the requested system clock (such as `HSIDIV`) but we will
427 // ignore those for now.
428 //
429 // Therefore we must use pll1_p_ck
430 let pll1_p_ck = match self.config.pll1.p_ck {
431 Some(p_ck) => {
432 assert!(p_ck == sys_ck,
433 "Error: Cannot set pll1_p_ck independently as it must be used to generate sys_ck");
434 Some(p_ck)
435 }
436 None => Some(sys_ck),
437 };
438 self.config.pll1.p_ck = pll1_p_ck;
439
440 (sys_ck, true)
441 } else {
442 // sys_ck is derived directly from a source clock
443 // (HSE/HSI). pll1_p_ck can be as requested
444 (sys_ck, false)
445 }
446 } 173 }
174}
447 175
448 fn flash_setup(rcc_aclk: u32, vos: VoltageScale) { 176fn flash_setup(rcc_aclk: u32, vos: VoltageScale) {
449 use crate::pac::FLASH; 177 use crate::pac::FLASH;
450 178
451 // ACLK in MHz, round down and subtract 1 from integers. eg. 179 // ACLK in MHz, round down and subtract 1 from integers. eg.
452 // 61_999_999 -> 61MHz 180 // 61_999_999 -> 61MHz
453 // 62_000_000 -> 61MHz 181 // 62_000_000 -> 61MHz
454 // 62_000_001 -> 62MHz 182 // 62_000_001 -> 62MHz
455 let rcc_aclk_mhz = (rcc_aclk - 1) / 1_000_000; 183 let rcc_aclk_mhz = (rcc_aclk - 1) / 1_000_000;
456 184
457 // See RM0433 Rev 7 Table 17. FLASH recommended number of wait 185 // See RM0433 Rev 7 Table 17. FLASH recommended number of wait
458 // states and programming delay 186 // states and programming delay
459 let (wait_states, progr_delay) = match vos { 187 let (wait_states, progr_delay) = match vos {
460 // VOS 0 range VCORE 1.26V - 1.40V 188 // VOS 0 range VCORE 1.26V - 1.40V
461 VoltageScale::Scale0 => match rcc_aclk_mhz { 189 VoltageScale::Scale0 => match rcc_aclk_mhz {
462 0..=69 => (0, 0), 190 0..=69 => (0, 0),
463 70..=139 => (1, 1), 191 70..=139 => (1, 1),
464 140..=184 => (2, 1), 192 140..=184 => (2, 1),
465 185..=209 => (2, 2), 193 185..=209 => (2, 2),
466 210..=224 => (3, 2), 194 210..=224 => (3, 2),
467 225..=239 => (4, 2), 195 225..=239 => (4, 2),
468 _ => (7, 3), 196 _ => (7, 3),
469 }, 197 },
470 // VOS 1 range VCORE 1.15V - 1.26V 198 // VOS 1 range VCORE 1.15V - 1.26V
471 VoltageScale::Scale1 => match rcc_aclk_mhz { 199 VoltageScale::Scale1 => match rcc_aclk_mhz {
472 0..=69 => (0, 0), 200 0..=69 => (0, 0),
473 70..=139 => (1, 1), 201 70..=139 => (1, 1),
474 140..=184 => (2, 1), 202 140..=184 => (2, 1),
475 185..=209 => (2, 2), 203 185..=209 => (2, 2),
476 210..=224 => (3, 2), 204 210..=224 => (3, 2),
477 _ => (7, 3), 205 _ => (7, 3),
478 }, 206 },
479 // VOS 2 range VCORE 1.05V - 1.15V 207 // VOS 2 range VCORE 1.05V - 1.15V
480 VoltageScale::Scale2 => match rcc_aclk_mhz { 208 VoltageScale::Scale2 => match rcc_aclk_mhz {
481 0..=54 => (0, 0), 209 0..=54 => (0, 0),
482 55..=109 => (1, 1), 210 55..=109 => (1, 1),
483 110..=164 => (2, 1), 211 110..=164 => (2, 1),
484 165..=224 => (3, 2), 212 165..=224 => (3, 2),
485 _ => (7, 3), 213 _ => (7, 3),
486 }, 214 },
487 // VOS 3 range VCORE 0.95V - 1.05V 215 // VOS 3 range VCORE 0.95V - 1.05V
488 VoltageScale::Scale3 => match rcc_aclk_mhz { 216 VoltageScale::Scale3 => match rcc_aclk_mhz {
489 0..=44 => (0, 0), 217 0..=44 => (0, 0),
490 45..=89 => (1, 1), 218 45..=89 => (1, 1),
491 90..=134 => (2, 1), 219 90..=134 => (2, 1),
492 135..=179 => (3, 2), 220 135..=179 => (3, 2),
493 180..=224 => (4, 2), 221 180..=224 => (4, 2),
494 _ => (7, 3), 222 _ => (7, 3),
495 }, 223 },
496 }; 224 };
497 225
498 // NOTE(unsafe) Atomic write 226 // NOTE(unsafe) Atomic write
499 unsafe { 227 unsafe {
500 FLASH.acr().write(|w| { 228 FLASH.acr().write(|w| {
501 w.set_wrhighfreq(progr_delay); 229 w.set_wrhighfreq(progr_delay);
502 w.set_latency(wait_states) 230 w.set_latency(wait_states)
503 }); 231 });
504 while FLASH.acr().read().latency() != wait_states {} 232 while FLASH.acr().read().latency() != wait_states {}
505 }
506 } 233 }
507} 234}
235
508pub enum McoClock { 236pub enum McoClock {
509 Disabled, 237 Disabled,
510 Bypassed, 238 Bypassed,
@@ -681,10 +409,309 @@ impl<'d, T: McoInstance> Mco<'d, T> {
681 } 409 }
682} 410}
683 411
684pub(crate) unsafe fn init(config: Config) { 412pub(crate) unsafe fn init(mut config: Config) {
685 let mut power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal(), false); 413 // TODO make configurable?
686 let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); 414 let enable_overdrive = false;
687 let core_clocks = rcc.freeze(&mut power); 415
416 // NB. The lower bytes of CR3 can only be written once after
417 // POR, and must be written with a valid combination. Refer to
418 // RM0433 Rev 7 6.8.4. This is partially enforced by dropping
419 // `self` at the end of this method, but of course we cannot
420 // know what happened between the previous POR and here.
421 #[cfg(pwr_h7)]
422 PWR.cr3().modify(|w| {
423 w.set_scuen(true);
424 w.set_ldoen(true);
425 w.set_bypass(false);
426 });
427
428 #[cfg(pwr_h7smps)]
429 PWR.cr3().modify(|w| {
430 // hardcode "Direct SPMS" for now, this is what works on nucleos with the
431 // default solderbridge configuration.
432 w.set_sden(true);
433 w.set_ldoen(false);
434 });
435
436 // Validate the supply configuration. If you are stuck here, it is
437 // because the voltages on your board do not match those specified
438 // in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset
439 // VOS = Scale 3, so check that the voltage on the VCAP pins =
440 // 1.0V.
441 while !PWR.csr1().read().actvosrdy() {}
442
443 // Go to Scale 1
444 PWR.d3cr().modify(|w| w.set_vos(0b11));
445 while !PWR.d3cr().read().vosrdy() {}
446
447 let pwr_vos = if !enable_overdrive {
448 VoltageScale::Scale1
449 } else {
450 critical_section::with(|_| {
451 RCC.apb4enr().modify(|w| w.set_syscfgen(true));
452
453 SYSCFG.pwrcr().modify(|w| w.set_oden(1));
454 });
455 while !PWR.d3cr().read().vosrdy() {}
456 VoltageScale::Scale0
457 };
458
459 // Freeze the core clocks, returning a Core Clocks Distribution
460 // and Reset (CCDR) structure. The actual frequency of the clocks
461 // configured is returned in the `clocks` member of the CCDR
462 // structure.
463 //
464 // Note that `freeze` will never result in a clock _faster_ than
465 // that specified. It may result in a clock that is a factor of [1,
466 // 2) slower.
467 //
468 // `syscfg` is required to enable the I/O compensation cell.
469 //
470 // # Panics
471 //
472 // If a clock specification cannot be achieved within the
473 // hardware specification then this function will panic. This
474 // function may also panic if a clock specification can be
475 // achieved, but the mechanism for doing so is not yet
476 // implemented here.
477
478 let srcclk = config.hse.unwrap_or(HSI); // Available clocks
479 let (sys_ck, sys_use_pll1_p) = sys_ck_setup(&mut config, srcclk);
480
481 // Configure traceclk from PLL if needed
482 traceclk_setup(&mut config, sys_use_pll1_p);
483
484 // NOTE(unsafe) We have exclusive access to the RCC
485 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = pll::pll_setup(srcclk.0, &config.pll1, 0);
486 let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = pll::pll_setup(srcclk.0, &config.pll2, 1);
487 let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = pll::pll_setup(srcclk.0, &config.pll3, 2);
488
489 let sys_ck = if sys_use_pll1_p {
490 Hertz(unwrap!(pll1_p_ck)) // Must have been set by sys_ck_setup
491 } else {
492 sys_ck
493 };
494
495 // This routine does not support HSIDIV != 1. To
496 // do so it would need to ensure all PLLxON bits are clear
497 // before changing the value of HSIDIV
498 let cr = RCC.cr().read();
499 assert!(cr.hsion());
500 assert!(cr.hsidiv() == Hsidiv::DIV1);
501
502 RCC.csr().modify(|w| w.set_lsion(true));
503 while !RCC.csr().read().lsirdy() {}
504
505 // per_ck from HSI by default
506 let (per_ck, ckpersel) = match (config.per_ck == config.hse, config.per_ck) {
507 (true, Some(hse)) => (hse, Ckpersel::HSE), // HSE
508 (_, Some(CSI)) => (CSI, Ckpersel::CSI), // CSI
509 _ => (HSI, Ckpersel::HSI), // HSI
510 };
511
512 // D1 Core Prescaler
513 // Set to 1
514 let d1cpre_bits = 0;
515 let d1cpre_div = 1;
516 let sys_d1cpre_ck = sys_ck.0 / d1cpre_div;
517
518 // Refer to part datasheet "General operating conditions"
519 // table for (rev V). We do not assert checks for earlier
520 // revisions which may have lower limits.
521 let (sys_d1cpre_ck_max, rcc_hclk_max, pclk_max) = match pwr_vos {
522 VoltageScale::Scale0 => (480_000_000, 240_000_000, 120_000_000),
523 VoltageScale::Scale1 => (400_000_000, 200_000_000, 100_000_000),
524 VoltageScale::Scale2 => (300_000_000, 150_000_000, 75_000_000),
525 _ => (200_000_000, 100_000_000, 50_000_000),
526 };
527 assert!(sys_d1cpre_ck <= sys_d1cpre_ck_max);
528
529 let rcc_hclk = config.rcc_hclk.map(|v| v.0).unwrap_or(sys_d1cpre_ck / 2);
530 assert!(rcc_hclk <= rcc_hclk_max);
531
532 // Estimate divisor
533 let (hpre_bits, hpre_div) = match (sys_d1cpre_ck + rcc_hclk - 1) / rcc_hclk {
534 0 => panic!(),
535 1 => (Hpre::DIV1, 1),
536 2 => (Hpre::DIV2, 2),
537 3..=5 => (Hpre::DIV4, 4),
538 6..=11 => (Hpre::DIV8, 8),
539 12..=39 => (Hpre::DIV16, 16),
540 40..=95 => (Hpre::DIV64, 64),
541 96..=191 => (Hpre::DIV128, 128),
542 192..=383 => (Hpre::DIV256, 256),
543 _ => (Hpre::DIV512, 512),
544 };
545 // Calculate real AXI and AHB clock
546 let rcc_hclk = sys_d1cpre_ck / hpre_div;
547 assert!(rcc_hclk <= rcc_hclk_max);
548 let rcc_aclk = rcc_hclk; // AXI clock is always equal to AHB clock on H7
549 // Timer prescaler selection
550 let timpre = Timpre::DEFAULTX2;
551
552 let requested_pclk1 = config
553 .pclk1
554 .map(|v| v.0)
555 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
556 let (rcc_pclk1, ppre1_bits, ppre1, rcc_timerx_ker_ck) =
557 ppre_calculate(requested_pclk1, rcc_hclk, pclk_max, Some(timpre));
558
559 let requested_pclk2 = config
560 .pclk2
561 .map(|v| v.0)
562 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
563 let (rcc_pclk2, ppre2_bits, ppre2, rcc_timery_ker_ck) =
564 ppre_calculate(requested_pclk2, rcc_hclk, pclk_max, Some(timpre));
565
566 let requested_pclk3 = config
567 .pclk3
568 .map(|v| v.0)
569 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
570 let (rcc_pclk3, ppre3_bits, ppre3, _) =
571 ppre_calculate(requested_pclk3, rcc_hclk, pclk_max, None);
572
573 let requested_pclk4 = config
574 .pclk4
575 .map(|v| v.0)
576 .unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
577 let (rcc_pclk4, ppre4_bits, ppre4, _) =
578 ppre_calculate(requested_pclk4, rcc_hclk, pclk_max, None);
579
580 flash_setup(rcc_aclk, pwr_vos);
581
582 // Start switching clocks -------------------
583
584 // Ensure CSI is on and stable
585 RCC.cr().modify(|w| w.set_csion(true));
586 while !RCC.cr().read().csirdy() {}
587
588 // Ensure HSI48 is on and stable
589 RCC.cr().modify(|w| w.set_hsi48on(true));
590 while !RCC.cr().read().hsi48on() {}
591
592 // XXX: support MCO ?
593
594 let hse_ck = match config.hse {
595 Some(hse) => {
596 // Ensure HSE is on and stable
597 RCC.cr().modify(|w| {
598 w.set_hseon(true);
599 w.set_hsebyp(if config.bypass_hse {
600 Hsebyp::BYPASSED
601 } else {
602 Hsebyp::NOTBYPASSED
603 });
604 });
605 while !RCC.cr().read().hserdy() {}
606 Some(hse)
607 }
608 None => None,
609 };
610
611 let pllsrc = if config.hse.is_some() {
612 Pllsrc::HSE
613 } else {
614 Pllsrc::HSI
615 };
616 RCC.pllckselr().modify(|w| w.set_pllsrc(pllsrc));
617
618 let enable_pll = |pll| {
619 RCC.cr().modify(|w| w.set_pllon(pll, true));
620 while !RCC.cr().read().pllrdy(pll) {}
621 };
622
623 if pll1_p_ck.is_some() {
624 enable_pll(0);
625 }
626
627 if pll2_p_ck.is_some() {
628 enable_pll(1);
629 }
630
631 if pll3_p_ck.is_some() {
632 enable_pll(2);
633 }
634
635 // Core Prescaler / AHB Prescaler / APB3 Prescaler
636 RCC.d1cfgr().modify(|w| {
637 w.set_d1cpre(Hpre(d1cpre_bits));
638 w.set_d1ppre(Dppre(ppre3_bits));
639 w.set_hpre(hpre_bits)
640 });
641 // Ensure core prescaler value is valid before future lower
642 // core voltage
643 while RCC.d1cfgr().read().d1cpre().0 != d1cpre_bits {}
644
645 // APB1 / APB2 Prescaler
646 RCC.d2cfgr().modify(|w| {
647 w.set_d2ppre1(Dppre(ppre1_bits));
648 w.set_d2ppre2(Dppre(ppre2_bits));
649 });
650
651 // APB4 Prescaler
652 RCC.d3cfgr().modify(|w| w.set_d3ppre(Dppre(ppre4_bits)));
653
654 // Peripheral Clock (per_ck)
655 RCC.d1ccipr().modify(|w| w.set_ckpersel(ckpersel));
656
657 // Set timer clocks prescaler setting
658 RCC.cfgr().modify(|w| w.set_timpre(timpre));
659
660 // Select system clock source
661 let sw = match (sys_use_pll1_p, config.hse.is_some()) {
662 (true, _) => Sw::PLL1,
663 (false, true) => Sw::HSE,
664 _ => Sw::HSI,
665 };
666 RCC.cfgr().modify(|w| w.set_sw(sw));
667 while RCC.cfgr().read().sws() != sw.0 {}
668
669 // IO compensation cell - Requires CSI clock and SYSCFG
670 assert!(RCC.cr().read().csirdy());
671 RCC.apb4enr().modify(|w| w.set_syscfgen(true));
672
673 // Enable the compensation cell, using back-bias voltage code
674 // provide by the cell.
675 critical_section::with(|_| {
676 SYSCFG.cccsr().modify(|w| {
677 w.set_en(true);
678 w.set_cs(false);
679 w.set_hslv(false);
680 })
681 });
682 while !SYSCFG.cccsr().read().ready() {}
683
684 let core_clocks = CoreClocks {
685 hclk: Hertz(rcc_hclk),
686 pclk1: Hertz(rcc_pclk1),
687 pclk2: Hertz(rcc_pclk2),
688 pclk3: Hertz(rcc_pclk3),
689 pclk4: Hertz(rcc_pclk4),
690 ppre1,
691 ppre2,
692 ppre3,
693 ppre4,
694 csi_ck: Some(CSI),
695 hsi_ck: Some(HSI),
696 hsi48_ck: Some(HSI48),
697 lsi_ck: Some(LSI),
698 per_ck: Some(per_ck),
699 hse_ck,
700 pll1_p_ck: pll1_p_ck.map(Hertz),
701 pll1_q_ck: pll1_q_ck.map(Hertz),
702 pll1_r_ck: pll1_r_ck.map(Hertz),
703 pll2_p_ck: pll2_p_ck.map(Hertz),
704 pll2_q_ck: pll2_q_ck.map(Hertz),
705 pll2_r_ck: pll2_r_ck.map(Hertz),
706 pll3_p_ck: pll3_p_ck.map(Hertz),
707 pll3_q_ck: pll3_q_ck.map(Hertz),
708 pll3_r_ck: pll3_r_ck.map(Hertz),
709 timx_ker_ck: rcc_timerx_ker_ck.map(Hertz),
710 timy_ker_ck: rcc_timery_ker_ck.map(Hertz),
711 sys_ck,
712 c_ck: Hertz(sys_d1cpre_ck),
713 };
714
688 set_freqs(Clocks { 715 set_freqs(Clocks {
689 sys: core_clocks.c_ck, 716 sys: core_clocks.c_ck,
690 ahb1: core_clocks.hclk, 717 ahb1: core_clocks.hclk,
diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs
index fc70ef0ac..25daeedf0 100644
--- a/embassy-stm32/src/rcc/l0.rs
+++ b/embassy-stm32/src/rcc/l0.rs
@@ -1,18 +1,11 @@
1use crate::pac; 1use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
2use crate::peripherals::{self, CRS, RCC, SYSCFG}; 2use crate::pac::{CRS, RCC, SYSCFG};
3use crate::rcc::{get_freqs, set_freqs, Clocks}; 3use crate::rcc::{set_freqs, Clocks};
4use crate::time::Hertz; 4use crate::time::Hertz;
5use crate::time::U32Ext; 5use crate::time::U32Ext;
6use core::marker::PhantomData;
7use embassy::util::Unborrow;
8use embassy_hal_common::unborrow;
9use pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
10 6
11/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 7/// HSI16 speed
12/// and with the addition of the init function to configure a system clock. 8pub const HSI16_FREQ: u32 = 16_000_000;
13
14/// HSI speed
15pub const HSI_FREQ: u32 = 16_000_000;
16 9
17/// System clock mux source 10/// System clock mux source
18#[derive(Clone, Copy)] 11#[derive(Clone, Copy)]
@@ -104,9 +97,9 @@ pub enum PLLSource {
104 HSE(Hertz), 97 HSE(Hertz),
105} 98}
106 99
107impl Into<Pllmul> for PLLMul { 100impl From<PLLMul> for Pllmul {
108 fn into(self) -> Pllmul { 101 fn from(val: PLLMul) -> Pllmul {
109 match self { 102 match val {
110 PLLMul::Mul3 => Pllmul::MUL3, 103 PLLMul::Mul3 => Pllmul::MUL3,
111 PLLMul::Mul4 => Pllmul::MUL4, 104 PLLMul::Mul4 => Pllmul::MUL4,
112 PLLMul::Mul6 => Pllmul::MUL6, 105 PLLMul::Mul6 => Pllmul::MUL6,
@@ -120,9 +113,9 @@ impl Into<Pllmul> for PLLMul {
120 } 113 }
121} 114}
122 115
123impl Into<Plldiv> for PLLDiv { 116impl From<PLLDiv> for Plldiv {
124 fn into(self) -> Plldiv { 117 fn from(val: PLLDiv) -> Plldiv {
125 match self { 118 match val {
126 PLLDiv::Div2 => Plldiv::DIV2, 119 PLLDiv::Div2 => Plldiv::DIV2,
127 PLLDiv::Div3 => Plldiv::DIV3, 120 PLLDiv::Div3 => Plldiv::DIV3,
128 PLLDiv::Div4 => Plldiv::DIV4, 121 PLLDiv::Div4 => Plldiv::DIV4,
@@ -130,18 +123,18 @@ impl Into<Plldiv> for PLLDiv {
130 } 123 }
131} 124}
132 125
133impl Into<Pllsrc> for PLLSource { 126impl From<PLLSource> for Pllsrc {
134 fn into(self) -> Pllsrc { 127 fn from(val: PLLSource) -> Pllsrc {
135 match self { 128 match val {
136 PLLSource::HSI16 => Pllsrc::HSI16, 129 PLLSource::HSI16 => Pllsrc::HSI16,
137 PLLSource::HSE(_) => Pllsrc::HSE, 130 PLLSource::HSE(_) => Pllsrc::HSE,
138 } 131 }
139 } 132 }
140} 133}
141 134
142impl Into<Ppre> for APBPrescaler { 135impl From<APBPrescaler> for Ppre {
143 fn into(self) -> Ppre { 136 fn from(val: APBPrescaler) -> Ppre {
144 match self { 137 match val {
145 APBPrescaler::NotDivided => Ppre::DIV1, 138 APBPrescaler::NotDivided => Ppre::DIV1,
146 APBPrescaler::Div2 => Ppre::DIV2, 139 APBPrescaler::Div2 => Ppre::DIV2,
147 APBPrescaler::Div4 => Ppre::DIV4, 140 APBPrescaler::Div4 => Ppre::DIV4,
@@ -151,9 +144,9 @@ impl Into<Ppre> for APBPrescaler {
151 } 144 }
152} 145}
153 146
154impl Into<Hpre> for AHBPrescaler { 147impl From<AHBPrescaler> for Hpre {
155 fn into(self) -> Hpre { 148 fn from(val: AHBPrescaler) -> Hpre {
156 match self { 149 match val {
157 AHBPrescaler::NotDivided => Hpre::DIV1, 150 AHBPrescaler::NotDivided => Hpre::DIV1,
158 AHBPrescaler::Div2 => Hpre::DIV2, 151 AHBPrescaler::Div2 => Hpre::DIV2,
159 AHBPrescaler::Div4 => Hpre::DIV4, 152 AHBPrescaler::Div4 => Hpre::DIV4,
@@ -167,9 +160,9 @@ impl Into<Hpre> for AHBPrescaler {
167 } 160 }
168} 161}
169 162
170impl Into<Msirange> for MSIRange { 163impl From<MSIRange> for Msirange {
171 fn into(self) -> Msirange { 164 fn from(val: MSIRange) -> Msirange {
172 match self { 165 match val {
173 MSIRange::Range0 => Msirange::RANGE0, 166 MSIRange::Range0 => Msirange::RANGE0,
174 MSIRange::Range1 => Msirange::RANGE1, 167 MSIRange::Range1 => Msirange::RANGE1,
175 MSIRange::Range2 => Msirange::RANGE2, 168 MSIRange::Range2 => Msirange::RANGE2,
@@ -187,6 +180,7 @@ pub struct Config {
187 pub ahb_pre: AHBPrescaler, 180 pub ahb_pre: AHBPrescaler,
188 pub apb1_pre: APBPrescaler, 181 pub apb1_pre: APBPrescaler,
189 pub apb2_pre: APBPrescaler, 182 pub apb2_pre: APBPrescaler,
183 pub enable_hsi48: bool,
190} 184}
191 185
192impl Default for Config { 186impl Default for Config {
@@ -197,241 +191,172 @@ impl Default for Config {
197 ahb_pre: AHBPrescaler::NotDivided, 191 ahb_pre: AHBPrescaler::NotDivided,
198 apb1_pre: APBPrescaler::NotDivided, 192 apb1_pre: APBPrescaler::NotDivided,
199 apb2_pre: APBPrescaler::NotDivided, 193 apb2_pre: APBPrescaler::NotDivided,
194 enable_hsi48: false,
200 } 195 }
201 } 196 }
202} 197}
203 198
204/// RCC peripheral 199pub(crate) unsafe fn init(config: Config) {
205pub struct Rcc<'d> { 200 let (sys_clk, sw) = match config.mux {
206 _rb: peripherals::RCC, 201 ClockSrc::MSI(range) => {
207 phantom: PhantomData<&'d mut peripherals::RCC>, 202 // Set MSI range
208} 203 RCC.icscr().write(|w| w.set_msirange(range.into()));
209
210impl<'d> Rcc<'d> {
211 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
212 unborrow!(rcc);
213 Self {
214 _rb: rcc,
215 phantom: PhantomData,
216 }
217 }
218
219 // Safety: RCC init must have been called
220 pub fn clocks(&self) -> &'static Clocks {
221 unsafe { get_freqs() }
222 }
223
224 pub fn enable_hsi48(&mut self, _syscfg: &mut SYSCFG, _crs: CRS) -> HSI48 {
225 let rcc = pac::RCC;
226 unsafe {
227 // Reset SYSCFG peripheral
228 rcc.apb2rstr().modify(|w| w.set_syscfgrst(true));
229 rcc.apb2rstr().modify(|w| w.set_syscfgrst(false));
230
231 // Enable SYSCFG peripheral
232 rcc.apb2enr().modify(|w| w.set_syscfgen(true));
233
234 // Reset CRS peripheral
235 rcc.apb1rstr().modify(|w| w.set_crsrst(true));
236 rcc.apb1rstr().modify(|w| w.set_crsrst(false));
237 204
238 // Enable CRS peripheral 205 // Enable MSI
239 rcc.apb1enr().modify(|w| w.set_crsen(true)); 206 RCC.cr().write(|w| w.set_msion(true));
207 while !RCC.cr().read().msirdy() {}
240 208
241 // Initialize CRS 209 let freq = 32_768 * (1 << (range as u8 + 1));
242 let crs = pac::CRS; 210 (freq, Sw::MSI)
243 crs.cfgr().write(|w| 211 }
212 ClockSrc::HSI16 => {
213 // Enable HSI16
214 RCC.cr().write(|w| w.set_hsi16on(true));
215 while !RCC.cr().read().hsi16rdyf() {}
244 216
245 // Select LSE as synchronization source 217 (HSI16_FREQ, Sw::HSI16)
246 w.set_syncsrc(0b01)); 218 }
247 crs.cr().modify(|w| { 219 ClockSrc::HSE(freq) => {
248 w.set_autotrimen(true); 220 // Enable HSE
249 w.set_cen(true); 221 RCC.cr().write(|w| w.set_hseon(true));
250 }); 222 while !RCC.cr().read().hserdy() {}
251 223
252 // Enable VREFINT reference for HSI48 oscillator 224 (freq.0, Sw::HSE)
253 let syscfg = pac::SYSCFG; 225 }
254 syscfg.cfgr3().modify(|w| { 226 ClockSrc::PLL(src, mul, div) => {
255 w.set_enref_hsi48(true); 227 let freq = match src {
256 w.set_en_vrefint(true); 228 PLLSource::HSE(freq) => {
229 // Enable HSE
230 RCC.cr().write(|w| w.set_hseon(true));
231 while !RCC.cr().read().hserdy() {}
232 freq.0
233 }
234 PLLSource::HSI16 => {
235 // Enable HSI
236 RCC.cr().write(|w| w.set_hsi16on(true));
237 while !RCC.cr().read().hsi16rdyf() {}
238 HSI16_FREQ
239 }
240 };
241
242 // Disable PLL
243 RCC.cr().modify(|w| w.set_pllon(false));
244 while RCC.cr().read().pllrdy() {}
245
246 let freq = match mul {
247 PLLMul::Mul3 => freq * 3,
248 PLLMul::Mul4 => freq * 4,
249 PLLMul::Mul6 => freq * 6,
250 PLLMul::Mul8 => freq * 8,
251 PLLMul::Mul12 => freq * 12,
252 PLLMul::Mul16 => freq * 16,
253 PLLMul::Mul24 => freq * 24,
254 PLLMul::Mul32 => freq * 32,
255 PLLMul::Mul48 => freq * 48,
256 };
257
258 let freq = match div {
259 PLLDiv::Div2 => freq / 2,
260 PLLDiv::Div3 => freq / 3,
261 PLLDiv::Div4 => freq / 4,
262 };
263 assert!(freq <= 32_u32.mhz().0);
264
265 RCC.cfgr().write(move |w| {
266 w.set_pllmul(mul.into());
267 w.set_plldiv(div.into());
268 w.set_pllsrc(src.into());
257 }); 269 });
258 270
259 // Select HSI48 as USB clock 271 // Enable PLL
260 rcc.ccipr().modify(|w| w.set_hsi48msel(true)); 272 RCC.cr().modify(|w| w.set_pllon(true));
273 while !RCC.cr().read().pllrdy() {}
261 274
262 // Enable dedicated USB clock 275 (freq, Sw::PLL)
263 rcc.crrcr().modify(|w| w.set_hsi48on(true));
264 while !rcc.crrcr().read().hsi48rdy() {}
265 } 276 }
277 };
278
279 RCC.cfgr().modify(|w| {
280 w.set_sw(sw);
281 w.set_hpre(config.ahb_pre.into());
282 w.set_ppre1(config.apb1_pre.into());
283 w.set_ppre2(config.apb2_pre.into());
284 });
285
286 let ahb_freq: u32 = match config.ahb_pre {
287 AHBPrescaler::NotDivided => sys_clk,
288 pre => {
289 let pre: Hpre = pre.into();
290 let pre = 1 << (pre.0 as u32 - 7);
291 sys_clk / pre
292 }
293 };
294
295 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
296 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
297 pre => {
298 let pre: Ppre = pre.into();
299 let pre: u8 = 1 << (pre.0 - 3);
300 let freq = ahb_freq / pre as u32;
301 (freq, freq * 2)
302 }
303 };
304
305 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
306 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
307 pre => {
308 let pre: Ppre = pre.into();
309 let pre: u8 = 1 << (pre.0 - 3);
310 let freq = ahb_freq / (1 << (pre as u8 - 3));
311 (freq, freq * 2)
312 }
313 };
266 314
267 HSI48(()) 315 if config.enable_hsi48 {
268 } 316 // Reset SYSCFG peripheral
269} 317 RCC.apb2rstr().modify(|w| w.set_syscfgrst(true));
270 318 RCC.apb2rstr().modify(|w| w.set_syscfgrst(false));
271/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
272pub trait RccExt {
273 fn freeze(self, config: Config) -> Clocks;
274}
275
276impl RccExt for RCC {
277 // `cfgr` is almost always a constant, so make sure it can be constant-propagated properly by
278 // marking this function and all `Config` constructors and setters as `#[inline]`.
279 // This saves ~900 Bytes for the `pwr.rs` example.
280 #[inline]
281 fn freeze(self, cfgr: Config) -> Clocks {
282 let rcc = pac::RCC;
283 let (sys_clk, sw) = match cfgr.mux {
284 ClockSrc::MSI(range) => {
285 // Set MSI range
286 unsafe {
287 rcc.icscr().write(|w| w.set_msirange(range.into()));
288 }
289 319
290 // Enable MSI 320 // Enable SYSCFG peripheral
291 unsafe { 321 RCC.apb2enr().modify(|w| w.set_syscfgen(true));
292 rcc.cr().write(|w| w.set_msion(true));
293 while !rcc.cr().read().msirdy() {}
294 }
295 322
296 let freq = 32_768 * (1 << (range as u8 + 1)); 323 // Reset CRS peripheral
297 (freq, Sw::MSI) 324 RCC.apb1rstr().modify(|w| w.set_crsrst(true));
298 } 325 RCC.apb1rstr().modify(|w| w.set_crsrst(false));
299 ClockSrc::HSI16 => {
300 // Enable HSI16
301 unsafe {
302 rcc.cr().write(|w| w.set_hsi16on(true));
303 while !rcc.cr().read().hsi16rdyf() {}
304 }
305 326
306 (HSI_FREQ, Sw::HSI16) 327 // Enable CRS peripheral
307 } 328 RCC.apb1enr().modify(|w| w.set_crsen(true));
308 ClockSrc::HSE(freq) => {
309 // Enable HSE
310 unsafe {
311 rcc.cr().write(|w| w.set_hseon(true));
312 while !rcc.cr().read().hserdy() {}
313 }
314 329
315 (freq.0, Sw::HSE) 330 // Initialize CRS
316 } 331 CRS.cfgr().write(|w|
317 ClockSrc::PLL(src, mul, div) => {
318 let freq = match src {
319 PLLSource::HSE(freq) => {
320 // Enable HSE
321 unsafe {
322 rcc.cr().write(|w| w.set_hseon(true));
323 while !rcc.cr().read().hserdy() {}
324 }
325 freq.0
326 }
327 PLLSource::HSI16 => {
328 // Enable HSI
329 unsafe {
330 rcc.cr().write(|w| w.set_hsi16on(true));
331 while !rcc.cr().read().hsi16rdyf() {}
332 }
333 HSI_FREQ
334 }
335 };
336
337 // Disable PLL
338 unsafe {
339 rcc.cr().modify(|w| w.set_pllon(false));
340 while rcc.cr().read().pllrdy() {}
341 }
342 332
343 let freq = match mul { 333 // Select LSE as synchronization source
344 PLLMul::Mul3 => freq * 3, 334 w.set_syncsrc(0b01));
345 PLLMul::Mul4 => freq * 4, 335 CRS.cr().modify(|w| {
346 PLLMul::Mul6 => freq * 6, 336 w.set_autotrimen(true);
347 PLLMul::Mul8 => freq * 8, 337 w.set_cen(true);
348 PLLMul::Mul12 => freq * 12, 338 });
349 PLLMul::Mul16 => freq * 16,
350 PLLMul::Mul24 => freq * 24,
351 PLLMul::Mul32 => freq * 32,
352 PLLMul::Mul48 => freq * 48,
353 };
354
355 let freq = match div {
356 PLLDiv::Div2 => freq / 2,
357 PLLDiv::Div3 => freq / 3,
358 PLLDiv::Div4 => freq / 4,
359 };
360 assert!(freq <= 32_u32.mhz().0);
361
362 unsafe {
363 rcc.cfgr().write(move |w| {
364 w.set_pllmul(mul.into());
365 w.set_plldiv(div.into());
366 w.set_pllsrc(src.into());
367 });
368
369 // Enable PLL
370 rcc.cr().modify(|w| w.set_pllon(true));
371 while !rcc.cr().read().pllrdy() {}
372 }
373 339
374 (freq, Sw::PLL) 340 // Enable VREFINT reference for HSI48 oscillator
375 } 341 SYSCFG.cfgr3().modify(|w| {
376 }; 342 w.set_enref_hsi48(true);
343 w.set_en_vrefint(true);
344 });
377 345
378 unsafe { 346 // Select HSI48 as USB clock
379 rcc.cfgr().modify(|w| { 347 RCC.ccipr().modify(|w| w.set_hsi48msel(true));
380 w.set_sw(sw.into());
381 w.set_hpre(cfgr.ahb_pre.into());
382 w.set_ppre1(cfgr.apb1_pre.into());
383 w.set_ppre2(cfgr.apb2_pre.into());
384 });
385 }
386 348
387 let ahb_freq: u32 = match cfgr.ahb_pre { 349 // Enable dedicated USB clock
388 AHBPrescaler::NotDivided => sys_clk, 350 RCC.crrcr().modify(|w| w.set_hsi48on(true));
389 pre => { 351 while !RCC.crrcr().read().hsi48rdy() {}
390 let pre: Hpre = pre.into();
391 let pre = 1 << (pre.0 as u32 - 7);
392 sys_clk / pre
393 }
394 };
395
396 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre {
397 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
398 pre => {
399 let pre: Ppre = pre.into();
400 let pre: u8 = 1 << (pre.0 - 3);
401 let freq = ahb_freq / pre as u32;
402 (freq, freq * 2)
403 }
404 };
405
406 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre {
407 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
408 pre => {
409 let pre: Ppre = pre.into();
410 let pre: u8 = 1 << (pre.0 - 3);
411 let freq = ahb_freq / (1 << (pre as u8 - 3));
412 (freq, freq * 2)
413 }
414 };
415
416 Clocks {
417 sys: sys_clk.hz(),
418 ahb: ahb_freq.hz(),
419 apb1: apb1_freq.hz(),
420 apb2: apb2_freq.hz(),
421 apb1_tim: apb1_tim_freq.hz(),
422 apb2_tim: apb2_tim_freq.hz(),
423 }
424 } 352 }
425}
426 353
427/// Token that exists only, if the HSI48 clock has been enabled 354 set_freqs(Clocks {
428/// 355 sys: sys_clk.hz(),
429/// You can get an instance of this struct by calling [`Rcc::enable_hsi48`]. 356 ahb: ahb_freq.hz(),
430#[derive(Clone, Copy)] 357 apb1: apb1_freq.hz(),
431pub struct HSI48(()); 358 apb2: apb2_freq.hz(),
432 359 apb1_tim: apb1_tim_freq.hz(),
433pub(crate) unsafe fn init(config: Config) { 360 apb2_tim: apb2_tim_freq.hz(),
434 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 361 });
435 let clocks = r.freeze(config);
436 set_freqs(clocks);
437} 362}
diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs
index 746433c12..517869ca4 100644
--- a/embassy-stm32/src/rcc/l1.rs
+++ b/embassy-stm32/src/rcc/l1.rs
@@ -1,13 +1,8 @@
1use crate::pac; 1use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
2use crate::peripherals::{self, RCC}; 2use crate::pac::RCC;
3use crate::rcc::{get_freqs, set_freqs, Clocks}; 3use crate::rcc::{set_freqs, Clocks};
4use crate::time::Hertz; 4use crate::time::Hertz;
5use crate::time::U32Ext; 5use crate::time::U32Ext;
6use core::marker::PhantomData;
7use embassy::util::Unborrow;
8use embassy_hal_common::unborrow;
9
10/// Most of clock setup is copied from rcc/l0
11 6
12/// HSI speed 7/// HSI speed
13pub const HSI_FREQ: u32 = 16_000_000; 8pub const HSI_FREQ: u32 = 16_000_000;
@@ -16,6 +11,7 @@ pub const HSI_FREQ: u32 = 16_000_000;
16#[derive(Clone, Copy)] 11#[derive(Clone, Copy)]
17pub enum ClockSrc { 12pub enum ClockSrc {
18 MSI(MSIRange), 13 MSI(MSIRange),
14 PLL(PLLSource, PLLMul, PLLDiv),
19 HSE(Hertz), 15 HSE(Hertz),
20 HSI, 16 HSI,
21} 17}
@@ -48,6 +44,28 @@ impl Default for MSIRange {
48 } 44 }
49} 45}
50 46
47/// PLL divider
48#[derive(Clone, Copy)]
49pub enum PLLDiv {
50 Div2,
51 Div3,
52 Div4,
53}
54
55/// PLL multiplier
56#[derive(Clone, Copy)]
57pub enum PLLMul {
58 Mul3,
59 Mul4,
60 Mul6,
61 Mul8,
62 Mul12,
63 Mul16,
64 Mul24,
65 Mul32,
66 Mul48,
67}
68
51/// AHB prescaler 69/// AHB prescaler
52#[derive(Clone, Copy, PartialEq)] 70#[derive(Clone, Copy, PartialEq)]
53pub enum AHBPrescaler { 71pub enum AHBPrescaler {
@@ -72,46 +90,86 @@ pub enum APBPrescaler {
72 Div16, 90 Div16,
73} 91}
74 92
75type Ppre = u8; 93/// PLL clock input source
76impl Into<Ppre> for APBPrescaler { 94#[derive(Clone, Copy)]
77 fn into(self) -> Ppre { 95pub enum PLLSource {
78 match self { 96 HSI,
79 APBPrescaler::NotDivided => 0b000, 97 HSE(Hertz),
80 APBPrescaler::Div2 => 0b100, 98}
81 APBPrescaler::Div4 => 0b101, 99
82 APBPrescaler::Div8 => 0b110, 100impl From<PLLMul> for Pllmul {
83 APBPrescaler::Div16 => 0b111, 101 fn from(val: PLLMul) -> Pllmul {
102 match val {
103 PLLMul::Mul3 => Pllmul::MUL3,
104 PLLMul::Mul4 => Pllmul::MUL4,
105 PLLMul::Mul6 => Pllmul::MUL6,
106 PLLMul::Mul8 => Pllmul::MUL8,
107 PLLMul::Mul12 => Pllmul::MUL12,
108 PLLMul::Mul16 => Pllmul::MUL16,
109 PLLMul::Mul24 => Pllmul::MUL24,
110 PLLMul::Mul32 => Pllmul::MUL32,
111 PLLMul::Mul48 => Pllmul::MUL48,
112 }
113 }
114}
115
116impl From<PLLDiv> for Plldiv {
117 fn from(val: PLLDiv) -> Plldiv {
118 match val {
119 PLLDiv::Div2 => Plldiv::DIV2,
120 PLLDiv::Div3 => Plldiv::DIV3,
121 PLLDiv::Div4 => Plldiv::DIV4,
122 }
123 }
124}
125
126impl From<PLLSource> for Pllsrc {
127 fn from(val: PLLSource) -> Pllsrc {
128 match val {
129 PLLSource::HSI => Pllsrc::HSI,
130 PLLSource::HSE(_) => Pllsrc::HSE,
131 }
132 }
133}
134
135impl From<APBPrescaler> for Ppre {
136 fn from(val: APBPrescaler) -> Ppre {
137 match val {
138 APBPrescaler::NotDivided => Ppre::DIV1,
139 APBPrescaler::Div2 => Ppre::DIV2,
140 APBPrescaler::Div4 => Ppre::DIV4,
141 APBPrescaler::Div8 => Ppre::DIV8,
142 APBPrescaler::Div16 => Ppre::DIV16,
84 } 143 }
85 } 144 }
86} 145}
87 146
88type Hpre = u8; 147impl From<AHBPrescaler> for Hpre {
89impl Into<Hpre> for AHBPrescaler { 148 fn from(val: AHBPrescaler) -> Hpre {
90 fn into(self) -> Hpre { 149 match val {
91 match self { 150 AHBPrescaler::NotDivided => Hpre::DIV1,
92 AHBPrescaler::NotDivided => 0b0000, 151 AHBPrescaler::Div2 => Hpre::DIV2,
93 AHBPrescaler::Div2 => 0b1000, 152 AHBPrescaler::Div4 => Hpre::DIV4,
94 AHBPrescaler::Div4 => 0b1001, 153 AHBPrescaler::Div8 => Hpre::DIV8,
95 AHBPrescaler::Div8 => 0b1010, 154 AHBPrescaler::Div16 => Hpre::DIV16,
96 AHBPrescaler::Div16 => 0b1011, 155 AHBPrescaler::Div64 => Hpre::DIV64,
97 AHBPrescaler::Div64 => 0b1100, 156 AHBPrescaler::Div128 => Hpre::DIV128,
98 AHBPrescaler::Div128 => 0b1101, 157 AHBPrescaler::Div256 => Hpre::DIV256,
99 AHBPrescaler::Div256 => 0b1110, 158 AHBPrescaler::Div512 => Hpre::DIV512,
100 AHBPrescaler::Div512 => 0b1111,
101 } 159 }
102 } 160 }
103} 161}
104 162
105impl Into<u8> for MSIRange { 163impl From<MSIRange> for Msirange {
106 fn into(self) -> u8 { 164 fn from(val: MSIRange) -> Msirange {
107 match self { 165 match val {
108 MSIRange::Range0 => 0b000, 166 MSIRange::Range0 => Msirange::RANGE0,
109 MSIRange::Range1 => 0b001, 167 MSIRange::Range1 => Msirange::RANGE1,
110 MSIRange::Range2 => 0b010, 168 MSIRange::Range2 => Msirange::RANGE2,
111 MSIRange::Range3 => 0b011, 169 MSIRange::Range3 => Msirange::RANGE3,
112 MSIRange::Range4 => 0b100, 170 MSIRange::Range4 => Msirange::RANGE4,
113 MSIRange::Range5 => 0b101, 171 MSIRange::Range5 => Msirange::RANGE5,
114 MSIRange::Range6 => 0b110, 172 MSIRange::Range6 => Msirange::RANGE6,
115 } 173 }
116 } 174 }
117} 175}
@@ -136,126 +194,128 @@ impl Default for Config {
136 } 194 }
137} 195}
138 196
139/// RCC peripheral 197pub(crate) unsafe fn init(config: Config) {
140pub struct Rcc<'d> { 198 let (sys_clk, sw) = match config.mux {
141 _rb: peripherals::RCC, 199 ClockSrc::MSI(range) => {
142 phantom: PhantomData<&'d mut peripherals::RCC>, 200 // Set MSI range
143} 201 RCC.icscr().write(|w| w.set_msirange(range.into()));
144 202
145impl<'d> Rcc<'d> { 203 // Enable MSI
146 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self { 204 RCC.cr().write(|w| w.set_msion(true));
147 unborrow!(rcc); 205 while !RCC.cr().read().msirdy() {}
148 Self {
149 _rb: rcc,
150 phantom: PhantomData,
151 }
152 }
153 206
154 // Safety: RCC init must have been called 207 let freq = 32_768 * (1 << (range as u8 + 1));
155 pub fn clocks(&self) -> &'static Clocks { 208 (freq, Sw::MSI)
156 unsafe { get_freqs() } 209 }
157 } 210 ClockSrc::HSI => {
158} 211 // Enable HSI
212 RCC.cr().write(|w| w.set_hsion(true));
213 while !RCC.cr().read().hsirdy() {}
159 214
160/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration 215 (HSI_FREQ, Sw::HSI)
161pub trait RccExt { 216 }
162 fn freeze(self, config: Config) -> Clocks; 217 ClockSrc::HSE(freq) => {
163} 218 // Enable HSE
219 RCC.cr().write(|w| w.set_hseon(true));
220 while !RCC.cr().read().hserdy() {}
164 221
165impl RccExt for RCC { 222 (freq.0, Sw::HSE)
166 // `cfgr` is almost always a constant, so make sure it can be constant-propagated properly by 223 }
167 // marking this function and all `Config` constructors and setters as `#[inline]`. 224 ClockSrc::PLL(src, mul, div) => {
168 // This saves ~900 Bytes for the `pwr.rs` example. 225 let freq = match src {
169 #[inline] 226 PLLSource::HSE(freq) => {
170 fn freeze(self, cfgr: Config) -> Clocks { 227 // Enable HSE
171 let rcc = pac::RCC; 228 RCC.cr().write(|w| w.set_hseon(true));
172 let (sys_clk, sw) = match cfgr.mux { 229 while !RCC.cr().read().hserdy() {}
173 ClockSrc::MSI(range) => { 230 freq.0
174 // Set MSI range
175 unsafe {
176 rcc.icscr().write(|w| w.set_msirange(range.into()));
177 } 231 }
178 232 PLLSource::HSI => {
179 // Enable MSI 233 // Enable HSI
180 unsafe { 234 RCC.cr().write(|w| w.set_hsion(true));
181 rcc.cr().write(|w| w.set_msion(true)); 235 while !RCC.cr().read().hsirdy() {}
182 while !rcc.cr().read().msirdy() {} 236 HSI_FREQ
183 } 237 }
238 };
184 239
185 let freq = 32_768 * (1 << (range as u8 + 1)); 240 // Disable PLL
186 (freq, 0b00) 241 RCC.cr().modify(|w| w.set_pllon(false));
187 } 242 while RCC.cr().read().pllrdy() {}
188 ClockSrc::HSI => {
189 // Enable HSI
190 unsafe {
191 rcc.cr().write(|w| w.set_hsion(true));
192 while !rcc.cr().read().hsirdy() {}
193 }
194 243
195 (HSI_FREQ, 0b01) 244 let freq = match mul {
196 } 245 PLLMul::Mul3 => freq * 3,
197 ClockSrc::HSE(freq) => { 246 PLLMul::Mul4 => freq * 4,
198 // Enable HSE 247 PLLMul::Mul6 => freq * 6,
199 unsafe { 248 PLLMul::Mul8 => freq * 8,
200 rcc.cr().write(|w| w.set_hseon(true)); 249 PLLMul::Mul12 => freq * 12,
201 while !rcc.cr().read().hserdy() {} 250 PLLMul::Mul16 => freq * 16,
202 } 251 PLLMul::Mul24 => freq * 24,
252 PLLMul::Mul32 => freq * 32,
253 PLLMul::Mul48 => freq * 48,
254 };
203 255
204 (freq.0, 0b10) 256 let freq = match div {
205 } 257 PLLDiv::Div2 => freq / 2,
206 }; 258 PLLDiv::Div3 => freq / 3,
259 PLLDiv::Div4 => freq / 4,
260 };
261 assert!(freq <= 32_u32.mhz().0);
207 262
208 unsafe { 263 RCC.cfgr().write(move |w| {
209 rcc.cfgr().modify(|w| { 264 w.set_pllmul(mul.into());
210 w.set_sw(sw.into()); 265 w.set_plldiv(div.into());
211 w.set_hpre(cfgr.ahb_pre.into()); 266 w.set_pllsrc(src.into());
212 w.set_ppre1(cfgr.apb1_pre.into());
213 w.set_ppre2(cfgr.apb2_pre.into());
214 }); 267 });
268
269 // Enable PLL
270 RCC.cr().modify(|w| w.set_pllon(true));
271 while !RCC.cr().read().pllrdy() {}
272
273 (freq, Sw::PLL)
215 } 274 }
275 };
276
277 RCC.cfgr().modify(|w| {
278 w.set_sw(sw);
279 w.set_hpre(config.ahb_pre.into());
280 w.set_ppre1(config.apb1_pre.into());
281 w.set_ppre2(config.apb2_pre.into());
282 });
216 283
217 let ahb_freq: u32 = match cfgr.ahb_pre { 284 let ahb_freq: u32 = match config.ahb_pre {
218 AHBPrescaler::NotDivided => sys_clk, 285 AHBPrescaler::NotDivided => sys_clk,
219 pre => { 286 pre => {
220 let pre: Hpre = pre.into(); 287 let pre: Hpre = pre.into();
221 let pre = 1 << (pre as u32 - 7); 288 let pre = 1 << (pre.0 as u32 - 7);
222 sys_clk / pre 289 sys_clk / pre
223 }
224 };
225
226 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre {
227 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
228 pre => {
229 let pre: Ppre = pre.into();
230 let pre: u8 = 1 << (pre - 3);
231 let freq = ahb_freq / pre as u32;
232 (freq, freq * 2)
233 }
234 };
235
236 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre {
237 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
238 pre => {
239 let pre: Ppre = pre.into();
240 let pre: u8 = 1 << (pre - 3);
241 let freq = ahb_freq / (1 << (pre as u8 - 3));
242 (freq, freq * 2)
243 }
244 };
245
246 Clocks {
247 sys: sys_clk.hz(),
248 ahb: ahb_freq.hz(),
249 apb1: apb1_freq.hz(),
250 apb2: apb2_freq.hz(),
251 apb1_tim: apb1_tim_freq.hz(),
252 apb2_tim: apb2_tim_freq.hz(),
253 } 290 }
254 } 291 };
255}
256 292
257pub(crate) unsafe fn init(config: Config) { 293 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
258 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 294 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
259 let clocks = r.freeze(config); 295 pre => {
260 set_freqs(clocks); 296 let pre: Ppre = pre.into();
297 let pre: u8 = 1 << (pre.0 - 3);
298 let freq = ahb_freq / pre as u32;
299 (freq, freq * 2)
300 }
301 };
302
303 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
304 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
305 pre => {
306 let pre: Ppre = pre.into();
307 let pre: u8 = 1 << (pre.0 - 3);
308 let freq = ahb_freq / (1 << (pre as u8 - 3));
309 (freq, freq * 2)
310 }
311 };
312
313 set_freqs(Clocks {
314 sys: sys_clk.hz(),
315 ahb: ahb_freq.hz(),
316 apb1: apb1_freq.hz(),
317 apb2: apb2_freq.hz(),
318 apb1_tim: apb1_tim_freq.hz(),
319 apb2_tim: apb2_tim_freq.hz(),
320 });
261} 321}
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs
index 510cbddfa..68b960d7c 100644
--- a/embassy-stm32/src/rcc/l4.rs
+++ b/embassy-stm32/src/rcc/l4.rs
@@ -1,17 +1,8 @@
1use crate::pac; 1use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
2use crate::peripherals::{self, RCC}; 2use crate::pac::{FLASH, RCC};
3use crate::rcc::{get_freqs, set_freqs, Clocks}; 3use crate::rcc::{set_freqs, Clocks};
4use crate::time::Hertz; 4use crate::time::Hertz;
5use crate::time::U32Ext; 5use crate::time::U32Ext;
6use core::marker::PhantomData;
7use embassy::util::Unborrow;
8use embassy_hal_common::unborrow;
9use stm32_metapac::rcc::vals::Msirange;
10
11/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
12/// and with the addition of the init function to configure a system clock.
13
14/// Only the basic setup using the HSE and HSI clocks are supported as of now.
15 6
16/// HSI16 speed 7/// HSI16 speed
17pub const HSI16_FREQ: u32 = 16_000_000; 8pub const HSI16_FREQ: u32 = 16_000_000;
@@ -19,8 +10,8 @@ pub const HSI16_FREQ: u32 = 16_000_000;
19/// System clock mux source 10/// System clock mux source
20#[derive(Clone, Copy)] 11#[derive(Clone, Copy)]
21pub enum ClockSrc { 12pub enum ClockSrc {
22 PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option<PLL48Div>),
23 MSI(MSIRange), 13 MSI(MSIRange),
14 PLL(PLLSource, PLLClkDiv, PLLSrcDiv, PLLMul, Option<PLL48Div>),
24 HSE(Hertz), 15 HSE(Hertz),
25 HSI16, 16 HSI16,
26} 17}
@@ -57,25 +48,6 @@ pub enum MSIRange {
57 Range11, 48 Range11,
58} 49}
59 50
60impl Into<u32> for MSIRange {
61 fn into(self) -> u32 {
62 match self {
63 MSIRange::Range0 => 100_000,
64 MSIRange::Range1 => 200_000,
65 MSIRange::Range2 => 400_000,
66 MSIRange::Range3 => 800_000,
67 MSIRange::Range4 => 1_000_000,
68 MSIRange::Range5 => 2_000_000,
69 MSIRange::Range6 => 4_000_000,
70 MSIRange::Range7 => 8_000_000,
71 MSIRange::Range8 => 16_000_000,
72 MSIRange::Range9 => 24_000_000,
73 MSIRange::Range10 => 32_000_000,
74 MSIRange::Range11 => 48_000_000,
75 }
76 }
77}
78
79impl Default for MSIRange { 51impl Default for MSIRange {
80 fn default() -> MSIRange { 52 fn default() -> MSIRange {
81 MSIRange::Range6 53 MSIRange::Range6
@@ -131,9 +103,9 @@ seq_macro::seq!(N in 8..=86 {
131 )* 103 )*
132 } 104 }
133 105
134 impl Into<u8> for PLLMul { 106 impl From<PLLMul> for u8 {
135 fn into(self) -> u8 { 107 fn from(val: PLLMul) -> u8 {
136 match self { 108 match val {
137 #( 109 #(
138 PLLMul::Mul#N => N, 110 PLLMul::Mul#N => N,
139 )* 111 )*
@@ -163,13 +135,13 @@ pub enum PLLClkDiv {
163impl PLLClkDiv { 135impl PLLClkDiv {
164 pub fn to_div(self) -> u32 { 136 pub fn to_div(self) -> u32 {
165 let val: u8 = self.into(); 137 let val: u8 = self.into();
166 val as u32 + 1 * 2 138 (val as u32 + 1) * 2
167 } 139 }
168} 140}
169 141
170impl Into<u8> for PLLClkDiv { 142impl From<PLLClkDiv> for u8 {
171 fn into(self) -> u8 { 143 fn from(val: PLLClkDiv) -> u8 {
172 match self { 144 match val {
173 PLLClkDiv::Div2 => 0b00, 145 PLLClkDiv::Div2 => 0b00,
174 PLLClkDiv::Div4 => 0b01, 146 PLLClkDiv::Div4 => 0b01,
175 PLLClkDiv::Div6 => 0b10, 147 PLLClkDiv::Div6 => 0b10,
@@ -197,9 +169,9 @@ impl PLLSrcDiv {
197 } 169 }
198} 170}
199 171
200impl Into<u8> for PLLSrcDiv { 172impl From<PLLSrcDiv> for u8 {
201 fn into(self) -> u8 { 173 fn from(val: PLLSrcDiv) -> u8 {
202 match self { 174 match val {
203 PLLSrcDiv::Div1 => 0b000, 175 PLLSrcDiv::Div1 => 0b000,
204 PLLSrcDiv::Div2 => 0b001, 176 PLLSrcDiv::Div2 => 0b001,
205 PLLSrcDiv::Div3 => 0b010, 177 PLLSrcDiv::Div3 => 0b010,
@@ -212,18 +184,46 @@ impl Into<u8> for PLLSrcDiv {
212 } 184 }
213} 185}
214 186
215impl Into<u8> for PLLSource { 187impl From<PLLSource> for Pllsrc {
216 fn into(self) -> u8 { 188 fn from(val: PLLSource) -> Pllsrc {
217 match self { 189 match val {
218 PLLSource::HSI16 => 0b10, 190 PLLSource::HSI16 => Pllsrc::HSI16,
219 PLLSource::HSE(_) => 0b11, 191 PLLSource::HSE(_) => Pllsrc::HSE,
220 } 192 }
221 } 193 }
222} 194}
223 195
224impl Into<Msirange> for MSIRange { 196impl From<APBPrescaler> for Ppre {
225 fn into(self) -> Msirange { 197 fn from(val: APBPrescaler) -> Ppre {
226 match self { 198 match val {
199 APBPrescaler::NotDivided => Ppre::DIV1,
200 APBPrescaler::Div2 => Ppre::DIV2,
201 APBPrescaler::Div4 => Ppre::DIV4,
202 APBPrescaler::Div8 => Ppre::DIV8,
203 APBPrescaler::Div16 => Ppre::DIV16,
204 }
205 }
206}
207
208impl From<AHBPrescaler> for Hpre {
209 fn from(val: AHBPrescaler) -> Hpre {
210 match val {
211 AHBPrescaler::NotDivided => Hpre::DIV1,
212 AHBPrescaler::Div2 => Hpre::DIV2,
213 AHBPrescaler::Div4 => Hpre::DIV4,
214 AHBPrescaler::Div8 => Hpre::DIV8,
215 AHBPrescaler::Div16 => Hpre::DIV16,
216 AHBPrescaler::Div64 => Hpre::DIV64,
217 AHBPrescaler::Div128 => Hpre::DIV128,
218 AHBPrescaler::Div256 => Hpre::DIV256,
219 AHBPrescaler::Div512 => Hpre::DIV512,
220 }
221 }
222}
223
224impl From<MSIRange> for Msirange {
225 fn from(val: MSIRange) -> Msirange {
226 match val {
227 MSIRange::Range0 => Msirange::RANGE100K, 227 MSIRange::Range0 => Msirange::RANGE100K,
228 MSIRange::Range1 => Msirange::RANGE200K, 228 MSIRange::Range1 => Msirange::RANGE200K,
229 MSIRange::Range2 => Msirange::RANGE400K, 229 MSIRange::Range2 => Msirange::RANGE400K,
@@ -239,30 +239,22 @@ impl Into<Msirange> for MSIRange {
239 } 239 }
240 } 240 }
241} 241}
242impl Into<u8> for APBPrescaler {
243 fn into(self) -> u8 {
244 match self {
245 APBPrescaler::NotDivided => 1,
246 APBPrescaler::Div2 => 0x04,
247 APBPrescaler::Div4 => 0x05,
248 APBPrescaler::Div8 => 0x06,
249 APBPrescaler::Div16 => 0x07,
250 }
251 }
252}
253 242
254impl Into<u8> for AHBPrescaler { 243impl From<MSIRange> for u32 {
255 fn into(self) -> u8 { 244 fn from(val: MSIRange) -> u32 {
256 match self { 245 match val {
257 AHBPrescaler::NotDivided => 1, 246 MSIRange::Range0 => 100_000,
258 AHBPrescaler::Div2 => 0x08, 247 MSIRange::Range1 => 200_000,
259 AHBPrescaler::Div4 => 0x09, 248 MSIRange::Range2 => 400_000,
260 AHBPrescaler::Div8 => 0x0a, 249 MSIRange::Range3 => 800_000,
261 AHBPrescaler::Div16 => 0x0b, 250 MSIRange::Range4 => 1_000_000,
262 AHBPrescaler::Div64 => 0x0c, 251 MSIRange::Range5 => 2_000_000,
263 AHBPrescaler::Div128 => 0x0d, 252 MSIRange::Range6 => 4_000_000,
264 AHBPrescaler::Div256 => 0x0e, 253 MSIRange::Range7 => 8_000_000,
265 AHBPrescaler::Div512 => 0x0f, 254 MSIRange::Range8 => 16_000_000,
255 MSIRange::Range9 => 24_000_000,
256 MSIRange::Range10 => 32_000_000,
257 MSIRange::Range11 => 48_000_000,
266 } 258 }
267 } 259 }
268} 260}
@@ -287,203 +279,151 @@ impl Default for Config {
287 } 279 }
288} 280}
289 281
290/// RCC peripheral 282pub(crate) unsafe fn init(config: Config) {
291pub struct Rcc<'d> { 283 let (sys_clk, sw) = match config.mux {
292 _rb: peripherals::RCC, 284 ClockSrc::MSI(range) => {
293 phantom: PhantomData<&'d mut peripherals::RCC>, 285 // Enable MSI
294} 286 RCC.cr().write(|w| {
287 let bits: Msirange = range.into();
288 w.set_msirange(bits);
289 w.set_msipllen(false);
290 w.set_msirgsel(true);
291 w.set_msion(true);
292 });
293 while !RCC.cr().read().msirdy() {}
295 294
296impl<'d> Rcc<'d> { 295 // Enable as clock source for USB, RNG if running at 48 MHz
297 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self { 296 if let MSIRange::Range11 = range {
298 unborrow!(rcc); 297 RCC.ccipr().modify(|w| {
299 Self { 298 w.set_clk48sel(0b11);
300 _rb: rcc, 299 });
301 phantom: PhantomData, 300 }
301 (range.into(), Sw::MSI)
302 } 302 }
303 } 303 ClockSrc::HSI16 => {
304 // Enable HSI16
305 RCC.cr().write(|w| w.set_hsion(true));
306 while !RCC.cr().read().hsirdy() {}
304 307
305 // Safety: RCC init must have been called 308 (HSI16_FREQ, Sw::HSI16)
306 pub fn clocks(&self) -> &'static Clocks { 309 }
307 unsafe { get_freqs() } 310 ClockSrc::HSE(freq) => {
308 } 311 // Enable HSE
309} 312 RCC.cr().write(|w| w.set_hseon(true));
310 313 while !RCC.cr().read().hserdy() {}
311/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
312pub trait RccExt {
313 fn freeze(self, config: Config) -> Clocks;
314}
315 314
316impl RccExt for RCC { 315 (freq.0, Sw::HSE)
317 #[inline] 316 }
318 fn freeze(self, cfgr: Config) -> Clocks { 317 ClockSrc::PLL(src, div, prediv, mul, pll48div) => {
319 let rcc = pac::RCC; 318 let freq = match src {
320 let (sys_clk, sw) = match cfgr.mux { 319 PLLSource::HSE(freq) => {
321 ClockSrc::HSI16 => { 320 // Enable HSE
322 // Enable HSI16 321 RCC.cr().write(|w| w.set_hseon(true));
323 unsafe { 322 while !RCC.cr().read().hserdy() {}
324 rcc.cr().write(|w| w.set_hsion(true)); 323 freq.0
325 while !rcc.cr().read().hsirdy() {}
326 } 324 }
327 325 PLLSource::HSI16 => {
328 (HSI16_FREQ, 0b01) 326 // Enable HSI
329 } 327 RCC.cr().write(|w| w.set_hsion(true));
330 ClockSrc::HSE(freq) => { 328 while !RCC.cr().read().hsirdy() {}
331 // Enable HSE 329 HSI16_FREQ
332 unsafe {
333 rcc.cr().write(|w| w.set_hseon(true));
334 while !rcc.cr().read().hserdy() {}
335 } 330 }
331 };
336 332
337 (freq.0, 0b10) 333 // Disable PLL
338 } 334 RCC.cr().modify(|w| w.set_pllon(false));
339 ClockSrc::MSI(range) => { 335 while RCC.cr().read().pllrdy() {}
340 // Enable MSI
341 unsafe {
342 rcc.cr().write(|w| {
343 let bits: Msirange = range.into();
344 w.set_msirange(bits);
345 w.set_msipllen(false);
346 w.set_msirgsel(true);
347 w.set_msion(true);
348 });
349 while !rcc.cr().read().msirdy() {}
350
351 // Enable as clock source for USB, RNG if running at 48 MHz
352 if let MSIRange::Range11 = range {
353 rcc.ccipr().modify(|w| {
354 w.set_clk48sel(0b11);
355 });
356 }
357 }
358 (range.into(), 0b00)
359 }
360 ClockSrc::PLL(src, div, prediv, mul, pll48div) => {
361 let freq = match src {
362 PLLSource::HSE(freq) => {
363 // Enable HSE
364 unsafe {
365 rcc.cr().write(|w| w.set_hseon(true));
366 while !rcc.cr().read().hserdy() {}
367 }
368 freq.0
369 }
370 PLLSource::HSI16 => {
371 // Enable HSI
372 unsafe {
373 rcc.cr().write(|w| w.set_hsion(true));
374 while !rcc.cr().read().hsirdy() {}
375 }
376 HSI16_FREQ
377 }
378 };
379
380 // Disable PLL
381 unsafe {
382 rcc.cr().modify(|w| w.set_pllon(false));
383 while rcc.cr().read().pllrdy() {}
384 }
385 336
386 let freq = (freq / prediv.to_div() * mul.to_mul()) / div.to_div(); 337 let freq = (freq / prediv.to_div() * mul.to_mul()) / div.to_div();
387
388 assert!(freq <= 80_000_000);
389
390 unsafe {
391 rcc.pllcfgr().write(move |w| {
392 w.set_plln(mul.into());
393 w.set_pllm(prediv.into());
394 w.set_pllr(div.into());
395 if let Some(pll48div) = pll48div {
396 w.set_pllq(pll48div.into());
397 w.set_pllqen(true);
398 }
399 w.set_pllsrc(src.into());
400 });
401
402 // Enable as clock source for USB, RNG if PLL48 divisor is provided
403 if pll48div.is_some() {
404 rcc.ccipr().modify(|w| {
405 w.set_clk48sel(0b10);
406 });
407 }
408
409 // Enable PLL
410 rcc.cr().modify(|w| w.set_pllon(true));
411 while !rcc.cr().read().pllrdy() {}
412 rcc.pllcfgr().modify(|w| w.set_pllren(true));
413 }
414 (freq, 0b11)
415 }
416 };
417
418 unsafe {
419 // Set flash wait states
420 pac::FLASH.acr().modify(|w| {
421 w.set_latency(if sys_clk <= 16_000_000 {
422 0b000
423 } else if sys_clk <= 32_000_000 {
424 0b001
425 } else if sys_clk <= 48_000_000 {
426 0b010
427 } else if sys_clk <= 64_000_000 {
428 0b011
429 } else {
430 0b100
431 });
432 });
433 338
434 // Switch active clocks to new clock source 339 assert!(freq <= 80_000_000);
435 rcc.cfgr().modify(|w| { 340
436 w.set_sw(sw.into()); 341 RCC.pllcfgr().write(move |w| {
437 w.set_hpre(cfgr.ahb_pre.into()); 342 w.set_plln(mul.into());
438 w.set_ppre1(cfgr.apb1_pre.into()); 343 w.set_pllm(prediv.into());
439 w.set_ppre2(cfgr.apb2_pre.into()); 344 w.set_pllr(div.into());
345 if let Some(pll48div) = pll48div {
346 w.set_pllq(pll48div.into());
347 w.set_pllqen(true);
348 }
349 w.set_pllsrc(src.into());
440 }); 350 });
441 }
442 351
443 let ahb_freq: u32 = match cfgr.ahb_pre { 352 // Enable as clock source for USB, RNG if PLL48 divisor is provided
444 AHBPrescaler::NotDivided => sys_clk, 353 if pll48div.is_some() {
445 pre => { 354 RCC.ccipr().modify(|w| {
446 let pre: u8 = pre.into(); 355 w.set_clk48sel(0b10);
447 let pre = 1 << (pre as u32 - 7); 356 });
448 sys_clk / pre
449 }
450 };
451
452 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre {
453 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
454 pre => {
455 let pre: u8 = pre.into();
456 let pre: u8 = 1 << (pre - 3);
457 let freq = ahb_freq / pre as u32;
458 (freq, freq * 2)
459 }
460 };
461
462 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre {
463 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
464 pre => {
465 let pre: u8 = pre.into();
466 let pre: u8 = 1 << (pre - 3);
467 let freq = ahb_freq / (1 << (pre as u8 - 3));
468 (freq, freq * 2)
469 } 357 }
470 };
471
472 Clocks {
473 sys: sys_clk.hz(),
474 ahb1: ahb_freq.hz(),
475 ahb2: ahb_freq.hz(),
476 ahb3: ahb_freq.hz(),
477 apb1: apb1_freq.hz(),
478 apb2: apb2_freq.hz(),
479 apb1_tim: apb1_tim_freq.hz(),
480 apb2_tim: apb2_tim_freq.hz(),
481 }
482 }
483}
484 358
485pub(crate) unsafe fn init(config: Config) { 359 // Enable PLL
486 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 360 RCC.cr().modify(|w| w.set_pllon(true));
487 let clocks = r.freeze(config); 361 while !RCC.cr().read().pllrdy() {}
488 set_freqs(clocks); 362 RCC.pllcfgr().modify(|w| w.set_pllren(true));
363
364 (freq, Sw::PLL)
365 }
366 };
367
368 // Set flash wait states
369 FLASH.acr().modify(|w| {
370 w.set_latency(if sys_clk <= 16_000_000 {
371 0b000
372 } else if sys_clk <= 32_000_000 {
373 0b001
374 } else if sys_clk <= 48_000_000 {
375 0b010
376 } else if sys_clk <= 64_000_000 {
377 0b011
378 } else {
379 0b100
380 });
381 });
382
383 RCC.cfgr().modify(|w| {
384 w.set_sw(sw);
385 w.set_hpre(config.ahb_pre.into());
386 w.set_ppre1(config.apb1_pre.into());
387 w.set_ppre2(config.apb2_pre.into());
388 });
389
390 let ahb_freq: u32 = match config.ahb_pre {
391 AHBPrescaler::NotDivided => sys_clk,
392 pre => {
393 let pre: Hpre = pre.into();
394 let pre = 1 << (pre.0 as u32 - 7);
395 sys_clk / pre
396 }
397 };
398
399 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
400 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
401 pre => {
402 let pre: Ppre = pre.into();
403 let pre: u8 = 1 << (pre.0 - 3);
404 let freq = ahb_freq / pre as u32;
405 (freq, freq * 2)
406 }
407 };
408
409 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
410 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
411 pre => {
412 let pre: Ppre = pre.into();
413 let pre: u8 = 1 << (pre.0 - 3);
414 let freq = ahb_freq / (1 << (pre as u8 - 3));
415 (freq, freq * 2)
416 }
417 };
418
419 set_freqs(Clocks {
420 sys: sys_clk.hz(),
421 ahb1: ahb_freq.hz(),
422 ahb2: ahb_freq.hz(),
423 ahb3: ahb_freq.hz(),
424 apb1: apb1_freq.hz(),
425 apb2: apb2_freq.hz(),
426 apb1_tim: apb1_tim_freq.hz(),
427 apb2_tim: apb2_tim_freq.hz(),
428 });
489} 429}
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index e8bd82718..ac1cd06c8 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -1,6 +1,4 @@
1use crate::pac; 1use crate::pac::{FLASH, RCC};
2use crate::peripherals::{self, RCC};
3use crate::pwr::{Power, VoltageScale};
4use crate::rcc::{set_freqs, Clocks}; 2use crate::rcc::{set_freqs, Clocks};
5use crate::time::{Hertz, U32Ext}; 3use crate::time::{Hertz, U32Ext};
6use stm32_metapac::rcc::vals::{Hpre, Msirange, Msirgsel, Pllm, Pllsrc, Ppre, Sw}; 4use stm32_metapac::rcc::vals::{Hpre, Msirange, Msirgsel, Pllm, Pllsrc, Ppre, Sw};
@@ -8,6 +6,20 @@ use stm32_metapac::rcc::vals::{Hpre, Msirange, Msirgsel, Pllm, Pllsrc, Ppre, Sw}
8/// HSI16 speed 6/// HSI16 speed
9pub const HSI16_FREQ: u32 = 16_000_000; 7pub const HSI16_FREQ: u32 = 16_000_000;
10 8
9/// Voltage Scale
10///
11/// Represents the voltage range feeding the CPU core. The maximum core
12/// clock frequency depends on this value.
13#[derive(Copy, Clone, PartialEq)]
14pub enum VoltageScale {
15 // Highest frequency
16 Range1,
17 Range2,
18 Range3,
19 // Lowest power
20 Range4,
21}
22
11#[derive(Copy, Clone)] 23#[derive(Copy, Clone)]
12pub enum ClockSrc { 24pub enum ClockSrc {
13 MSI(MSIRange), 25 MSI(MSIRange),
@@ -293,218 +305,188 @@ impl Default for Config {
293 } 305 }
294} 306}
295 307
296/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration 308pub(crate) unsafe fn init(config: Config) {
297pub trait RccExt { 309 let sys_clk = match config.mux {
298 fn freeze(self, config: Config, power: &Power) -> Clocks; 310 ClockSrc::MSI(range) => {
299} 311 RCC.icscr1().modify(|w| {
300 312 let bits: Msirange = range.into();
301impl RccExt for RCC { 313 w.set_msisrange(bits);
302 #[inline] 314 w.set_msirgsel(Msirgsel::RCC_ICSCR1);
303 fn freeze(self, cfgr: Config, power: &Power) -> Clocks { 315 });
304 let rcc = pac::RCC; 316 RCC.cr().write(|w| {
305 317 w.set_msipllen(false);
306 let sys_clk = match cfgr.mux { 318 w.set_msison(true);
307 ClockSrc::MSI(range) => { 319 w.set_msison(true);
308 unsafe { 320 });
309 rcc.icscr1().modify(|w| { 321 while !RCC.cr().read().msisrdy() {}
310 let bits: Msirange = range.into();
311 w.set_msisrange(bits);
312 w.set_msirgsel(Msirgsel::RCC_ICSCR1);
313 });
314 rcc.cr().write(|w| {
315 w.set_msipllen(false);
316 w.set_msison(true);
317 w.set_msison(true);
318 });
319 while !rcc.cr().read().msisrdy() {}
320 }
321
322 range.into()
323 }
324 ClockSrc::HSE(freq) => {
325 unsafe {
326 rcc.cr().write(|w| w.set_hseon(true));
327 while !rcc.cr().read().hserdy() {}
328 }
329
330 freq.0
331 }
332 ClockSrc::HSI16 => {
333 unsafe {
334 rcc.cr().write(|w| w.set_hsion(true));
335 while !rcc.cr().read().hsirdy() {}
336 }
337 322
338 HSI16_FREQ 323 range.into()
339 } 324 }
340 ClockSrc::PLL1R(src, m, n, div) => { 325 ClockSrc::HSE(freq) => {
341 let freq = match src { 326 RCC.cr().write(|w| w.set_hseon(true));
342 PllSrc::MSI(_) => MSIRange::default().into(), 327 while !RCC.cr().read().hserdy() {}
343 PllSrc::HSE(hertz) => hertz.0,
344 PllSrc::HSI16 => HSI16_FREQ,
345 };
346
347 // disable
348 unsafe {
349 rcc.cr().modify(|w| w.set_pllon(0, false));
350 while rcc.cr().read().pllrdy(0) {}
351 }
352
353 let vco = freq * n as u8 as u32;
354 let pll_ck = vco / (div as u8 as u32 + 1);
355
356 unsafe {
357 rcc.pll1cfgr().write(|w| {
358 w.set_pllm(m.into());
359 w.set_pllsrc(src.into());
360 });
361
362 rcc.pll1divr().modify(|w| {
363 w.set_pllr(div.to_div());
364 w.set_plln(n.to_mul());
365 });
366
367 // Enable PLL
368 rcc.cr().modify(|w| w.set_pllon(0, true));
369 while !rcc.cr().read().pllrdy(0) {}
370 rcc.pll1cfgr().modify(|w| w.set_pllren(true));
371 }
372
373 unsafe {
374 rcc.cr().write(|w| w.set_pllon(0, true));
375 while !rcc.cr().read().pllrdy(0) {}
376 }
377
378 pll_ck
379 }
380 };
381
382 // states and programming delay
383 let wait_states = match power.vos {
384 // VOS 0 range VCORE 1.26V - 1.40V
385 VoltageScale::Range1 => {
386 if sys_clk < 32_000_000 {
387 0
388 } else if sys_clk < 64_000_000 {
389 1
390 } else if sys_clk < 96_000_000 {
391 2
392 } else if sys_clk < 128_000_000 {
393 3
394 } else {
395 4
396 }
397 }
398 // VOS 1 range VCORE 1.15V - 1.26V
399 VoltageScale::Range2 => {
400 if sys_clk < 30_000_000 {
401 0
402 } else if sys_clk < 60_000_000 {
403 1
404 } else if sys_clk < 90_000_000 {
405 2
406 } else {
407 3
408 }
409 }
410 // VOS 2 range VCORE 1.05V - 1.15V
411 VoltageScale::Range3 => {
412 if sys_clk < 24_000_000 {
413 0
414 } else if sys_clk < 48_000_000 {
415 1
416 } else {
417 2
418 }
419 }
420 // VOS 3 range VCORE 0.95V - 1.05V
421 VoltageScale::Range4 => {
422 if sys_clk < 12_000_000 {
423 0
424 } else {
425 1
426 }
427 }
428 };
429 328
430 unsafe { 329 freq.0
431 pac::FLASH.acr().modify(|w| {
432 w.set_latency(wait_states);
433 })
434 } 330 }
331 ClockSrc::HSI16 => {
332 RCC.cr().write(|w| w.set_hsion(true));
333 while !RCC.cr().read().hsirdy() {}
435 334
436 unsafe { 335 HSI16_FREQ
437 rcc.cfgr1().modify(|w| { 336 }
438 w.set_sw(cfgr.mux.into()); 337 ClockSrc::PLL1R(src, m, n, div) => {
338 let freq = match src {
339 PllSrc::MSI(_) => MSIRange::default().into(),
340 PllSrc::HSE(hertz) => hertz.0,
341 PllSrc::HSI16 => HSI16_FREQ,
342 };
343
344 // disable
345 RCC.cr().modify(|w| w.set_pllon(0, false));
346 while RCC.cr().read().pllrdy(0) {}
347
348 let vco = freq * n as u8 as u32;
349 let pll_ck = vco / (div as u8 as u32 + 1);
350
351 RCC.pll1cfgr().write(|w| {
352 w.set_pllm(m.into());
353 w.set_pllsrc(src.into());
439 }); 354 });
440 355
441 rcc.cfgr2().modify(|w| { 356 RCC.pll1divr().modify(|w| {
442 w.set_hpre(cfgr.ahb_pre.into()); 357 w.set_pllr(div.to_div());
443 w.set_ppre1(cfgr.apb1_pre.into()); 358 w.set_plln(n.to_mul());
444 w.set_ppre2(cfgr.apb2_pre.into());
445 }); 359 });
446 360
447 rcc.cfgr3().modify(|w| { 361 // Enable PLL
448 w.set_ppre3(cfgr.apb3_pre.into()); 362 RCC.cr().modify(|w| w.set_pllon(0, true));
449 }); 363 while !RCC.cr().read().pllrdy(0) {}
450 } 364 RCC.pll1cfgr().modify(|w| w.set_pllren(true));
365
366 RCC.cr().write(|w| w.set_pllon(0, true));
367 while !RCC.cr().read().pllrdy(0) {}
451 368
452 let ahb_freq: u32 = match cfgr.ahb_pre { 369 pll_ck
453 AHBPrescaler::NotDivided => sys_clk, 370 }
454 pre => { 371 };
455 let pre: u8 = pre.into(); 372
456 let pre = 1 << (pre as u32 - 7); 373 // TODO make configurable
457 sys_clk / pre 374 let power_vos = VoltageScale::Range4;
375
376 // states and programming delay
377 let wait_states = match power_vos {
378 // VOS 0 range VCORE 1.26V - 1.40V
379 VoltageScale::Range1 => {
380 if sys_clk < 32_000_000 {
381 0
382 } else if sys_clk < 64_000_000 {
383 1
384 } else if sys_clk < 96_000_000 {
385 2
386 } else if sys_clk < 128_000_000 {
387 3
388 } else {
389 4
458 } 390 }
459 }; 391 }
460 392 // VOS 1 range VCORE 1.15V - 1.26V
461 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre { 393 VoltageScale::Range2 => {
462 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 394 if sys_clk < 30_000_000 {
463 pre => { 395 0
464 let pre: u8 = pre.into(); 396 } else if sys_clk < 60_000_000 {
465 let pre: u8 = 1 << (pre - 3); 397 1
466 let freq = ahb_freq / pre as u32; 398 } else if sys_clk < 90_000_000 {
467 (freq, freq * 2) 399 2
400 } else {
401 3
468 } 402 }
469 }; 403 }
470 404 // VOS 2 range VCORE 1.05V - 1.15V
471 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre { 405 VoltageScale::Range3 => {
472 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 406 if sys_clk < 24_000_000 {
473 pre => { 407 0
474 let pre: u8 = pre.into(); 408 } else if sys_clk < 48_000_000 {
475 let pre: u8 = 1 << (pre - 3); 409 1
476 let freq = ahb_freq / (1 << (pre as u8 - 3)); 410 } else {
477 (freq, freq * 2) 411 2
478 } 412 }
479 }; 413 }
480 414 // VOS 3 range VCORE 0.95V - 1.05V
481 let (apb3_freq, _apb3_tim_freq) = match cfgr.apb3_pre { 415 VoltageScale::Range4 => {
482 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 416 if sys_clk < 12_000_000 {
483 pre => { 417 0
484 let pre: u8 = pre.into(); 418 } else {
485 let pre: u8 = 1 << (pre - 3); 419 1
486 let freq = ahb_freq / (1 << (pre as u8 - 3));
487 (freq, freq * 2)
488 } 420 }
489 };
490
491 Clocks {
492 sys: sys_clk.hz(),
493 ahb1: ahb_freq.hz(),
494 ahb2: ahb_freq.hz(),
495 ahb3: ahb_freq.hz(),
496 apb1: apb1_freq.hz(),
497 apb2: apb2_freq.hz(),
498 apb3: apb3_freq.hz(),
499 apb1_tim: apb1_tim_freq.hz(),
500 apb2_tim: apb2_tim_freq.hz(),
501 } 421 }
502 } 422 };
503} 423
504 424 FLASH.acr().modify(|w| {
505pub(crate) unsafe fn init(config: Config) { 425 w.set_latency(wait_states);
506 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 426 });
507 let power = Power::new(<peripherals::PWR as embassy::util::Steal>::steal()); 427
508 let clocks = r.freeze(config, &power); 428 RCC.cfgr1().modify(|w| {
509 set_freqs(clocks); 429 w.set_sw(config.mux.into());
430 });
431
432 RCC.cfgr2().modify(|w| {
433 w.set_hpre(config.ahb_pre.into());
434 w.set_ppre1(config.apb1_pre.into());
435 w.set_ppre2(config.apb2_pre.into());
436 });
437
438 RCC.cfgr3().modify(|w| {
439 w.set_ppre3(config.apb3_pre.into());
440 });
441
442 let ahb_freq: u32 = match config.ahb_pre {
443 AHBPrescaler::NotDivided => sys_clk,
444 pre => {
445 let pre: u8 = pre.into();
446 let pre = 1 << (pre as u32 - 7);
447 sys_clk / pre
448 }
449 };
450
451 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
452 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
453 pre => {
454 let pre: u8 = pre.into();
455 let pre: u8 = 1 << (pre - 3);
456 let freq = ahb_freq / pre as u32;
457 (freq, freq * 2)
458 }
459 };
460
461 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
462 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
463 pre => {
464 let pre: u8 = pre.into();
465 let pre: u8 = 1 << (pre - 3);
466 let freq = ahb_freq / (1 << (pre as u8 - 3));
467 (freq, freq * 2)
468 }
469 };
470
471 let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre {
472 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
473 pre => {
474 let pre: u8 = pre.into();
475 let pre: u8 = 1 << (pre - 3);
476 let freq = ahb_freq / (1 << (pre as u8 - 3));
477 (freq, freq * 2)
478 }
479 };
480
481 set_freqs(Clocks {
482 sys: sys_clk.hz(),
483 ahb1: ahb_freq.hz(),
484 ahb2: ahb_freq.hz(),
485 ahb3: ahb_freq.hz(),
486 apb1: apb1_freq.hz(),
487 apb2: apb2_freq.hz(),
488 apb3: apb3_freq.hz(),
489 apb1_tim: apb1_tim_freq.hz(),
490 apb2_tim: apb2_tim_freq.hz(),
491 });
510} 492}
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs
index 58146d4bd..eae7c9464 100644
--- a/embassy-stm32/src/rcc/wb.rs
+++ b/embassy-stm32/src/rcc/wb.rs
@@ -1,11 +1,7 @@
1use crate::pac; 1use crate::pac::RCC;
2use crate::peripherals::{self, RCC}; 2use crate::rcc::{set_freqs, Clocks};
3use crate::rcc::{get_freqs, set_freqs, Clocks};
4use crate::time::Hertz; 3use crate::time::Hertz;
5use crate::time::U32Ext; 4use crate::time::U32Ext;
6use core::marker::PhantomData;
7use embassy::util::Unborrow;
8use embassy_hal_common::unborrow;
9 5
10/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 6/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
11/// and with the addition of the init function to configure a system clock. 7/// and with the addition of the init function to configure a system clock.
@@ -104,110 +100,68 @@ impl Default for Config {
104 } 100 }
105} 101}
106 102
107/// RCC peripheral 103pub(crate) unsafe fn init(config: Config) {
108pub struct Rcc<'d> { 104 let (sys_clk, sw) = match config.mux {
109 _rb: peripherals::RCC, 105 ClockSrc::HSI16 => {
110 phantom: PhantomData<&'d mut peripherals::RCC>, 106 // Enable HSI16
111} 107 RCC.cr().write(|w| w.set_hsion(true));
108 while !RCC.cr().read().hsirdy() {}
112 109
113impl<'d> Rcc<'d> { 110 (HSI_FREQ, 0x01)
114 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
115 unborrow!(rcc);
116 Self {
117 _rb: rcc,
118 phantom: PhantomData,
119 } 111 }
120 } 112 ClockSrc::HSE(freq) => {
121 113 // Enable HSE
122 // Safety: RCC init must have been called 114 RCC.cr().write(|w| w.set_hseon(true));
123 pub fn clocks(&self) -> &'static Clocks { 115 while !RCC.cr().read().hserdy() {}
124 unsafe { get_freqs() }
125 }
126}
127
128/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
129pub trait RccExt {
130 fn freeze(self, config: Config) -> Clocks;
131}
132 116
133impl RccExt for RCC { 117 (freq.0, 0x02)
134 #[inline]
135 fn freeze(self, cfgr: Config) -> Clocks {
136 let rcc = pac::RCC;
137 let (sys_clk, sw) = match cfgr.mux {
138 ClockSrc::HSI16 => {
139 // Enable HSI16
140 unsafe {
141 rcc.cr().write(|w| w.set_hsion(true));
142 while !rcc.cr().read().hsirdy() {}
143 }
144
145 (HSI_FREQ, 0x01)
146 }
147 ClockSrc::HSE(freq) => {
148 // Enable HSE
149 unsafe {
150 rcc.cr().write(|w| w.set_hseon(true));
151 while !rcc.cr().read().hserdy() {}
152 }
153
154 (freq.0, 0x02)
155 }
156 };
157
158 unsafe {
159 rcc.cfgr().modify(|w| {
160 w.set_sw(sw.into());
161 w.set_hpre(cfgr.ahb_pre.into());
162 w.set_ppre1(cfgr.apb1_pre.into());
163 w.set_ppre2(cfgr.apb2_pre.into());
164 });
165 } 118 }
166 119 };
167 let ahb_freq: u32 = match cfgr.ahb_pre { 120
168 AHBPrescaler::NotDivided => sys_clk, 121 RCC.cfgr().modify(|w| {
169 pre => { 122 w.set_sw(sw.into());
170 let pre: u8 = pre.into(); 123 w.set_hpre(config.ahb_pre.into());
171 let pre = 1 << (pre as u32 - 7); 124 w.set_ppre1(config.apb1_pre.into());
172 sys_clk / pre 125 w.set_ppre2(config.apb2_pre.into());
173 } 126 });
174 }; 127
175 128 let ahb_freq: u32 = match config.ahb_pre {
176 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre { 129 AHBPrescaler::NotDivided => sys_clk,
177 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 130 pre => {
178 pre => { 131 let pre: u8 = pre.into();
179 let pre: u8 = pre.into(); 132 let pre = 1 << (pre as u32 - 7);
180 let pre: u8 = 1 << (pre - 3); 133 sys_clk / pre
181 let freq = ahb_freq / pre as u32;
182 (freq, freq * 2)
183 }
184 };
185
186 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre {
187 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
188 pre => {
189 let pre: u8 = pre.into();
190 let pre: u8 = 1 << (pre - 3);
191 let freq = ahb_freq / (1 << (pre as u8 - 3));
192 (freq, freq * 2)
193 }
194 };
195
196 Clocks {
197 sys: sys_clk.hz(),
198 ahb1: ahb_freq.hz(),
199 ahb2: ahb_freq.hz(),
200 ahb3: ahb_freq.hz(),
201 apb1: apb1_freq.hz(),
202 apb2: apb2_freq.hz(),
203 apb1_tim: apb1_tim_freq.hz(),
204 apb2_tim: apb2_tim_freq.hz(),
205 } 134 }
206 } 135 };
207} 136
208 137 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
209pub(crate) unsafe fn init(config: Config) { 138 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
210 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 139 pre => {
211 let clocks = r.freeze(config); 140 let pre: u8 = pre.into();
212 set_freqs(clocks); 141 let pre: u8 = 1 << (pre - 3);
142 let freq = ahb_freq / pre as u32;
143 (freq, freq * 2)
144 }
145 };
146
147 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
148 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
149 pre => {
150 let pre: u8 = pre.into();
151 let pre: u8 = 1 << (pre - 3);
152 let freq = ahb_freq / (1 << (pre as u8 - 3));
153 (freq, freq * 2)
154 }
155 };
156
157 set_freqs(Clocks {
158 sys: sys_clk.hz(),
159 ahb1: ahb_freq.hz(),
160 ahb2: ahb_freq.hz(),
161 ahb3: ahb_freq.hz(),
162 apb1: apb1_freq.hz(),
163 apb2: apb2_freq.hz(),
164 apb1_tim: apb1_tim_freq.hz(),
165 apb2_tim: apb2_tim_freq.hz(),
166 });
213} 167}
diff --git a/embassy-stm32/src/rcc/wl5.rs b/embassy-stm32/src/rcc/wl5.rs
index 00b91dfec..fb2dd9986 100644
--- a/embassy-stm32/src/rcc/wl5.rs
+++ b/embassy-stm32/src/rcc/wl5.rs
@@ -1,10 +1,6 @@
1use crate::pac; 1use crate::pac::RCC;
2use crate::peripherals::{self, RCC}; 2use crate::rcc::{set_freqs, Clocks};
3use crate::rcc::{get_freqs, set_freqs, Clocks};
4use crate::time::U32Ext; 3use crate::time::U32Ext;
5use core::marker::PhantomData;
6use embassy::util::Unborrow;
7use embassy_hal_common::unborrow;
8 4
9/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 5/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
10/// and with the addition of the init function to configure a system clock. 6/// and with the addition of the init function to configure a system clock.
@@ -91,6 +87,7 @@ pub struct Config {
91 pub ahb_pre: AHBPrescaler, 87 pub ahb_pre: AHBPrescaler,
92 pub apb1_pre: APBPrescaler, 88 pub apb1_pre: APBPrescaler,
93 pub apb2_pre: APBPrescaler, 89 pub apb2_pre: APBPrescaler,
90 pub enable_lsi: bool,
94} 91}
95 92
96impl Default for Config { 93impl Default for Config {
@@ -101,136 +98,92 @@ impl Default for Config {
101 ahb_pre: AHBPrescaler::NotDivided, 98 ahb_pre: AHBPrescaler::NotDivided,
102 apb1_pre: APBPrescaler::NotDivided, 99 apb1_pre: APBPrescaler::NotDivided,
103 apb2_pre: APBPrescaler::NotDivided, 100 apb2_pre: APBPrescaler::NotDivided,
101 enable_lsi: false,
104 } 102 }
105 } 103 }
106} 104}
107 105
108/// RCC peripheral 106pub(crate) unsafe fn init(config: Config) {
109pub struct Rcc<'d> { 107 let (sys_clk, sw) = match config.mux {
110 _rb: peripherals::RCC, 108 ClockSrc::HSI16 => {
111 phantom: PhantomData<&'d mut peripherals::RCC>, 109 // Enable HSI16
112} 110 RCC.cr().write(|w| w.set_hsion(true));
111 while !RCC.cr().read().hsirdy() {}
113 112
114impl<'d> Rcc<'d> { 113 (HSI_FREQ, 0x01)
115 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
116 unborrow!(rcc);
117 Self {
118 _rb: rcc,
119 phantom: PhantomData,
120 } 114 }
121 } 115 ClockSrc::HSE32 => {
116 // Enable HSE32
117 RCC.cr().write(|w| {
118 w.set_hsebyppwr(true);
119 w.set_hseon(true);
120 });
121 while !RCC.cr().read().hserdy() {}
122 122
123 pub fn enable_lsi(&mut self) { 123 (HSE32_FREQ, 0x02)
124 let rcc = pac::RCC;
125 unsafe {
126 let csr = rcc.csr().read();
127 if !csr.lsion() {
128 rcc.csr().modify(|w| w.set_lsion(true));
129 while !rcc.csr().read().lsirdy() {}
130 }
131 } 124 }
132 } 125 };
133 126
134 // Safety: RCC init must have been called 127 RCC.cfgr().modify(|w| {
135 pub fn clocks(&self) -> &'static Clocks { 128 w.set_sw(sw.into());
136 unsafe { get_freqs() } 129 if config.ahb_pre == AHBPrescaler::NotDivided {
137 } 130 w.set_hpre(0);
138} 131 } else {
139 132 w.set_hpre(config.ahb_pre.into());
140/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration 133 }
141pub trait RccExt { 134 w.set_ppre1(config.apb1_pre.into());
142 fn freeze(self, config: Config) -> Clocks; 135 w.set_ppre2(config.apb2_pre.into());
143} 136 });
144 137
145impl RccExt for RCC { 138 let ahb_freq: u32 = match config.ahb_pre {
146 #[inline] 139 AHBPrescaler::NotDivided => sys_clk,
147 fn freeze(self, cfgr: Config) -> Clocks { 140 pre => {
148 let rcc = pac::RCC; 141 let pre: u8 = pre.into();
149 let (sys_clk, sw) = match cfgr.mux { 142 let pre = 1 << (pre as u32 - 7);
150 ClockSrc::HSI16 => { 143 sys_clk / pre
151 // Enable HSI16 144 }
152 unsafe { 145 };
153 rcc.cr().write(|w| w.set_hsion(true)); 146
154 while !rcc.cr().read().hsirdy() {} 147 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
155 } 148 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
156 149 pre => {
157 (HSI_FREQ, 0x01) 150 let pre: u8 = pre.into();
158 } 151 let pre: u8 = 1 << (pre - 3);
159 ClockSrc::HSE32 => { 152 let freq = ahb_freq / pre as u32;
160 // Enable HSE32 153 (freq, freq * 2)
161 unsafe {
162 rcc.cr().write(|w| {
163 w.set_hsebyppwr(true);
164 w.set_hseon(true);
165 });
166 while !rcc.cr().read().hserdy() {}
167 }
168
169 (HSE32_FREQ, 0x02)
170 }
171 };
172
173 unsafe {
174 rcc.cfgr().modify(|w| {
175 w.set_sw(sw.into());
176 if cfgr.ahb_pre == AHBPrescaler::NotDivided {
177 w.set_hpre(0);
178 } else {
179 w.set_hpre(cfgr.ahb_pre.into());
180 }
181 w.set_ppre1(cfgr.apb1_pre.into());
182 w.set_ppre2(cfgr.apb2_pre.into());
183 });
184 } 154 }
155 };
156
157 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
158 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
159 pre => {
160 let pre: u8 = pre.into();
161 let pre: u8 = 1 << (pre - 3);
162 let freq = ahb_freq / (1 << (pre as u8 - 3));
163 (freq, freq * 2)
164 }
165 };
166
167 // TODO: completely untested
168 let apb3_freq = ahb_freq;
185 169
186 let ahb_freq: u32 = match cfgr.ahb_pre { 170 if config.enable_lsi {
187 AHBPrescaler::NotDivided => sys_clk, 171 let csr = RCC.csr().read();
188 pre => { 172 if !csr.lsion() {
189 let pre: u8 = pre.into(); 173 RCC.csr().modify(|w| w.set_lsion(true));
190 let pre = 1 << (pre as u32 - 7); 174 while !RCC.csr().read().lsirdy() {}
191 sys_clk / pre
192 }
193 };
194
195 let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre {
196 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
197 pre => {
198 let pre: u8 = pre.into();
199 let pre: u8 = 1 << (pre - 3);
200 let freq = ahb_freq / pre as u32;
201 (freq, freq * 2)
202 }
203 };
204
205 let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre {
206 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
207 pre => {
208 let pre: u8 = pre.into();
209 let pre: u8 = 1 << (pre - 3);
210 let freq = ahb_freq / (1 << (pre as u8 - 3));
211 (freq, freq * 2)
212 }
213 };
214
215 // TODO: completely untested
216 let apb3_freq = ahb_freq;
217
218 Clocks {
219 sys: sys_clk.hz(),
220 ahb1: ahb_freq.hz(),
221 ahb2: ahb_freq.hz(),
222 ahb3: ahb_freq.hz(),
223 apb1: apb1_freq.hz(),
224 apb2: apb2_freq.hz(),
225 apb3: apb3_freq.hz(),
226 apb1_tim: apb1_tim_freq.hz(),
227 apb2_tim: apb2_tim_freq.hz(),
228 } 175 }
229 } 176 }
230}
231 177
232pub(crate) unsafe fn init(config: Config) { 178 set_freqs(Clocks {
233 let r = <peripherals::RCC as embassy::util::Steal>::steal(); 179 sys: sys_clk.hz(),
234 let clocks = r.freeze(config); 180 ahb1: ahb_freq.hz(),
235 set_freqs(clocks); 181 ahb2: ahb_freq.hz(),
182 ahb3: ahb_freq.hz(),
183 apb1: apb1_freq.hz(),
184 apb2: apb2_freq.hz(),
185 apb3: apb3_freq.hz(),
186 apb1_tim: apb1_tim_freq.hz(),
187 apb2_tim: apb2_tim_freq.hz(),
188 });
236} 189}
diff --git a/examples/stm32l0/src/bin/button_exti.rs b/examples/stm32l0/src/bin/button_exti.rs
index 20d6f5555..88c75ce6d 100644
--- a/examples/stm32l0/src/bin/button_exti.rs
+++ b/examples/stm32l0/src/bin/button_exti.rs
@@ -8,16 +8,18 @@ mod example_common;
8use embassy::executor::Spawner; 8use embassy::executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::ExtiInput;
10use embassy_stm32::gpio::{Input, Pull}; 10use embassy_stm32::gpio::{Input, Pull};
11use embassy_stm32::{rcc, Peripherals}; 11use embassy_stm32::Peripherals;
12use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge}; 12use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge};
13use example_common::*; 13use example_common::*;
14 14
15#[embassy::main] 15fn config() -> embassy_stm32::Config {
16async fn main(_spawner: Spawner, mut p: Peripherals) { 16 let mut config = embassy_stm32::Config::default();
17 let mut rcc = rcc::Rcc::new(p.RCC); 17 config.rcc.enable_hsi48 = true;
18 // Enables SYSCFG 18 config
19 let _ = rcc.enable_hsi48(&mut p.SYSCFG, p.CRS); 19}
20 20
21#[embassy::main(config = "config()")]
22async fn main(_spawner: Spawner, p: Peripherals) {
21 let button = Input::new(p.PB2, Pull::Up); 23 let button = Input::new(p.PB2, Pull::Up);
22 let mut button = ExtiInput::new(button, p.EXTI2); 24 let mut button = ExtiInput::new(button, p.EXTI2);
23 25
diff --git a/examples/stm32l0/src/bin/lorawan.rs b/examples/stm32l0/src/bin/lorawan.rs
index 7ce859a8d..df08ba18c 100644
--- a/examples/stm32l0/src/bin/lorawan.rs
+++ b/examples/stm32l0/src/bin/lorawan.rs
@@ -11,10 +11,8 @@ mod example_common;
11 11
12use embassy_lora::{sx127x::*, LoraTimer}; 12use embassy_lora::{sx127x::*, LoraTimer};
13use embassy_stm32::{ 13use embassy_stm32::{
14 dbgmcu::Dbgmcu,
15 exti::ExtiInput, 14 exti::ExtiInput,
16 gpio::{Input, Level, Output, Pull, Speed}, 15 gpio::{Input, Level, Output, Pull, Speed},
17 rcc,
18 rng::Rng, 16 rng::Rng,
19 spi, 17 spi,
20 time::U32Ext, 18 time::U32Ext,
@@ -26,18 +24,12 @@ use lorawan_encoding::default_crypto::DefaultFactory as Crypto;
26fn config() -> embassy_stm32::Config { 24fn config() -> embassy_stm32::Config {
27 let mut config = embassy_stm32::Config::default(); 25 let mut config = embassy_stm32::Config::default();
28 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16; 26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
27 config.rcc.enable_hsi48 = true;
29 config 28 config
30} 29}
31 30
32#[embassy::main(config = "config()")] 31#[embassy::main(config = "config()")]
33async fn main(_spawner: embassy::executor::Spawner, mut p: Peripherals) { 32async fn main(_spawner: embassy::executor::Spawner, p: Peripherals) {
34 unsafe {
35 Dbgmcu::enable_all();
36 }
37
38 let mut rcc = rcc::Rcc::new(p.RCC);
39 let _ = rcc.enable_hsi48(&mut p.SYSCFG, p.CRS);
40
41 // SPI for sx127x 33 // SPI for sx127x
42 let spi = spi::Spi::new( 34 let spi = spi::Spi::new(
43 p.SPI1, 35 p.SPI1,
diff --git a/examples/stm32wl55/src/bin/lorawan.rs b/examples/stm32wl55/src/bin/lorawan.rs
index 7048a5814..5d26dead2 100644
--- a/examples/stm32wl55/src/bin/lorawan.rs
+++ b/examples/stm32wl55/src/bin/lorawan.rs
@@ -10,10 +10,9 @@ mod example_common;
10 10
11use embassy_lora::{stm32wl::*, LoraTimer}; 11use embassy_lora::{stm32wl::*, LoraTimer};
12use embassy_stm32::{ 12use embassy_stm32::{
13 dbgmcu::Dbgmcu,
14 dma::NoDma, 13 dma::NoDma,
15 gpio::{Level, Output, Pin, Speed}, 14 gpio::{Level, Output, Pin, Speed},
16 interrupt, pac, rcc, 15 interrupt, pac,
17 rng::Rng, 16 rng::Rng,
18 subghz::*, 17 subghz::*,
19 Peripherals, 18 Peripherals,
@@ -24,19 +23,13 @@ use lorawan_encoding::default_crypto::DefaultFactory as Crypto;
24fn config() -> embassy_stm32::Config { 23fn config() -> embassy_stm32::Config {
25 let mut config = embassy_stm32::Config::default(); 24 let mut config = embassy_stm32::Config::default();
26 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16; 25 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSI16;
26 config.rcc.enable_lsi = true;
27 config 27 config
28} 28}
29 29
30#[embassy::main(config = "config()")] 30#[embassy::main(config = "config()")]
31async fn main(_spawner: embassy::executor::Spawner, p: Peripherals) { 31async fn main(_spawner: embassy::executor::Spawner, p: Peripherals) {
32 unsafe { 32 unsafe { pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01)) }
33 Dbgmcu::enable_all();
34 let mut rcc = rcc::Rcc::new(p.RCC);
35 rcc.enable_lsi();
36 pac::RCC.ccipr().modify(|w| {
37 w.set_rngsel(0b01);
38 });
39 }
40 33
41 let ctrl1 = Output::new(p.PC3.degrade(), Level::High, Speed::High); 34 let ctrl1 = Output::new(p.PC3.degrade(), Level::High, Speed::High);
42 let ctrl2 = Output::new(p.PC4.degrade(), Level::High, Speed::High); 35 let ctrl2 = Output::new(p.PC4.degrade(), Level::High, Speed::High);
diff --git a/examples/stm32wl55/src/bin/subghz.rs b/examples/stm32wl55/src/bin/subghz.rs
index a73c361c2..52fe6e9fa 100644
--- a/examples/stm32wl55/src/bin/subghz.rs
+++ b/examples/stm32wl55/src/bin/subghz.rs
@@ -11,7 +11,6 @@ mod example_common;
11use embassy::channel::signal::Signal; 11use embassy::channel::signal::Signal;
12use embassy::interrupt::{Interrupt, InterruptExt}; 12use embassy::interrupt::{Interrupt, InterruptExt};
13use embassy::traits::gpio::WaitForRisingEdge; 13use embassy::traits::gpio::WaitForRisingEdge;
14use embassy_stm32::dbgmcu::Dbgmcu;
15use embassy_stm32::dma::NoDma; 14use embassy_stm32::dma::NoDma;
16use embassy_stm32::exti::ExtiInput; 15use embassy_stm32::exti::ExtiInput;
17use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; 16use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
@@ -72,10 +71,6 @@ fn config() -> embassy_stm32::Config {
72 71
73#[embassy::main(config = "config()")] 72#[embassy::main(config = "config()")]
74async fn main(_spawner: embassy::executor::Spawner, p: Peripherals) { 73async fn main(_spawner: embassy::executor::Spawner, p: Peripherals) {
75 unsafe {
76 Dbgmcu::enable_all();
77 }
78
79 let mut led1 = Output::new(p.PB15, Level::High, Speed::Low); 74 let mut led1 = Output::new(p.PB15, Level::High, Speed::Low);
80 let mut led2 = Output::new(p.PB9, Level::Low, Speed::Low); 75 let mut led2 = Output::new(p.PB9, Level::Low, Speed::Low);
81 let mut led3 = Output::new(p.PB11, Level::Low, Speed::Low); 76 let mut led3 = Output::new(p.PB11, Level::Low, Speed::Low);
diff --git a/stm32-data b/stm32-data
Subproject 8530a19ffdcdcbc608a97b40895827d09e670eb Subproject 3fa97966f07d43a28c0031175591e1c2ff5d083