aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-10-23 00:28:54 +0200
committerDario Nieuwenhuis <[email protected]>2023-10-23 00:31:36 +0200
commitb9e13cb5d1ca3e85a02b2a37b7ee14f73663b1bd (patch)
tree1ae33453bcee12a6aaf4cfdd8dc1795187c7cadc /embassy-stm32/src
parent46ff2c82aa3193dd1378b142be284aa746045923 (diff)
stm32/rcc: merge wl into l4/l5.
Diffstat (limited to 'embassy-stm32/src')
-rw-r--r--embassy-stm32/src/ipcc.rs5
-rw-r--r--embassy-stm32/src/rcc/l4l5.rs153
-rw-r--r--embassy-stm32/src/rcc/mod.rs3
-rw-r--r--embassy-stm32/src/rcc/u5.rs2
-rw-r--r--embassy-stm32/src/rcc/wl.rs184
5 files changed, 112 insertions, 235 deletions
diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs
index 1b1e182f0..4006dee19 100644
--- a/embassy-stm32/src/ipcc.rs
+++ b/embassy-stm32/src/ipcc.rs
@@ -5,6 +5,7 @@ use core::task::Poll;
5use self::sealed::Instance; 5use self::sealed::Instance;
6use crate::interrupt; 6use crate::interrupt;
7use crate::interrupt::typelevel::Interrupt; 7use crate::interrupt::typelevel::Interrupt;
8use crate::pac::rcc::vals::{Lptim1sel, Lptim2sel};
8use crate::peripherals::IPCC; 9use crate::peripherals::IPCC;
9use crate::rcc::sealed::RccPeripheral; 10use crate::rcc::sealed::RccPeripheral;
10 11
@@ -273,7 +274,7 @@ fn _configure_pwr() {
273 274
274 // set LPTIM1 & LPTIM2 clock source 275 // set LPTIM1 & LPTIM2 clock source
275 rcc.ccipr().modify(|w| { 276 rcc.ccipr().modify(|w| {
276 w.set_lptim1sel(0b00); // PCLK 277 w.set_lptim1sel(Lptim1sel::PCLK1);
277 w.set_lptim2sel(0b00); // PCLK 278 w.set_lptim2sel(Lptim2sel::PCLK1);
278 }); 279 });
279} 280}
diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs
index 8cf284d1e..b56962270 100644
--- a/embassy-stm32/src/rcc/l4l5.rs
+++ b/embassy-stm32/src/rcc/l4l5.rs
@@ -1,8 +1,10 @@
1use crate::pac::rcc::regs::Cfgr; 1use crate::pac::rcc::regs::Cfgr;
2#[cfg(not(stm32wl))]
3pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
2use crate::pac::rcc::vals::Msirgsel; 4use crate::pac::rcc::vals::Msirgsel;
3pub use crate::pac::rcc::vals::{ 5pub use crate::pac::rcc::vals::{
4 Clk48sel as Clk48Src, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, 6 Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv,
5 Pllp as PllPDiv, Pllq as PllQDiv, Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc, 7 Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
6}; 8};
7use crate::pac::{FLASH, RCC}; 9use crate::pac::{FLASH, RCC};
8use crate::rcc::{set_freqs, Clocks}; 10use crate::rcc::{set_freqs, Clocks};
@@ -11,6 +13,22 @@ use crate::time::Hertz;
11/// HSI speed 13/// HSI speed
12pub const HSI_FREQ: Hertz = Hertz(16_000_000); 14pub const HSI_FREQ: Hertz = Hertz(16_000_000);
13 15
16#[derive(Clone, Copy, Eq, PartialEq)]
17pub enum HseMode {
18 /// crystal/ceramic oscillator (HSEBYP=0)
19 Oscillator,
20 /// external analog clock (low swing) (HSEBYP=1)
21 Bypass,
22}
23
24#[derive(Clone, Copy, Eq, PartialEq)]
25pub struct Hse {
26 /// HSE frequency.
27 pub freq: Hertz,
28 /// HSE mode.
29 pub mode: HseMode,
30}
31
14#[derive(Clone, Copy)] 32#[derive(Clone, Copy)]
15pub struct Pll { 33pub struct Pll {
16 /// PLL source 34 /// PLL source
@@ -35,12 +53,13 @@ pub struct Config {
35 // base clock sources 53 // base clock sources
36 pub msi: Option<MSIRange>, 54 pub msi: Option<MSIRange>,
37 pub hsi: bool, 55 pub hsi: bool,
38 pub hse: Option<Hertz>, 56 pub hse: Option<Hse>,
39 #[cfg(not(any(stm32l47x, stm32l48x)))] 57 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
40 pub hsi48: bool, 58 pub hsi48: bool,
41 59
42 // pll 60 // pll
43 pub pll: Option<Pll>, 61 pub pll: Option<Pll>,
62 #[cfg(any(stm32l4, stm32l5))]
44 pub pllsai1: Option<Pll>, 63 pub pllsai1: Option<Pll>,
45 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 64 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
46 pub pllsai2: Option<Pll>, 65 pub pllsai2: Option<Pll>,
@@ -50,8 +69,11 @@ pub struct Config {
50 pub ahb_pre: AHBPrescaler, 69 pub ahb_pre: AHBPrescaler,
51 pub apb1_pre: APBPrescaler, 70 pub apb1_pre: APBPrescaler,
52 pub apb2_pre: APBPrescaler, 71 pub apb2_pre: APBPrescaler,
72 #[cfg(stm32wl)]
73 pub shared_ahb_pre: AHBPrescaler,
53 74
54 // muxes 75 // muxes
76 #[cfg(not(stm32wl))]
55 pub clk48_src: Clk48Src, 77 pub clk48_src: Clk48Src,
56 78
57 // low speed LSI/LSE/RTC 79 // low speed LSI/LSE/RTC
@@ -69,12 +91,16 @@ impl Default for Config {
69 ahb_pre: AHBPrescaler::DIV1, 91 ahb_pre: AHBPrescaler::DIV1,
70 apb1_pre: APBPrescaler::DIV1, 92 apb1_pre: APBPrescaler::DIV1,
71 apb2_pre: APBPrescaler::DIV1, 93 apb2_pre: APBPrescaler::DIV1,
94 #[cfg(stm32wl)]
95 shared_ahb_pre: AHBPrescaler::DIV1,
72 pll: None, 96 pll: None,
97 #[cfg(any(stm32l4, stm32l5))]
73 pllsai1: None, 98 pllsai1: None,
74 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 99 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
75 pllsai2: None, 100 pllsai2: None,
76 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] 101 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
77 hsi48: true, 102 hsi48: true,
103 #[cfg(not(stm32wl))]
78 clk48_src: Clk48Src::HSI48, 104 clk48_src: Clk48Src::HSI48,
79 ls: Default::default(), 105 ls: Default::default(),
80 } 106 }
@@ -111,7 +137,7 @@ pub(crate) unsafe fn init(config: Config) {
111 137
112 let msi = config.msi.map(|range| { 138 let msi = config.msi.map(|range| {
113 // Enable MSI 139 // Enable MSI
114 RCC.cr().write(|w| { 140 RCC.cr().modify(|w| {
115 w.set_msirange(range); 141 w.set_msirange(range);
116 w.set_msirgsel(Msirgsel::CR); 142 w.set_msirgsel(Msirgsel::CR);
117 w.set_msion(true); 143 w.set_msion(true);
@@ -128,20 +154,26 @@ pub(crate) unsafe fn init(config: Config) {
128 }); 154 });
129 155
130 let hsi = config.hsi.then(|| { 156 let hsi = config.hsi.then(|| {
131 RCC.cr().write(|w| w.set_hsion(true)); 157 RCC.cr().modify(|w| w.set_hsion(true));
132 while !RCC.cr().read().hsirdy() {} 158 while !RCC.cr().read().hsirdy() {}
133 159
134 HSI_FREQ 160 HSI_FREQ
135 }); 161 });
136 162
137 let hse = config.hse.map(|freq| { 163 let hse = config.hse.map(|hse| {
138 RCC.cr().write(|w| w.set_hseon(true)); 164 RCC.cr().modify(|w| {
165 #[cfg(stm32wl)]
166 w.set_hsebyppwr(hse.mode == HseMode::Bypass);
167 #[cfg(not(stm32wl))]
168 w.set_hsebyp(hse.mode == HseMode::Bypass);
169 w.set_hseon(true);
170 });
139 while !RCC.cr().read().hserdy() {} 171 while !RCC.cr().read().hserdy() {}
140 172
141 freq 173 hse.freq
142 }); 174 });
143 175
144 #[cfg(not(any(stm32l47x, stm32l48x)))] 176 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))]
145 let hsi48 = config.hsi48.then(|| { 177 let hsi48 = config.hsi48.then(|| {
146 RCC.crrcr().modify(|w| w.set_hsi48on(true)); 178 RCC.crrcr().modify(|w| w.set_hsi48on(true));
147 while !RCC.crrcr().read().hsi48rdy() {} 179 while !RCC.crrcr().read().hsi48rdy() {}
@@ -153,6 +185,7 @@ pub(crate) unsafe fn init(config: Config) {
153 185
154 let _plls = [ 186 let _plls = [
155 &config.pll, 187 &config.pll,
188 #[cfg(any(stm32l4, stm32l5))]
156 &config.pllsai1, 189 &config.pllsai1,
157 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 190 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
158 &config.pllsai2, 191 &config.pllsai2,
@@ -169,8 +202,8 @@ pub(crate) unsafe fn init(config: Config) {
169 }), 202 }),
170 }; 203 };
171 204
172 // L4+ has shared PLLSRC, check it's equal in all PLLs. 205 // L4+, WL has shared PLLSRC, check it's equal in all PLLs.
173 #[cfg(any(rcc_l4plus))] 206 #[cfg(any(rcc_l4plus, stm32wl))]
174 match get_equal(_plls.into_iter().flatten().map(|p| p.source)) { 207 match get_equal(_plls.into_iter().flatten().map(|p| p.source)) {
175 Err(()) => panic!("Source must be equal across all enabled PLLs."), 208 Err(()) => panic!("Source must be equal across all enabled PLLs."),
176 Ok(None) => {} 209 Ok(None) => {}
@@ -181,6 +214,7 @@ pub(crate) unsafe fn init(config: Config) {
181 214
182 let pll_input = PllInput { hse, hsi, msi }; 215 let pll_input = PllInput { hse, hsi, msi };
183 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); 216 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
217 #[cfg(any(stm32l4, stm32l5))]
184 let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input); 218 let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
185 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 219 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
186 let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input); 220 let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
@@ -196,6 +230,7 @@ pub(crate) unsafe fn init(config: Config) {
196 RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); 230 RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
197 #[cfg(stm32l5)] 231 #[cfg(stm32l5)]
198 RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src)); 232 RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src));
233 #[cfg(not(stm32wl))]
199 let _clk48 = match config.clk48_src { 234 let _clk48 = match config.clk48_src {
200 Clk48Src::HSI48 => hsi48, 235 Clk48Src::HSI48 => hsi48,
201 Clk48Src::MSI => msi, 236 Clk48Src::MSI => msi,
@@ -208,38 +243,6 @@ pub(crate) unsafe fn init(config: Config) {
208 #[cfg(all(stm32l4, not(rcc_l4plus)))] 243 #[cfg(all(stm32l4, not(rcc_l4plus)))]
209 assert!(sys_clk.0 <= 80_000_000); 244 assert!(sys_clk.0 <= 80_000_000);
210 245
211 // Set flash wait states
212 #[cfg(stm32l4)]
213 FLASH.acr().modify(|w| {
214 w.set_latency(match sys_clk.0 {
215 0..=16_000_000 => 0,
216 0..=32_000_000 => 1,
217 0..=48_000_000 => 2,
218 0..=64_000_000 => 3,
219 _ => 4,
220 })
221 });
222 // VCORE Range 0 (performance), others TODO
223 #[cfg(stm32l5)]
224 FLASH.acr().modify(|w| {
225 w.set_latency(match sys_clk.0 {
226 0..=20_000_000 => 0,
227 0..=40_000_000 => 1,
228 0..=60_000_000 => 2,
229 0..=80_000_000 => 3,
230 0..=100_000_000 => 4,
231 _ => 5,
232 })
233 });
234
235 RCC.cfgr().modify(|w| {
236 w.set_sw(config.mux);
237 w.set_hpre(config.ahb_pre);
238 w.set_ppre1(config.apb1_pre);
239 w.set_ppre2(config.apb2_pre);
240 });
241 while RCC.cfgr().read().sws() != config.mux {}
242
243 let ahb_freq = sys_clk / config.ahb_pre; 246 let ahb_freq = sys_clk / config.ahb_pre;
244 247
245 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 248 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
@@ -258,15 +261,69 @@ pub(crate) unsafe fn init(config: Config) {
258 } 261 }
259 }; 262 };
260 263
264 #[cfg(stm32wl)]
265 let ahb3_freq = sys_clk / config.shared_ahb_pre;
266
267 // Set flash wait states
268 #[cfg(stm32l4)]
269 let latency = match sys_clk.0 {
270 0..=16_000_000 => 0,
271 0..=32_000_000 => 1,
272 0..=48_000_000 => 2,
273 0..=64_000_000 => 3,
274 _ => 4,
275 };
276 #[cfg(stm32l5)]
277 let latency = match sys_clk.0 {
278 // VCORE Range 0 (performance), others TODO
279 0..=20_000_000 => 0,
280 0..=40_000_000 => 1,
281 0..=60_000_000 => 2,
282 0..=80_000_000 => 3,
283 0..=100_000_000 => 4,
284 _ => 5,
285 };
286 #[cfg(stm32wl)]
287 let latency = match ahb3_freq.0 {
288 // VOS RANGE1, others TODO.
289 ..=18_000_000 => 0,
290 ..=36_000_000 => 1,
291 _ => 2,
292 };
293
294 FLASH.acr().modify(|w| w.set_latency(latency));
295 while FLASH.acr().read().latency() != latency {}
296
297 RCC.cfgr().modify(|w| {
298 w.set_sw(config.mux);
299 w.set_hpre(config.ahb_pre);
300 w.set_ppre1(config.apb1_pre);
301 w.set_ppre2(config.apb2_pre);
302 });
303 while RCC.cfgr().read().sws() != config.mux {}
304
305 #[cfg(stm32wl)]
306 {
307 RCC.extcfgr().modify(|w| {
308 w.set_shdhpre(config.shared_ahb_pre);
309 });
310 while !RCC.extcfgr().read().shdhpref() {}
311 }
312
261 set_freqs(Clocks { 313 set_freqs(Clocks {
262 sys: sys_clk, 314 sys: sys_clk,
263 hclk1: ahb_freq, 315 hclk1: ahb_freq,
264 hclk2: ahb_freq, 316 hclk2: ahb_freq,
317 #[cfg(not(stm32wl))]
265 hclk3: ahb_freq, 318 hclk3: ahb_freq,
266 pclk1: apb1_freq, 319 pclk1: apb1_freq,
267 pclk2: apb2_freq, 320 pclk2: apb2_freq,
268 pclk1_tim: apb1_tim_freq, 321 pclk1_tim: apb1_tim_freq,
269 pclk2_tim: apb2_tim_freq, 322 pclk2_tim: apb2_tim_freq,
323 #[cfg(stm32wl)]
324 hclk3: ahb3_freq,
325 #[cfg(stm32wl)]
326 pclk3: ahb3_freq,
270 #[cfg(rcc_l4)] 327 #[cfg(rcc_l4)]
271 hsi: None, 328 hsi: None,
272 #[cfg(rcc_l4)] 329 #[cfg(rcc_l4)]
@@ -330,6 +387,7 @@ struct PllOutput {
330#[derive(PartialEq, Eq, Clone, Copy)] 387#[derive(PartialEq, Eq, Clone, Copy)]
331enum PllInstance { 388enum PllInstance {
332 Pll, 389 Pll,
390 #[cfg(any(stm32l4, stm32l5))]
333 Pllsai1, 391 Pllsai1,
334 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 392 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
335 Pllsai2, 393 Pllsai2,
@@ -342,6 +400,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
342 RCC.cr().modify(|w| w.set_pllon(false)); 400 RCC.cr().modify(|w| w.set_pllon(false));
343 while RCC.cr().read().pllrdy() {} 401 while RCC.cr().read().pllrdy() {}
344 } 402 }
403 #[cfg(any(stm32l4, stm32l5))]
345 PllInstance::Pllsai1 => { 404 PllInstance::Pllsai1 => {
346 RCC.cr().modify(|w| w.set_pllsai1on(false)); 405 RCC.cr().modify(|w| w.set_pllsai1on(false));
347 while RCC.cr().read().pllsai1rdy() {} 406 while RCC.cr().read().pllsai1rdy() {}
@@ -356,7 +415,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
356 let Some(pll) = config else { return PllOutput::default() }; 415 let Some(pll) = config else { return PllOutput::default() };
357 416
358 let pll_src = match pll.source { 417 let pll_src = match pll.source {
359 PLLSource::NONE => panic!("must not select PLL source as NONE"), 418 PLLSource::DISABLE => panic!("must not select PLL source as NONE"),
360 PLLSource::HSE => input.hse, 419 PLLSource::HSE => input.hse,
361 PLLSource::HSI => input.hsi, 420 PLLSource::HSI => input.hsi,
362 PLLSource::MSI => input.msi, 421 PLLSource::MSI => input.msi,
@@ -400,6 +459,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
400 w.set_pllsrc(pll.source); 459 w.set_pllsrc(pll.source);
401 write_fields!(w); 460 write_fields!(w);
402 }), 461 }),
462 #[cfg(any(stm32l4, stm32l5))]
403 PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { 463 PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
404 #[cfg(any(rcc_l4plus, stm32l5))] 464 #[cfg(any(rcc_l4plus, stm32l5))]
405 w.set_pllm(pll.prediv); 465 w.set_pllm(pll.prediv);
@@ -423,6 +483,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
423 RCC.cr().modify(|w| w.set_pllon(true)); 483 RCC.cr().modify(|w| w.set_pllon(true));
424 while !RCC.cr().read().pllrdy() {} 484 while !RCC.cr().read().pllrdy() {}
425 } 485 }
486 #[cfg(any(stm32l4, stm32l5))]
426 PllInstance::Pllsai1 => { 487 PllInstance::Pllsai1 => {
427 RCC.cr().modify(|w| w.set_pllsai1on(true)); 488 RCC.cr().modify(|w| w.set_pllsai1on(true));
428 while !RCC.cr().read().pllsai1rdy() {} 489 while !RCC.cr().read().pllsai1rdy() {}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 49174b27f..78d54f803 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -19,11 +19,10 @@ pub use mco::*;
19#[cfg_attr(rcc_g4, path = "g4.rs")] 19#[cfg_attr(rcc_g4, path = "g4.rs")]
20#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")] 20#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7rm0433, rcc_h7ab), path = "h.rs")]
21#[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")] 21#[cfg_attr(any(rcc_l0, rcc_l0_v2, rcc_l1), path = "l0l1.rs")]
22#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5), path = "l4l5.rs")] 22#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle), path = "l4l5.rs")]
23#[cfg_attr(rcc_u5, path = "u5.rs")] 23#[cfg_attr(rcc_u5, path = "u5.rs")]
24#[cfg_attr(rcc_wb, path = "wb.rs")] 24#[cfg_attr(rcc_wb, path = "wb.rs")]
25#[cfg_attr(rcc_wba, path = "wba.rs")] 25#[cfg_attr(rcc_wba, path = "wba.rs")]
26#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
27mod _version; 26mod _version;
28#[cfg(feature = "low-power")] 27#[cfg(feature = "low-power")]
29use core::sync::atomic::{AtomicU32, Ordering}; 28use core::sync::atomic::{AtomicU32, Ordering};
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index 7664557e9..2bbacbbdc 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -170,7 +170,7 @@ impl Config {
170 170
171 RCC.icscr1().modify(|w| { 171 RCC.icscr1().modify(|w| {
172 w.set_msisrange(range); 172 w.set_msisrange(range);
173 w.set_msirgsel(Msirgsel::RCC_ICSCR1); 173 w.set_msirgsel(Msirgsel::ICSCR1);
174 }); 174 });
175 RCC.cr().write(|w| { 175 RCC.cr().write(|w| {
176 w.set_msipllen(false); 176 w.set_msipllen(false);
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs
deleted file mode 100644
index 4d68b55c2..000000000
--- a/embassy-stm32/src/rcc/wl.rs
+++ /dev/null
@@ -1,184 +0,0 @@
1pub use crate::pac::pwr::vals::Vos as VoltageScale;
2use crate::pac::rcc::vals::Sw;
3pub use crate::pac::rcc::vals::{
4 Adcsel as AdcClockSource, Hpre as AHBPrescaler, Msirange as MSIRange, Pllm, Plln, Pllp, Pllq, Pllr,
5 Pllsrc as PllSource, Ppre as APBPrescaler,
6};
7use crate::pac::{FLASH, RCC};
8use crate::rcc::{set_freqs, Clocks};
9use crate::time::Hertz;
10
11/// HSI speed
12pub const HSI_FREQ: Hertz = Hertz(16_000_000);
13
14/// HSE speed
15pub const HSE_FREQ: Hertz = Hertz(32_000_000);
16
17/// System clock mux source
18#[derive(Clone, Copy)]
19pub enum ClockSrc {
20 MSI(MSIRange),
21 HSE,
22 HSI,
23}
24
25/// Clocks configutation
26pub struct Config {
27 pub mux: ClockSrc,
28 pub ahb_pre: AHBPrescaler,
29 pub shd_ahb_pre: AHBPrescaler,
30 pub apb1_pre: APBPrescaler,
31 pub apb2_pre: APBPrescaler,
32 pub adc_clock_source: AdcClockSource,
33 pub ls: super::LsConfig,
34}
35
36impl Default for Config {
37 #[inline]
38 fn default() -> Config {
39 Config {
40 mux: ClockSrc::MSI(MSIRange::RANGE4M),
41 ahb_pre: AHBPrescaler::DIV1,
42 shd_ahb_pre: AHBPrescaler::DIV1,
43 apb1_pre: APBPrescaler::DIV1,
44 apb2_pre: APBPrescaler::DIV1,
45 adc_clock_source: AdcClockSource::HSI,
46 ls: Default::default(),
47 }
48 }
49}
50
51pub(crate) unsafe fn init(config: Config) {
52 let (sys_clk, sw, vos) = match config.mux {
53 ClockSrc::HSI => (HSI_FREQ, Sw::HSI, VoltageScale::RANGE2),
54 ClockSrc::HSE => (HSE_FREQ, Sw::HSE, VoltageScale::RANGE1),
55 ClockSrc::MSI(range) => (msirange_to_hertz(range), Sw::MSI, msirange_to_vos(range)),
56 };
57
58 let ahb_freq = sys_clk / config.ahb_pre;
59 let shd_ahb_freq = sys_clk / config.shd_ahb_pre;
60
61 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
62 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
63 pre => {
64 let freq = ahb_freq / pre;
65 (freq, freq * 2u32)
66 }
67 };
68
69 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
70 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
71 pre => {
72 let freq = ahb_freq / pre;
73 (freq, freq * 2u32)
74 }
75 };
76
77 // Adjust flash latency
78 let flash_clk_src_freq = shd_ahb_freq;
79 let ws = match vos {
80 VoltageScale::RANGE1 => match flash_clk_src_freq.0 {
81 0..=18_000_000 => 0b000,
82 18_000_001..=36_000_000 => 0b001,
83 _ => 0b010,
84 },
85 VoltageScale::RANGE2 => match flash_clk_src_freq.0 {
86 0..=6_000_000 => 0b000,
87 6_000_001..=12_000_000 => 0b001,
88 _ => 0b010,
89 },
90 _ => unreachable!(),
91 };
92
93 FLASH.acr().modify(|w| {
94 w.set_latency(ws);
95 });
96
97 while FLASH.acr().read().latency() != ws {}
98
99 match config.mux {
100 ClockSrc::HSI => {
101 // Enable HSI
102 RCC.cr().write(|w| w.set_hsion(true));
103 while !RCC.cr().read().hsirdy() {}
104 }
105 ClockSrc::HSE => {
106 // Enable HSE
107 RCC.cr().write(|w| {
108 w.set_hsebyppwr(true);
109 w.set_hseon(true);
110 });
111 while !RCC.cr().read().hserdy() {}
112 }
113 ClockSrc::MSI(range) => {
114 let cr = RCC.cr().read();
115 assert!(!cr.msion() || cr.msirdy());
116 RCC.cr().write(|w| {
117 w.set_msirgsel(true);
118 w.set_msirange(range);
119 w.set_msion(true);
120
121 // If LSE is enabled, enable calibration of MSI
122 w.set_msipllen(config.ls.lse.is_some());
123 });
124 while !RCC.cr().read().msirdy() {}
125 }
126 }
127
128 RCC.extcfgr().modify(|w| {
129 w.set_shdhpre(config.shd_ahb_pre);
130 });
131
132 RCC.cfgr().modify(|w| {
133 w.set_sw(sw.into());
134 w.set_hpre(config.ahb_pre);
135 w.set_ppre1(config.apb1_pre);
136 w.set_ppre2(config.apb2_pre);
137 });
138
139 // ADC clock MUX
140 RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source));
141
142 // TODO: switch voltage range
143
144 let rtc = config.ls.init();
145
146 set_freqs(Clocks {
147 sys: sys_clk,
148 hclk1: ahb_freq,
149 hclk2: ahb_freq,
150 hclk3: shd_ahb_freq,
151 pclk1: apb1_freq,
152 pclk2: apb2_freq,
153 pclk3: shd_ahb_freq,
154 pclk1_tim: apb1_tim_freq,
155 pclk2_tim: apb2_tim_freq,
156 rtc,
157 });
158}
159
160fn msirange_to_hertz(range: MSIRange) -> Hertz {
161 match range {
162 MSIRange::RANGE100K => Hertz(100_000),
163 MSIRange::RANGE200K => Hertz(200_000),
164 MSIRange::RANGE400K => Hertz(400_000),
165 MSIRange::RANGE800K => Hertz(800_000),
166 MSIRange::RANGE1M => Hertz(1_000_000),
167 MSIRange::RANGE2M => Hertz(2_000_000),
168 MSIRange::RANGE4M => Hertz(4_000_000),
169 MSIRange::RANGE8M => Hertz(8_000_000),
170 MSIRange::RANGE16M => Hertz(16_000_000),
171 MSIRange::RANGE24M => Hertz(24_000_000),
172 MSIRange::RANGE32M => Hertz(32_000_000),
173 MSIRange::RANGE48M => Hertz(48_000_000),
174 _ => unreachable!(),
175 }
176}
177
178fn msirange_to_vos(range: MSIRange) -> VoltageScale {
179 if range.to_bits() > MSIRange::RANGE16M.to_bits() {
180 VoltageScale::RANGE1
181 } else {
182 VoltageScale::RANGE2
183 }
184}