aboutsummaryrefslogtreecommitdiff
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
parent46ff2c82aa3193dd1378b142be284aa746045923 (diff)
stm32/rcc: merge wl into l4/l5.
-rw-r--r--embassy-stm32/Cargo.toml4
-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
-rw-r--r--examples/stm32l4/src/bin/rtc.rs29
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs34
-rw-r--r--examples/stm32wl/src/bin/lora_lorawan.rs22
-rw-r--r--examples/stm32wl/src/bin/random.rs23
-rw-r--r--tests/stm32/src/common.rs15
11 files changed, 198 insertions, 276 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 2d694267a..568a7eeb9 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -58,7 +58,7 @@ rand_core = "0.6.3"
58sdio-host = "0.5.0" 58sdio-host = "0.5.0"
59embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 59embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
60critical-section = "1.1" 60critical-section = "1.1"
61stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ee64389697d9234af374a89788aa52bb93d59284" } 61stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc" }
62vcell = "0.1.3" 62vcell = "0.1.3"
63bxcan = "0.7.0" 63bxcan = "0.7.0"
64nb = "1.0.0" 64nb = "1.0.0"
@@ -76,7 +76,7 @@ critical-section = { version = "1.1", features = ["std"] }
76[build-dependencies] 76[build-dependencies]
77proc-macro2 = "1.0.36" 77proc-macro2 = "1.0.36"
78quote = "1.0.15" 78quote = "1.0.15"
79stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-ee64389697d9234af374a89788aa52bb93d59284", default-features = false, features = ["metadata"]} 79stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-4ddcb77c9d213d11eebb048f40e112bc54163cdc", default-features = false, features = ["metadata"]}
80 80
81 81
82[features] 82[features]
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}
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs
index fec0a349d..69527c9ad 100644
--- a/examples/stm32l4/src/bin/rtc.rs
+++ b/examples/stm32l4/src/bin/rtc.rs
@@ -5,7 +5,6 @@
5use chrono::{NaiveDate, NaiveDateTime}; 5use chrono::{NaiveDate, NaiveDateTime};
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::rcc::{ClockSrc, LsConfig, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
9use embassy_stm32::rtc::{Rtc, RtcConfig}; 8use embassy_stm32::rtc::{Rtc, RtcConfig};
10use embassy_stm32::time::Hertz; 9use embassy_stm32::time::Hertz;
11use embassy_stm32::Config; 10use embassy_stm32::Config;
@@ -15,17 +14,23 @@ use {defmt_rtt as _, panic_probe as _};
15#[embassy_executor::main] 14#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 15async fn main(_spawner: Spawner) {
17 let mut config = Config::default(); 16 let mut config = Config::default();
18 config.rcc.mux = ClockSrc::PLL1_R; 17 {
19 config.rcc.hse = Some(Hertz::mhz(8)); 18 use embassy_stm32::rcc::*;
20 config.rcc.pll = Some(Pll { 19 config.rcc.mux = ClockSrc::PLL1_R;
21 source: PLLSource::HSE, 20 config.rcc.hse = Some(Hse {
22 prediv: PllPreDiv::DIV1, 21 freq: Hertz::mhz(8),
23 mul: PllMul::MUL20, 22 mode: HseMode::Oscillator,
24 divp: None, 23 });
25 divq: None, 24 config.rcc.pll = Some(Pll {
26 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2) 25 source: PLLSource::HSE,
27 }); 26 prediv: PllPreDiv::DIV1,
28 config.rcc.ls = LsConfig::default_lse(); 27 mul: PllMul::MUL20,
28 divp: None,
29 divq: None,
30 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
31 });
32 config.rcc.ls = LsConfig::default_lse();
33 }
29 let p = embassy_stm32::init(config); 34 let p = embassy_stm32::init(config);
30 35
31 info!("Hello World!"); 36 info!("Hello World!");
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 3c9d2cfc0..f76b504a7 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -48,7 +48,6 @@ use embassy_net_adin1110::{self, Device, Runner, ADIN1110};
48use embedded_hal_bus::spi::ExclusiveDevice; 48use embedded_hal_bus::spi::ExclusiveDevice;
49use hal::gpio::Pull; 49use hal::gpio::Pull;
50use hal::i2c::Config as I2C_Config; 50use hal::i2c::Config as I2C_Config;
51use hal::rcc::{ClockSrc, PLLSource, Pll, PllMul, PllPreDiv, PllRDiv};
52use hal::spi::{Config as SPI_Config, Spi}; 51use hal::spi::{Config as SPI_Config, Spi};
53use hal::time::Hertz; 52use hal::time::Hertz;
54 53
@@ -74,20 +73,25 @@ async fn main(spawner: Spawner) {
74 defmt::println!("Start main()"); 73 defmt::println!("Start main()");
75 74
76 let mut config = embassy_stm32::Config::default(); 75 let mut config = embassy_stm32::Config::default();
77 76 {
78 // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2) 77 use embassy_stm32::rcc::*;
79 // 80MHz highest frequency for flash 0 wait. 78 // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2)
80 config.rcc.mux = ClockSrc::PLL1_R; 79 // 80MHz highest frequency for flash 0 wait.
81 config.rcc.hse = Some(Hertz::mhz(8)); 80 config.rcc.mux = ClockSrc::PLL1_R;
82 config.rcc.pll = Some(Pll { 81 config.rcc.hse = Some(Hse {
83 source: PLLSource::HSE, 82 freq: Hertz::mhz(8),
84 prediv: PllPreDiv::DIV1, 83 mode: HseMode::Oscillator,
85 mul: PllMul::MUL20, 84 });
86 divp: None, 85 config.rcc.pll = Some(Pll {
87 divq: None, 86 source: PLLSource::HSE,
88 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2) 87 prediv: PllPreDiv::DIV1,
89 }); 88 mul: PllMul::MUL20,
90 config.rcc.hsi48 = true; // needed for rng 89 divp: None,
90 divq: None,
91 divr: Some(PllRDiv::DIV2), // sysclk 80Mhz clock (8 / 1 * 20 / 2)
92 });
93 config.rcc.hsi48 = true; // needed for rng
94 }
91 95
92 let dp = embassy_stm32::init(config); 96 let dp = embassy_stm32::init(config);
93 97
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
index 8c789afbc..e26c274ad 100644
--- a/examples/stm32wl/src/bin/lora_lorawan.rs
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -12,7 +12,8 @@ use embassy_lora::LoraTimer;
12use embassy_stm32::gpio::{Level, Output, Pin, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pin, Speed};
13use embassy_stm32::rng::{self, Rng}; 13use embassy_stm32::rng::{self, Rng};
14use embassy_stm32::spi::Spi; 14use embassy_stm32::spi::Spi;
15use embassy_stm32::{bind_interrupts, pac, peripherals}; 15use embassy_stm32::time::Hertz;
16use embassy_stm32::{bind_interrupts, peripherals};
16use embassy_time::Delay; 17use embassy_time::Delay;
17use lora_phy::mod_params::*; 18use lora_phy::mod_params::*;
18use lora_phy::sx1261_2::SX1261_2; 19use lora_phy::sx1261_2::SX1261_2;
@@ -33,11 +34,24 @@ bind_interrupts!(struct Irqs{
33#[embassy_executor::main] 34#[embassy_executor::main]
34async fn main(_spawner: Spawner) { 35async fn main(_spawner: Spawner) {
35 let mut config = embassy_stm32::Config::default(); 36 let mut config = embassy_stm32::Config::default();
36 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; 37 {
38 use embassy_stm32::rcc::*;
39 config.rcc.hse = Some(Hse {
40 freq: Hertz(32_000_000),
41 mode: HseMode::Bypass,
42 });
43 config.rcc.mux = ClockSrc::PLL1_R;
44 config.rcc.pll = Some(Pll {
45 source: PLLSource::HSE,
46 prediv: PllPreDiv::DIV2,
47 mul: PllMul::MUL6,
48 divp: None,
49 divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
50 divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
51 });
52 }
37 let p = embassy_stm32::init(config); 53 let p = embassy_stm32::init(config);
38 54
39 pac::RCC.ccipr().modify(|w| w.set_rngsel(0b01));
40
41 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 55 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
42 56
43 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx 57 // Set CTRL1 and CTRL3 for high-power transmission, while CTRL2 acts as an RF switch between tx and rx
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs
index 70676c704..2cf7ef9d0 100644
--- a/examples/stm32wl/src/bin/random.rs
+++ b/examples/stm32wl/src/bin/random.rs
@@ -4,9 +4,9 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_stm32::rcc::{ClockSrc, MSIRange};
8use embassy_stm32::rng::{self, Rng}; 7use embassy_stm32::rng::{self, Rng};
9use embassy_stm32::{bind_interrupts, pac, peripherals}; 8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, peripherals};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs{ 12bind_interrupts!(struct Irqs{
@@ -16,11 +16,24 @@ bind_interrupts!(struct Irqs{
16#[embassy_executor::main] 16#[embassy_executor::main]
17async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
18 let mut config = embassy_stm32::Config::default(); 18 let mut config = embassy_stm32::Config::default();
19 config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M); 19 {
20 use embassy_stm32::rcc::*;
21 config.rcc.hse = Some(Hse {
22 freq: Hertz(32_000_000),
23 mode: HseMode::Bypass,
24 });
25 config.rcc.mux = ClockSrc::PLL1_R;
26 config.rcc.pll = Some(Pll {
27 source: PLLSource::HSE,
28 prediv: PllPreDiv::DIV2,
29 mul: PllMul::MUL6,
30 divp: None,
31 divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
32 divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
33 });
34 }
20 let p = embassy_stm32::init(config); 35 let p = embassy_stm32::init(config);
21 36
22 pac::RCC.ccipr().modify(|w| w.set_rngsel(0b11)); // msi
23
24 info!("Hello World!"); 37 info!("Hello World!");
25 38
26 let mut rng = Rng::new(p.RNG, Irqs); 39 let mut rng = Rng::new(p.RNG, Irqs);
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 0a70e6a7e..cb1738154 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -402,9 +402,18 @@ pub fn config() -> Config {
402 #[cfg(feature = "stm32wl55jc")] 402 #[cfg(feature = "stm32wl55jc")]
403 { 403 {
404 use embassy_stm32::rcc::*; 404 use embassy_stm32::rcc::*;
405 config.rcc.mux = ClockSrc::MSI(MSIRange::RANGE32M); 405 config.rcc.hse = Some(Hse {
406 embassy_stm32::pac::RCC.ccipr().modify(|w| { 406 freq: Hertz(32_000_000),
407 w.set_rngsel(0b11); // msi 407 mode: HseMode::Bypass,
408 });
409 config.rcc.mux = ClockSrc::PLL1_R;
410 config.rcc.pll = Some(Pll {
411 source: PLLSource::HSE,
412 prediv: PllPreDiv::DIV2,
413 mul: PllMul::MUL6,
414 divp: None,
415 divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
416 divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
408 }); 417 });
409 } 418 }
410 419