aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh4
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/gpio.rs7
-rw-r--r--embassy-stm32/src/rcc/f4f7.rs13
-rw-r--r--embassy-stm32/src/rcc/h.rs110
-rw-r--r--embassy-stm32/src/rcc/l0l1.rs30
-rw-r--r--embassy-stm32/src/rcc/l4l5.rs218
-rw-r--r--embassy-stm32/src/rcc/mod.rs33
-rw-r--r--embassy-stm32/src/rcc/wb.rs258
-rw-r--r--examples/stm32h5/src/bin/eth.rs4
-rw-r--r--examples/stm32h5/src/bin/usb_serial.rs4
-rw-r--r--examples/stm32h7/src/bin/adc.rs7
-rw-r--r--examples/stm32h7/src/bin/camera.rs6
-rw-r--r--examples/stm32h7/src/bin/dac.rs7
-rw-r--r--examples/stm32h7/src/bin/dac_dma.rs7
-rw-r--r--examples/stm32h7/src/bin/eth.rs6
-rw-r--r--examples/stm32h7/src/bin/eth_client.rs6
-rw-r--r--examples/stm32h7/src/bin/fmc.rs6
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs6
-rw-r--r--examples/stm32h7/src/bin/pwm.rs6
-rw-r--r--examples/stm32h7/src/bin/sdmmc.rs6
-rw-r--r--examples/stm32h7/src/bin/spi.rs6
-rw-r--r--examples/stm32h7/src/bin/spi_dma.rs6
-rw-r--r--examples/stm32h7/src/bin/usb_serial.rs6
-rw-r--r--examples/stm32wl/src/bin/lora_lorawan.rs1
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_receive.rs19
-rw-r--r--examples/stm32wl/src/bin/lora_p2p_send.rs19
-rw-r--r--examples/stm32wl/src/bin/random.rs1
-rw-r--r--examples/stm32wl/src/bin/rtc.rs26
-rw-r--r--tests/stm32/src/common.rs24
30 files changed, 327 insertions, 529 deletions
diff --git a/ci.sh b/ci.sh
index ffd36a455..eac4d3711 100755
--- a/ci.sh
+++ b/ci.sh
@@ -221,8 +221,8 @@ rm out/tests/stm32wb55rg/wpan_ble
221# unstable, I think it's running out of RAM? 221# unstable, I think it's running out of RAM?
222rm out/tests/stm32f207zg/eth 222rm out/tests/stm32f207zg/eth
223 223
224# doesn't work. Wire in D0-D1 might be bad, or the special IOVDD2 PGx pins. 224# doesn't work, gives "noise error", no idea why. usart_dma does pass.
225rm out/tests/stm32u5a5zj/{gpio,usart*} 225rm out/tests/stm32u5a5zj/usart
226 226
227if [[ -z "${TELEPROBE_TOKEN-}" ]]; then 227if [[ -z "${TELEPROBE_TOKEN-}" ]]; then
228 echo No teleprobe token found, skipping running HIL tests 228 echo No teleprobe token found, skipping running HIL tests
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 568a7eeb9..992883402 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-4ddcb77c9d213d11eebb048f40e112bc54163cdc" } 61stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-bcc9b6bf9fa195e91625849efc4ba473d9ace4e9" }
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-4ddcb77c9d213d11eebb048f40e112bc54163cdc", default-features = false, features = ["metadata"]} 79stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-bcc9b6bf9fa195e91625849efc4ba473d9ace4e9", default-features = false, features = ["metadata"]}
80 80
81 81
82[features] 82[features]
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index e1702b008..011f4c07a 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -763,6 +763,13 @@ pub(crate) unsafe fn init(_cs: CriticalSection) {
763 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs); 763 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs);
764 764
765 crate::_generated::init_gpio(); 765 crate::_generated::init_gpio();
766
767 // Setting this bit is mandatory to use PG[15:2].
768 #[cfg(stm32u5)]
769 crate::pac::PWR.svmcr().modify(|w| {
770 w.set_io2sv(true);
771 w.set_io2vmen(true);
772 });
766} 773}
767 774
768mod eh02 { 775mod eh02 {
diff --git a/embassy-stm32/src/rcc/f4f7.rs b/embassy-stm32/src/rcc/f4f7.rs
index 3f9a2be67..2e4f95722 100644
--- a/embassy-stm32/src/rcc/f4f7.rs
+++ b/embassy-stm32/src/rcc/f4f7.rs
@@ -166,8 +166,8 @@ pub(crate) unsafe fn init(config: Config) {
166 }; 166 };
167 167
168 let hclk = sys / config.ahb_pre; 168 let hclk = sys / config.ahb_pre;
169 let (pclk1, pclk1_tim) = calc_pclk(hclk, config.apb1_pre); 169 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre);
170 let (pclk2, pclk2_tim) = calc_pclk(hclk, config.apb2_pre); 170 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre);
171 171
172 assert!(max::SYSCLK.contains(&sys)); 172 assert!(max::SYSCLK.contains(&sys));
173 assert!(max::HCLK.contains(&hclk)); 173 assert!(max::HCLK.contains(&hclk));
@@ -326,15 +326,6 @@ fn flash_setup(clk: Hertz) {
326 while FLASH.acr().read().latency() != latency {} 326 while FLASH.acr().read().latency() != latency {}
327} 327}
328 328
329fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
330where
331 Hertz: core::ops::Div<D, Output = Hertz>,
332{
333 let pclk = hclk / ppre;
334 let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
335 (pclk, pclk_tim)
336}
337
338#[cfg(stm32f7)] 329#[cfg(stm32f7)]
339mod max { 330mod max {
340 use core::ops::RangeInclusive; 331 use core::ops::RangeInclusive;
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index 8883763ec..7e924f0ac 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -6,8 +6,11 @@ use crate::pac::pwr::vals::Vos;
6pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource; 6pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
7#[cfg(stm32h7)] 7#[cfg(stm32h7)]
8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource; 8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
9use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre}; 9pub use crate::pac::rcc::vals::{
10pub use crate::pac::rcc::vals::{Ckpersel as PerClockSource, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul}; 10 Ckpersel as PerClockSource, Hsidiv as HSIPrescaler, Plldiv as PllDiv, Pllm as PllPreDiv, Plln as PllMul,
11 Pllsrc as PllSource, Sw as Sysclk,
12};
13use crate::pac::rcc::vals::{Ckpersel, Pllrge, Pllvcosel, Timpre};
11use crate::pac::{FLASH, PWR, RCC}; 14use crate::pac::{FLASH, PWR, RCC};
12use crate::rcc::{set_freqs, Clocks}; 15use crate::rcc::{set_freqs, Clocks};
13use crate::time::Hertz; 16use crate::time::Hertz;
@@ -58,41 +61,9 @@ pub struct Hse {
58 pub mode: HseMode, 61 pub mode: HseMode,
59} 62}
60 63
61#[derive(Clone, Copy, Eq, PartialEq)]
62pub enum Hsi {
63 /// 64Mhz
64 Mhz64,
65 /// 32Mhz (divided by 2)
66 Mhz32,
67 /// 16Mhz (divided by 4)
68 Mhz16,
69 /// 8Mhz (divided by 8)
70 Mhz8,
71}
72
73#[derive(Clone, Copy, Eq, PartialEq)]
74pub enum Sysclk {
75 /// HSI selected as sysclk
76 HSI,
77 /// HSE selected as sysclk
78 HSE,
79 /// CSI selected as sysclk
80 CSI,
81 /// PLL1_P selected as sysclk
82 Pll1P,
83}
84
85#[derive(Clone, Copy, Eq, PartialEq)]
86pub enum PllSource {
87 Hsi,
88 Csi,
89 Hse,
90}
91
92#[derive(Clone, Copy)] 64#[derive(Clone, Copy)]
93pub struct Pll { 65pub struct Pll {
94 /// Source clock selection. 66 /// Source clock selection.
95 #[cfg(stm32h5)]
96 pub source: PllSource, 67 pub source: PllSource,
97 68
98 /// PLL pre-divider (DIVM). 69 /// PLL pre-divider (DIVM).
@@ -152,15 +123,12 @@ impl From<TimerPrescaler> for Timpre {
152/// Configuration of the core clocks 123/// Configuration of the core clocks
153#[non_exhaustive] 124#[non_exhaustive]
154pub struct Config { 125pub struct Config {
155 pub hsi: Option<Hsi>, 126 pub hsi: Option<HSIPrescaler>,
156 pub hse: Option<Hse>, 127 pub hse: Option<Hse>,
157 pub csi: bool, 128 pub csi: bool,
158 pub hsi48: bool, 129 pub hsi48: bool,
159 pub sys: Sysclk, 130 pub sys: Sysclk,
160 131
161 #[cfg(stm32h7)]
162 pub pll_src: PllSource,
163
164 pub pll1: Option<Pll>, 132 pub pll1: Option<Pll>,
165 pub pll2: Option<Pll>, 133 pub pll2: Option<Pll>,
166 #[cfg(any(rcc_h5, stm32h7))] 134 #[cfg(any(rcc_h5, stm32h7))]
@@ -184,13 +152,11 @@ pub struct Config {
184impl Default for Config { 152impl Default for Config {
185 fn default() -> Self { 153 fn default() -> Self {
186 Self { 154 Self {
187 hsi: Some(Hsi::Mhz64), 155 hsi: Some(HSIPrescaler::DIV1),
188 hse: None, 156 hse: None,
189 csi: false, 157 csi: false,
190 hsi48: false, 158 hsi48: false,
191 sys: Sysclk::HSI, 159 sys: Sysclk::HSI,
192 #[cfg(stm32h7)]
193 pll_src: PllSource::Hsi,
194 pll1: None, 160 pll1: None,
195 pll2: None, 161 pll2: None,
196 #[cfg(any(rcc_h5, stm32h7))] 162 #[cfg(any(rcc_h5, stm32h7))]
@@ -303,19 +269,13 @@ pub(crate) unsafe fn init(config: Config) {
303 RCC.cr().modify(|w| w.set_hsion(false)); 269 RCC.cr().modify(|w| w.set_hsion(false));
304 None 270 None
305 } 271 }
306 Some(hsi) => { 272 Some(hsidiv) => {
307 let (freq, hsidiv) = match hsi {
308 Hsi::Mhz64 => (HSI_FREQ / 1u32, Hsidiv::DIV1),
309 Hsi::Mhz32 => (HSI_FREQ / 2u32, Hsidiv::DIV2),
310 Hsi::Mhz16 => (HSI_FREQ / 4u32, Hsidiv::DIV4),
311 Hsi::Mhz8 => (HSI_FREQ / 8u32, Hsidiv::DIV8),
312 };
313 RCC.cr().modify(|w| { 273 RCC.cr().modify(|w| {
314 w.set_hsidiv(hsidiv); 274 w.set_hsidiv(hsidiv);
315 w.set_hsion(true); 275 w.set_hsion(true);
316 }); 276 });
317 while !RCC.cr().read().hsirdy() {} 277 while !RCC.cr().read().hsirdy() {}
318 Some(freq) 278 Some(HSI_FREQ / hsidiv)
319 } 279 }
320 }; 280 };
321 281
@@ -360,25 +320,29 @@ pub(crate) unsafe fn init(config: Config) {
360 } 320 }
361 }; 321 };
362 322
323 // H7 has shared PLLSRC, check it's equal in all PLLs.
324 #[cfg(stm32h7)]
325 {
326 let plls = [&config.pll1, &config.pll2, &config.pll3];
327 if !super::util::all_equal(plls.into_iter().flatten().map(|p| p.source)) {
328 panic!("Source must be equal across all enabled PLLs.")
329 };
330 }
331
363 // Configure PLLs. 332 // Configure PLLs.
364 let pll_input = PllInput { 333 let pll_input = PllInput { csi, hse, hsi };
365 csi,
366 hse,
367 hsi,
368 #[cfg(stm32h7)]
369 source: config.pll_src,
370 };
371 let pll1 = init_pll(0, config.pll1, &pll_input); 334 let pll1 = init_pll(0, config.pll1, &pll_input);
372 let pll2 = init_pll(1, config.pll2, &pll_input); 335 let pll2 = init_pll(1, config.pll2, &pll_input);
373 #[cfg(any(rcc_h5, stm32h7))] 336 #[cfg(any(rcc_h5, stm32h7))]
374 let pll3 = init_pll(2, config.pll3, &pll_input); 337 let pll3 = init_pll(2, config.pll3, &pll_input);
375 338
376 // Configure sysclk 339 // Configure sysclk
377 let (sys, sw) = match config.sys { 340 let sys = match config.sys {
378 Sysclk::HSI => (unwrap!(hsi), Sw::HSI), 341 Sysclk::HSI => unwrap!(hsi),
379 Sysclk::HSE => (unwrap!(hse), Sw::HSE), 342 Sysclk::HSE => unwrap!(hse),
380 Sysclk::CSI => (unwrap!(csi), Sw::CSI), 343 Sysclk::CSI => unwrap!(csi),
381 Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1_P), 344 Sysclk::PLL1_P => unwrap!(pll1.p),
345 _ => unreachable!(),
382 }; 346 };
383 347
384 // Check limits. 348 // Check limits.
@@ -502,8 +466,8 @@ pub(crate) unsafe fn init(config: Config) {
502 466
503 RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into())); 467 RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into()));
504 468
505 RCC.cfgr().modify(|w| w.set_sw(sw)); 469 RCC.cfgr().modify(|w| w.set_sw(config.sys));
506 while RCC.cfgr().read().sws() != sw {} 470 while RCC.cfgr().read().sws() != config.sys {}
507 471
508 // IO compensation cell - Requires CSI clock and SYSCFG 472 // IO compensation cell - Requires CSI clock and SYSCFG
509 #[cfg(stm32h7)] // TODO h5 473 #[cfg(stm32h7)] // TODO h5
@@ -588,8 +552,6 @@ struct PllInput {
588 hsi: Option<Hertz>, 552 hsi: Option<Hertz>,
589 hse: Option<Hertz>, 553 hse: Option<Hertz>,
590 csi: Option<Hertz>, 554 csi: Option<Hertz>,
591 #[cfg(stm32h7)]
592 source: PllSource,
593} 555}
594 556
595struct PllOutput { 557struct PllOutput {
@@ -619,15 +581,11 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
619 }; 581 };
620 }; 582 };
621 583
622 #[cfg(stm32h5)] 584 let in_clk = match config.source {
623 let source = config.source; 585 PllSource::DISABLE => panic!("must not set PllSource::Disable"),
624 #[cfg(stm32h7)] 586 PllSource::HSI => unwrap!(input.hsi),
625 let source = input.source; 587 PllSource::HSE => unwrap!(input.hse),
626 588 PllSource::CSI => unwrap!(input.csi),
627 let (in_clk, src) = match source {
628 PllSource::Hsi => (unwrap!(input.hsi), Pllsrc::HSI),
629 PllSource::Hse => (unwrap!(input.hse), Pllsrc::HSE),
630 PllSource::Csi => (unwrap!(input.csi), Pllsrc::CSI),
631 }; 589 };
632 590
633 let ref_clk = in_clk / config.prediv as u32; 591 let ref_clk = in_clk / config.prediv as u32;
@@ -667,7 +625,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
667 625
668 #[cfg(stm32h5)] 626 #[cfg(stm32h5)]
669 RCC.pllcfgr(num).write(|w| { 627 RCC.pllcfgr(num).write(|w| {
670 w.set_pllsrc(src); 628 w.set_pllsrc(config.source);
671 w.set_divm(config.prediv); 629 w.set_divm(config.prediv);
672 w.set_pllvcosel(vco_range); 630 w.set_pllvcosel(vco_range);
673 w.set_pllrge(ref_range); 631 w.set_pllrge(ref_range);
@@ -681,7 +639,7 @@ fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
681 { 639 {
682 RCC.pllckselr().modify(|w| { 640 RCC.pllckselr().modify(|w| {
683 w.set_divm(num, config.prediv); 641 w.set_divm(num, config.prediv);
684 w.set_pllsrc(src); 642 w.set_pllsrc(config.source);
685 }); 643 });
686 RCC.pllcfgr().modify(|w| { 644 RCC.pllcfgr().modify(|w| {
687 w.set_pllvcosel(num, vco_range); 645 w.set_pllvcosel(num, vco_range);
diff --git a/embassy-stm32/src/rcc/l0l1.rs b/embassy-stm32/src/rcc/l0l1.rs
index 52e9ccb3c..9fb2062d6 100644
--- a/embassy-stm32/src/rcc/l0l1.rs
+++ b/embassy-stm32/src/rcc/l0l1.rs
@@ -156,23 +156,9 @@ pub(crate) unsafe fn init(config: Config) {
156 w.set_ppre2(config.apb2_pre); 156 w.set_ppre2(config.apb2_pre);
157 }); 157 });
158 158
159 let ahb_freq = sys_clk / config.ahb_pre; 159 let hclk1 = sys_clk / config.ahb_pre;
160 160 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
161 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 161 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
162 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
163 pre => {
164 let freq = ahb_freq / pre;
165 (freq, freq * 2u32)
166 }
167 };
168
169 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
170 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
171 pre => {
172 let freq = ahb_freq / pre;
173 (freq, freq * 2u32)
174 }
175 };
176 162
177 #[cfg(crs)] 163 #[cfg(crs)]
178 if config.enable_hsi48 { 164 if config.enable_hsi48 {
@@ -209,11 +195,11 @@ pub(crate) unsafe fn init(config: Config) {
209 195
210 set_freqs(Clocks { 196 set_freqs(Clocks {
211 sys: sys_clk, 197 sys: sys_clk,
212 hclk1: ahb_freq, 198 hclk1,
213 pclk1: apb1_freq, 199 pclk1,
214 pclk2: apb2_freq, 200 pclk2,
215 pclk1_tim: apb1_tim_freq, 201 pclk1_tim,
216 pclk2_tim: apb2_tim_freq, 202 pclk2_tim,
217 rtc, 203 rtc,
218 }); 204 });
219} 205}
diff --git a/embassy-stm32/src/rcc/l4l5.rs b/embassy-stm32/src/rcc/l4l5.rs
index b56962270..2f89f6821 100644
--- a/embassy-stm32/src/rcc/l4l5.rs
+++ b/embassy-stm32/src/rcc/l4l5.rs
@@ -1,7 +1,8 @@
1use crate::pac::rcc::regs::Cfgr; 1use crate::pac::rcc::regs::Cfgr;
2#[cfg(not(stm32wl))] 2#[cfg(any(stm32l4, stm32l5, stm32wb))]
3pub use crate::pac::rcc::vals::Clk48sel as Clk48Src; 3pub use crate::pac::rcc::vals::Clk48sel as Clk48Src;
4use crate::pac::rcc::vals::Msirgsel; 4#[cfg(any(stm32wb, stm32wl))]
5pub use crate::pac::rcc::vals::Hsepre as HsePrescaler;
5pub use crate::pac::rcc::vals::{ 6pub use crate::pac::rcc::vals::{
6 Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv, 7 Hpre as AHBPrescaler, Msirange as MSIRange, Pllm as PllPreDiv, Plln as PllMul, Pllp as PllPDiv, Pllq as PllQDiv,
7 Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc, 8 Pllr as PllRDiv, Pllsrc as PLLSource, Ppre as APBPrescaler, Sw as ClockSrc,
@@ -27,6 +28,9 @@ pub struct Hse {
27 pub freq: Hertz, 28 pub freq: Hertz,
28 /// HSE mode. 29 /// HSE mode.
29 pub mode: HseMode, 30 pub mode: HseMode,
31 /// HSE prescaler
32 #[cfg(any(stm32wb, stm32wl))]
33 pub prescaler: HsePrescaler,
30} 34}
31 35
32#[derive(Clone, Copy)] 36#[derive(Clone, Copy)]
@@ -54,12 +58,12 @@ pub struct Config {
54 pub msi: Option<MSIRange>, 58 pub msi: Option<MSIRange>,
55 pub hsi: bool, 59 pub hsi: bool,
56 pub hse: Option<Hse>, 60 pub hse: Option<Hse>,
57 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))] 61 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
58 pub hsi48: bool, 62 pub hsi48: bool,
59 63
60 // pll 64 // pll
61 pub pll: Option<Pll>, 65 pub pll: Option<Pll>,
62 #[cfg(any(stm32l4, stm32l5))] 66 #[cfg(any(stm32l4, stm32l5, stm32wb))]
63 pub pllsai1: Option<Pll>, 67 pub pllsai1: Option<Pll>,
64 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 68 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
65 pub pllsai2: Option<Pll>, 69 pub pllsai2: Option<Pll>,
@@ -69,11 +73,13 @@ pub struct Config {
69 pub ahb_pre: AHBPrescaler, 73 pub ahb_pre: AHBPrescaler,
70 pub apb1_pre: APBPrescaler, 74 pub apb1_pre: APBPrescaler,
71 pub apb2_pre: APBPrescaler, 75 pub apb2_pre: APBPrescaler,
72 #[cfg(stm32wl)] 76 #[cfg(any(stm32wl5x, stm32wb))]
77 pub core2_ahb_pre: AHBPrescaler,
78 #[cfg(any(stm32wl, stm32wb))]
73 pub shared_ahb_pre: AHBPrescaler, 79 pub shared_ahb_pre: AHBPrescaler,
74 80
75 // muxes 81 // muxes
76 #[cfg(not(stm32wl))] 82 #[cfg(any(stm32l4, stm32l5, stm32wb))]
77 pub clk48_src: Clk48Src, 83 pub clk48_src: Clk48Src,
78 84
79 // low speed LSI/LSE/RTC 85 // low speed LSI/LSE/RTC
@@ -91,28 +97,63 @@ impl Default for Config {
91 ahb_pre: AHBPrescaler::DIV1, 97 ahb_pre: AHBPrescaler::DIV1,
92 apb1_pre: APBPrescaler::DIV1, 98 apb1_pre: APBPrescaler::DIV1,
93 apb2_pre: APBPrescaler::DIV1, 99 apb2_pre: APBPrescaler::DIV1,
94 #[cfg(stm32wl)] 100 #[cfg(any(stm32wl5x, stm32wb))]
101 core2_ahb_pre: AHBPrescaler::DIV1,
102 #[cfg(any(stm32wl, stm32wb))]
95 shared_ahb_pre: AHBPrescaler::DIV1, 103 shared_ahb_pre: AHBPrescaler::DIV1,
96 pll: None, 104 pll: None,
97 #[cfg(any(stm32l4, stm32l5))] 105 #[cfg(any(stm32l4, stm32l5, stm32wb))]
98 pllsai1: None, 106 pllsai1: None,
99 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 107 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
100 pllsai2: None, 108 pllsai2: None,
101 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))] 109 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
102 hsi48: true, 110 hsi48: true,
103 #[cfg(not(stm32wl))] 111 #[cfg(any(stm32l4, stm32l5, stm32wb))]
104 clk48_src: Clk48Src::HSI48, 112 clk48_src: Clk48Src::HSI48,
105 ls: Default::default(), 113 ls: Default::default(),
106 } 114 }
107 } 115 }
108} 116}
109 117
118#[cfg(stm32wb)]
119pub const WPAN_DEFAULT: Config = Config {
120 hse: Some(Hse {
121 freq: Hertz(32_000_000),
122 mode: HseMode::Oscillator,
123 prescaler: HsePrescaler::DIV1,
124 }),
125 mux: ClockSrc::PLL1_R,
126 hsi48: true,
127 msi: None,
128 hsi: false,
129 clk48_src: Clk48Src::PLL1_Q,
130
131 ls: super::LsConfig::default_lse(),
132
133 pll: Some(Pll {
134 source: PLLSource::HSE,
135 prediv: PllPreDiv::DIV2,
136 mul: PllMul::MUL12,
137 divp: Some(PllPDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz
138 divq: Some(PllQDiv::DIV4), // 32 / 2 * 12 / 4 = 48Mhz
139 divr: Some(PllRDiv::DIV3), // 32 / 2 * 12 / 3 = 64Mhz
140 }),
141 pllsai1: None,
142
143 ahb_pre: AHBPrescaler::DIV1,
144 core2_ahb_pre: AHBPrescaler::DIV2,
145 shared_ahb_pre: AHBPrescaler::DIV1,
146 apb1_pre: APBPrescaler::DIV1,
147 apb2_pre: APBPrescaler::DIV1,
148};
149
110pub(crate) unsafe fn init(config: Config) { 150pub(crate) unsafe fn init(config: Config) {
111 // Switch to MSI to prevent problems with PLL configuration. 151 // Switch to MSI to prevent problems with PLL configuration.
112 if !RCC.cr().read().msion() { 152 if !RCC.cr().read().msion() {
113 // Turn on MSI and configure it to 4MHz. 153 // Turn on MSI and configure it to 4MHz.
114 RCC.cr().modify(|w| { 154 RCC.cr().modify(|w| {
115 w.set_msirgsel(Msirgsel::CR); 155 #[cfg(not(stm32wb))]
156 w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
116 w.set_msirange(MSIRange::RANGE4M); 157 w.set_msirange(MSIRange::RANGE4M);
117 w.set_msipllen(false); 158 w.set_msipllen(false);
118 w.set_msion(true) 159 w.set_msion(true)
@@ -138,8 +179,9 @@ pub(crate) unsafe fn init(config: Config) {
138 let msi = config.msi.map(|range| { 179 let msi = config.msi.map(|range| {
139 // Enable MSI 180 // Enable MSI
140 RCC.cr().modify(|w| { 181 RCC.cr().modify(|w| {
182 #[cfg(not(stm32wb))]
183 w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
141 w.set_msirange(range); 184 w.set_msirange(range);
142 w.set_msirgsel(Msirgsel::CR);
143 w.set_msion(true); 185 w.set_msion(true);
144 186
145 // If LSE is enabled, enable calibration of MSI 187 // If LSE is enabled, enable calibration of MSI
@@ -173,7 +215,7 @@ pub(crate) unsafe fn init(config: Config) {
173 hse.freq 215 hse.freq
174 }); 216 });
175 217
176 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5))] 218 #[cfg(any(all(stm32l4, not(any(stm32l47x, stm32l48x))), stm32l5, stm32wb))]
177 let hsi48 = config.hsi48.then(|| { 219 let hsi48 = config.hsi48.then(|| {
178 RCC.crrcr().modify(|w| w.set_hsi48on(true)); 220 RCC.crrcr().modify(|w| w.set_hsi48on(true));
179 while !RCC.crrcr().read().hsi48rdy() {} 221 while !RCC.crrcr().read().hsi48rdy() {}
@@ -185,7 +227,7 @@ pub(crate) unsafe fn init(config: Config) {
185 227
186 let _plls = [ 228 let _plls = [
187 &config.pll, 229 &config.pll,
188 #[cfg(any(stm32l4, stm32l5))] 230 #[cfg(any(stm32l4, stm32l5, stm32wb))]
189 &config.pllsai1, 231 &config.pllsai1,
190 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 232 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
191 &config.pllsai2, 233 &config.pllsai2,
@@ -193,7 +235,7 @@ pub(crate) unsafe fn init(config: Config) {
193 235
194 // L4 has shared PLLSRC, PLLM, check it's equal in all PLLs. 236 // L4 has shared PLLSRC, PLLM, check it's equal in all PLLs.
195 #[cfg(all(stm32l4, not(rcc_l4plus)))] 237 #[cfg(all(stm32l4, not(rcc_l4plus)))]
196 match get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) { 238 match super::util::get_equal(_plls.into_iter().flatten().map(|p| (p.source, p.prediv))) {
197 Err(()) => panic!("Source must be equal across all enabled PLLs."), 239 Err(()) => panic!("Source must be equal across all enabled PLLs."),
198 Ok(None) => {} 240 Ok(None) => {}
199 Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| { 241 Ok(Some((source, prediv))) => RCC.pllcfgr().write(|w| {
@@ -204,7 +246,7 @@ pub(crate) unsafe fn init(config: Config) {
204 246
205 // L4+, WL has shared PLLSRC, check it's equal in all PLLs. 247 // L4+, WL has shared PLLSRC, check it's equal in all PLLs.
206 #[cfg(any(rcc_l4plus, stm32wl))] 248 #[cfg(any(rcc_l4plus, stm32wl))]
207 match get_equal(_plls.into_iter().flatten().map(|p| p.source)) { 249 match super::util::get_equal(_plls.into_iter().flatten().map(|p| p.source)) {
208 Err(()) => panic!("Source must be equal across all enabled PLLs."), 250 Err(()) => panic!("Source must be equal across all enabled PLLs."),
209 Ok(None) => {} 251 Ok(None) => {}
210 Ok(Some(source)) => RCC.pllcfgr().write(|w| { 252 Ok(Some(source)) => RCC.pllcfgr().write(|w| {
@@ -214,7 +256,7 @@ pub(crate) unsafe fn init(config: Config) {
214 256
215 let pll_input = PllInput { hse, hsi, msi }; 257 let pll_input = PllInput { hse, hsi, msi };
216 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); 258 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
217 #[cfg(any(stm32l4, stm32l5))] 259 #[cfg(any(stm32l4, stm32l5, stm32wb))]
218 let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input); 260 let pllsai1 = init_pll(PllInstance::Pllsai1, config.pllsai1, &pll_input);
219 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 261 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
220 let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input); 262 let _pllsai2 = init_pll(PllInstance::Pllsai2, config.pllsai2, &pll_input);
@@ -223,19 +265,19 @@ pub(crate) unsafe fn init(config: Config) {
223 ClockSrc::HSE => hse.unwrap(), 265 ClockSrc::HSE => hse.unwrap(),
224 ClockSrc::HSI => hsi.unwrap(), 266 ClockSrc::HSI => hsi.unwrap(),
225 ClockSrc::MSI => msi.unwrap(), 267 ClockSrc::MSI => msi.unwrap(),
226 ClockSrc::PLL1_R => pll._r.unwrap(), 268 ClockSrc::PLL1_R => pll.r.unwrap(),
227 }; 269 };
228 270
229 #[cfg(stm32l4)] 271 #[cfg(stm32l4)]
230 RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src)); 272 RCC.ccipr().modify(|w| w.set_clk48sel(config.clk48_src));
231 #[cfg(stm32l5)] 273 #[cfg(stm32l5)]
232 RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src)); 274 RCC.ccipr1().modify(|w| w.set_clk48sel(config.clk48_src));
233 #[cfg(not(stm32wl))] 275 #[cfg(any(stm32l4, stm32l5, stm32wb))]
234 let _clk48 = match config.clk48_src { 276 let _clk48 = match config.clk48_src {
235 Clk48Src::HSI48 => hsi48, 277 Clk48Src::HSI48 => hsi48,
236 Clk48Src::MSI => msi, 278 Clk48Src::MSI => msi,
237 Clk48Src::PLLSAI1_Q => pllsai1._q, 279 Clk48Src::PLLSAI1_Q => pllsai1.q,
238 Clk48Src::PLL1_Q => pll._q, 280 Clk48Src::PLL1_Q => pll.q,
239 }; 281 };
240 282
241 #[cfg(rcc_l4plus)] 283 #[cfg(rcc_l4plus)]
@@ -243,30 +285,21 @@ pub(crate) unsafe fn init(config: Config) {
243 #[cfg(all(stm32l4, not(rcc_l4plus)))] 285 #[cfg(all(stm32l4, not(rcc_l4plus)))]
244 assert!(sys_clk.0 <= 80_000_000); 286 assert!(sys_clk.0 <= 80_000_000);
245 287
246 let ahb_freq = sys_clk / config.ahb_pre; 288 let hclk1 = sys_clk / config.ahb_pre;
247 289 let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
248 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 290 let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
249 APBPrescaler::DIV1 => (ahb_freq, ahb_freq), 291 #[cfg(not(any(stm32wl5x, stm32wb)))]
250 pre => { 292 let hclk2 = hclk1;
251 let freq = ahb_freq / pre; 293 #[cfg(any(stm32wl5x, stm32wb))]
252 (freq, freq * 2u32) 294 let hclk2 = sys_clk / config.core2_ahb_pre;
253 } 295 #[cfg(not(any(stm32wl, stm32wb)))]
254 }; 296 let hclk3 = hclk1;
255 297 #[cfg(any(stm32wl, stm32wb))]
256 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 298 let hclk3 = sys_clk / config.shared_ahb_pre;
257 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
258 pre => {
259 let freq = ahb_freq / pre;
260 (freq, freq * 2u32)
261 }
262 };
263
264 #[cfg(stm32wl)]
265 let ahb3_freq = sys_clk / config.shared_ahb_pre;
266 299
267 // Set flash wait states 300 // Set flash wait states
268 #[cfg(stm32l4)] 301 #[cfg(stm32l4)]
269 let latency = match sys_clk.0 { 302 let latency = match hclk1.0 {
270 0..=16_000_000 => 0, 303 0..=16_000_000 => 0,
271 0..=32_000_000 => 1, 304 0..=32_000_000 => 1,
272 0..=48_000_000 => 2, 305 0..=48_000_000 => 2,
@@ -274,7 +307,7 @@ pub(crate) unsafe fn init(config: Config) {
274 _ => 4, 307 _ => 4,
275 }; 308 };
276 #[cfg(stm32l5)] 309 #[cfg(stm32l5)]
277 let latency = match sys_clk.0 { 310 let latency = match hclk1.0 {
278 // VCORE Range 0 (performance), others TODO 311 // VCORE Range 0 (performance), others TODO
279 0..=20_000_000 => 0, 312 0..=20_000_000 => 0,
280 0..=40_000_000 => 1, 313 0..=40_000_000 => 1,
@@ -284,12 +317,21 @@ pub(crate) unsafe fn init(config: Config) {
284 _ => 5, 317 _ => 5,
285 }; 318 };
286 #[cfg(stm32wl)] 319 #[cfg(stm32wl)]
287 let latency = match ahb3_freq.0 { 320 let latency = match hclk3.0 {
288 // VOS RANGE1, others TODO. 321 // VOS RANGE1, others TODO.
289 ..=18_000_000 => 0, 322 ..=18_000_000 => 0,
290 ..=36_000_000 => 1, 323 ..=36_000_000 => 1,
291 _ => 2, 324 _ => 2,
292 }; 325 };
326 #[cfg(stm32wb)]
327 let latency = match hclk3.0 {
328 // VOS RANGE1, others TODO.
329 ..=18_000_000 => 0,
330 ..=36_000_000 => 1,
331 ..=54_000_000 => 2,
332 ..=64_000_000 => 3,
333 _ => 4,
334 };
293 335
294 FLASH.acr().modify(|w| w.set_latency(latency)); 336 FLASH.acr().modify(|w| w.set_latency(latency));
295 while FLASH.acr().read().latency() != latency {} 337 while FLASH.acr().read().latency() != latency {}
@@ -302,28 +344,29 @@ pub(crate) unsafe fn init(config: Config) {
302 }); 344 });
303 while RCC.cfgr().read().sws() != config.mux {} 345 while RCC.cfgr().read().sws() != config.mux {}
304 346
305 #[cfg(stm32wl)] 347 #[cfg(any(stm32wl, stm32wb))]
306 { 348 {
307 RCC.extcfgr().modify(|w| { 349 RCC.extcfgr().modify(|w| {
308 w.set_shdhpre(config.shared_ahb_pre); 350 w.set_shdhpre(config.shared_ahb_pre);
351 #[cfg(any(stm32wl5x, stm32wb))]
352 w.set_c2hpre(config.core2_ahb_pre);
309 }); 353 });
310 while !RCC.extcfgr().read().shdhpref() {} 354 while !RCC.extcfgr().read().shdhpref() {}
355 #[cfg(any(stm32wl5x, stm32wb))]
356 while !RCC.extcfgr().read().c2hpref() {}
311 } 357 }
312 358
313 set_freqs(Clocks { 359 set_freqs(Clocks {
314 sys: sys_clk, 360 sys: sys_clk,
315 hclk1: ahb_freq, 361 hclk1,
316 hclk2: ahb_freq, 362 hclk2,
317 #[cfg(not(stm32wl))] 363 hclk3,
318 hclk3: ahb_freq, 364 pclk1,
319 pclk1: apb1_freq, 365 pclk2,
320 pclk2: apb2_freq, 366 pclk1_tim,
321 pclk1_tim: apb1_tim_freq, 367 pclk2_tim,
322 pclk2_tim: apb2_tim_freq,
323 #[cfg(stm32wl)]
324 hclk3: ahb3_freq,
325 #[cfg(stm32wl)] 368 #[cfg(stm32wl)]
326 pclk3: ahb3_freq, 369 pclk3: hclk3,
327 #[cfg(rcc_l4)] 370 #[cfg(rcc_l4)]
328 hsi: None, 371 hsi: None,
329 #[cfg(rcc_l4)] 372 #[cfg(rcc_l4)]
@@ -362,60 +405,56 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz {
362 } 405 }
363} 406}
364 407
365#[allow(unused)]
366fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
367 let Some(x) = iter.next() else { return Ok(None) };
368 if !iter.all(|y| y == x) {
369 return Err(());
370 }
371 return Ok(Some(x));
372}
373
374struct PllInput { 408struct PllInput {
375 hsi: Option<Hertz>, 409 hsi: Option<Hertz>,
376 hse: Option<Hertz>, 410 hse: Option<Hertz>,
377 msi: Option<Hertz>, 411 msi: Option<Hertz>,
378} 412}
379 413
414#[allow(unused)]
380#[derive(Default)] 415#[derive(Default)]
381struct PllOutput { 416struct PllOutput {
382 _p: Option<Hertz>, 417 p: Option<Hertz>,
383 _q: Option<Hertz>, 418 q: Option<Hertz>,
384 _r: Option<Hertz>, 419 r: Option<Hertz>,
385} 420}
386 421
387#[derive(PartialEq, Eq, Clone, Copy)] 422#[derive(PartialEq, Eq, Clone, Copy)]
388enum PllInstance { 423enum PllInstance {
389 Pll, 424 Pll,
390 #[cfg(any(stm32l4, stm32l5))] 425 #[cfg(any(stm32l4, stm32l5, stm32wb))]
391 Pllsai1, 426 Pllsai1,
392 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 427 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
393 Pllsai2, 428 Pllsai2,
394} 429}
395 430
396fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput { 431fn pll_enable(instance: PllInstance, enabled: bool) {
397 // Disable PLL
398 match instance { 432 match instance {
399 PllInstance::Pll => { 433 PllInstance::Pll => {
400 RCC.cr().modify(|w| w.set_pllon(false)); 434 RCC.cr().modify(|w| w.set_pllon(enabled));
401 while RCC.cr().read().pllrdy() {} 435 while RCC.cr().read().pllrdy() != enabled {}
402 } 436 }
403 #[cfg(any(stm32l4, stm32l5))] 437 #[cfg(any(stm32l4, stm32l5, stm32wb))]
404 PllInstance::Pllsai1 => { 438 PllInstance::Pllsai1 => {
405 RCC.cr().modify(|w| w.set_pllsai1on(false)); 439 RCC.cr().modify(|w| w.set_pllsai1on(enabled));
406 while RCC.cr().read().pllsai1rdy() {} 440 while RCC.cr().read().pllsai1rdy() != enabled {}
407 } 441 }
408 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))] 442 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
409 PllInstance::Pllsai2 => { 443 PllInstance::Pllsai2 => {
410 RCC.cr().modify(|w| w.set_pllsai2on(false)); 444 RCC.cr().modify(|w| w.set_pllsai2on(enabled));
411 while RCC.cr().read().pllsai2rdy() {} 445 while RCC.cr().read().pllsai2rdy() != enabled {}
412 } 446 }
413 } 447 }
448}
449
450fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> PllOutput {
451 // Disable PLL
452 pll_enable(instance, false);
414 453
415 let Some(pll) = config else { return PllOutput::default() }; 454 let Some(pll) = config else { return PllOutput::default() };
416 455
417 let pll_src = match pll.source { 456 let pll_src = match pll.source {
418 PLLSource::DISABLE => panic!("must not select PLL source as NONE"), 457 PLLSource::DISABLE => panic!("must not select PLL source as DISABLE"),
419 PLLSource::HSE => input.hse, 458 PLLSource::HSE => input.hse,
420 PLLSource::HSI => input.hsi, 459 PLLSource::HSI => input.hsi,
421 PLLSource::MSI => input.msi, 460 PLLSource::MSI => input.msi,
@@ -459,7 +498,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
459 w.set_pllsrc(pll.source); 498 w.set_pllsrc(pll.source);
460 write_fields!(w); 499 write_fields!(w);
461 }), 500 }),
462 #[cfg(any(stm32l4, stm32l5))] 501 #[cfg(any(stm32l4, stm32l5, stm32wb))]
463 PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| { 502 PllInstance::Pllsai1 => RCC.pllsai1cfgr().write(|w| {
464 #[cfg(any(rcc_l4plus, stm32l5))] 503 #[cfg(any(rcc_l4plus, stm32l5))]
465 w.set_pllm(pll.prediv); 504 w.set_pllm(pll.prediv);
@@ -478,22 +517,7 @@ fn init_pll(instance: PllInstance, config: Option<Pll>, input: &PllInput) -> Pll
478 } 517 }
479 518
480 // Enable PLL 519 // Enable PLL
481 match instance { 520 pll_enable(instance, true);
482 PllInstance::Pll => {
483 RCC.cr().modify(|w| w.set_pllon(true));
484 while !RCC.cr().read().pllrdy() {}
485 }
486 #[cfg(any(stm32l4, stm32l5))]
487 PllInstance::Pllsai1 => {
488 RCC.cr().modify(|w| w.set_pllsai1on(true));
489 while !RCC.cr().read().pllsai1rdy() {}
490 }
491 #[cfg(any(stm32l47x, stm32l48x, stm32l49x, stm32l4ax, rcc_l4plus, stm32l5))]
492 PllInstance::Pllsai2 => {
493 RCC.cr().modify(|w| w.set_pllsai2on(true));
494 while !RCC.cr().read().pllsai2rdy() {}
495 }
496 }
497 521
498 PllOutput { _p: p, _q: q, _r: r } 522 PllOutput { p, q, r }
499} 523}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 78d54f803..8cf2d6ab0 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -19,9 +19,8 @@ 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, rcc_wl5, rcc_wle), path = "l4l5.rs")] 22#[cfg_attr(any(rcc_l4, rcc_l4plus, rcc_l5, rcc_wl5, rcc_wle, rcc_wb), 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")]
25#[cfg_attr(rcc_wba, path = "wba.rs")] 24#[cfg_attr(rcc_wba, path = "wba.rs")]
26mod _version; 25mod _version;
27#[cfg(feature = "low-power")] 26#[cfg(feature = "low-power")]
@@ -247,3 +246,33 @@ pub(crate) mod sealed {
247} 246}
248 247
249pub trait RccPeripheral: sealed::RccPeripheral + 'static {} 248pub trait RccPeripheral: sealed::RccPeripheral + 'static {}
249
250#[allow(unused)]
251mod util {
252 use crate::time::Hertz;
253
254 pub fn calc_pclk<D>(hclk: Hertz, ppre: D) -> (Hertz, Hertz)
255 where
256 Hertz: core::ops::Div<D, Output = Hertz>,
257 {
258 let pclk = hclk / ppre;
259 let pclk_tim = if hclk == pclk { pclk } else { pclk * 2u32 };
260 (pclk, pclk_tim)
261 }
262
263 pub fn all_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> bool {
264 let Some(x) = iter.next() else { return true };
265 if !iter.all(|y| y == x) {
266 return false;
267 }
268 true
269 }
270
271 pub fn get_equal<T: Eq>(mut iter: impl Iterator<Item = T>) -> Result<Option<T>, ()> {
272 let Some(x) = iter.next() else { return Ok(None) };
273 if !iter.all(|y| y == x) {
274 return Err(());
275 }
276 Ok(Some(x))
277 }
278}
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs
deleted file mode 100644
index 2d0b2711a..000000000
--- a/embassy-stm32/src/rcc/wb.rs
+++ /dev/null
@@ -1,258 +0,0 @@
1pub use crate::pac::rcc::vals::{
2 Hpre as AHBPrescaler, Hsepre as HsePrescaler, Pllm, Plln, Pllp, Pllq, Pllr, Pllsrc as PllSource,
3 Ppre as APBPrescaler, Sw as Sysclk,
4};
5use crate::rcc::{set_freqs, Clocks};
6use crate::time::{mhz, Hertz};
7
8/// HSI speed
9pub const HSI_FREQ: Hertz = Hertz(16_000_000);
10
11pub struct Hse {
12 pub prediv: HsePrescaler,
13
14 pub frequency: Hertz,
15}
16
17pub struct PllMux {
18 /// Source clock selection.
19 pub source: PllSource,
20
21 /// PLL pre-divider (DIVM). Must be between 1 and 63.
22 pub prediv: Pllm,
23}
24
25pub struct Pll {
26 /// PLL multiplication factor. Must be between 4 and 512.
27 pub mul: Plln,
28
29 /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
30 /// On PLL1, it must be even (in particular, it cannot be 1.)
31 pub divp: Option<Pllp>,
32 /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
33 pub divq: Option<Pllq>,
34 /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
35 pub divr: Option<Pllr>,
36}
37
38/// Clocks configutation
39pub struct Config {
40 pub hse: Option<Hse>,
41 pub sys: Sysclk,
42 pub mux: Option<PllMux>,
43 pub hsi48: bool,
44
45 pub pll: Option<Pll>,
46 pub pllsai: Option<Pll>,
47
48 pub ahb1_pre: AHBPrescaler,
49 pub ahb2_pre: AHBPrescaler,
50 pub ahb3_pre: AHBPrescaler,
51 pub apb1_pre: APBPrescaler,
52 pub apb2_pre: APBPrescaler,
53
54 pub ls: super::LsConfig,
55}
56
57pub const WPAN_DEFAULT: Config = Config {
58 hse: Some(Hse {
59 frequency: mhz(32),
60 prediv: HsePrescaler::DIV1,
61 }),
62 sys: Sysclk::PLL1_R,
63 mux: Some(PllMux {
64 source: PllSource::HSE,
65 prediv: Pllm::DIV2,
66 }),
67 hsi48: true,
68
69 ls: super::LsConfig::default_lse(),
70
71 pll: Some(Pll {
72 mul: Plln::MUL12,
73 divp: Some(Pllp::DIV3),
74 divq: Some(Pllq::DIV4),
75 divr: Some(Pllr::DIV3),
76 }),
77 pllsai: None,
78
79 ahb1_pre: AHBPrescaler::DIV1,
80 ahb2_pre: AHBPrescaler::DIV2,
81 ahb3_pre: AHBPrescaler::DIV1,
82 apb1_pre: APBPrescaler::DIV1,
83 apb2_pre: APBPrescaler::DIV1,
84};
85
86impl Default for Config {
87 #[inline]
88 fn default() -> Config {
89 Config {
90 sys: Sysclk::HSI,
91 hse: None,
92 mux: None,
93 pll: None,
94 pllsai: None,
95 hsi48: true,
96
97 ls: Default::default(),
98
99 ahb1_pre: AHBPrescaler::DIV1,
100 ahb2_pre: AHBPrescaler::DIV1,
101 ahb3_pre: AHBPrescaler::DIV1,
102 apb1_pre: APBPrescaler::DIV1,
103 apb2_pre: APBPrescaler::DIV1,
104 }
105 }
106}
107
108#[cfg(stm32wb)]
109/// RCC initialization function
110pub(crate) unsafe fn init(config: Config) {
111 let hse_clk = config.hse.as_ref().map(|hse| hse.frequency / hse.prediv);
112
113 let mux_clk = config.mux.as_ref().map(|pll_mux| {
114 (match pll_mux.source {
115 PllSource::HSE => hse_clk.unwrap(),
116 PllSource::HSI => HSI_FREQ,
117 _ => unreachable!(),
118 } / pll_mux.prediv)
119 });
120
121 let (pll_r, _pll_q, _pll_p) = match &config.pll {
122 Some(pll) => {
123 let pll_vco = mux_clk.unwrap() * pll.mul as u32;
124
125 (
126 pll.divr.map(|divr| pll_vco / divr),
127 pll.divq.map(|divq| pll_vco / divq),
128 pll.divp.map(|divp| pll_vco / divp),
129 )
130 }
131 None => (None, None, None),
132 };
133
134 let sys_clk = match config.sys {
135 Sysclk::HSE => hse_clk.unwrap(),
136 Sysclk::HSI => HSI_FREQ,
137 Sysclk::PLL1_R => pll_r.unwrap(),
138 _ => unreachable!(),
139 };
140
141 let ahb1_clk = sys_clk / config.ahb1_pre;
142 let ahb2_clk = sys_clk / config.ahb2_pre;
143 let ahb3_clk = sys_clk / config.ahb3_pre;
144
145 let (apb1_clk, apb1_tim_clk) = match config.apb1_pre {
146 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
147 pre => {
148 let freq = ahb1_clk / pre;
149 (freq, freq * 2u32)
150 }
151 };
152
153 let (apb2_clk, apb2_tim_clk) = match config.apb2_pre {
154 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
155 pre => {
156 let freq = ahb1_clk / pre;
157 (freq, freq * 2u32)
158 }
159 };
160
161 let rcc = crate::pac::RCC;
162
163 let needs_hsi = if let Some(pll_mux) = &config.mux {
164 pll_mux.source == PllSource::HSI
165 } else {
166 false
167 };
168
169 if needs_hsi || config.sys == Sysclk::HSI {
170 rcc.cr().modify(|w| {
171 w.set_hsion(true);
172 });
173
174 while !rcc.cr().read().hsirdy() {}
175 }
176
177 rcc.cfgr().modify(|w| w.set_stopwuck(true));
178
179 let rtc = config.ls.init();
180
181 match &config.hse {
182 Some(hse) => {
183 rcc.cr().modify(|w| {
184 w.set_hsepre(hse.prediv);
185 w.set_hseon(true);
186 });
187
188 while !rcc.cr().read().hserdy() {}
189 }
190 _ => {}
191 }
192
193 match &config.mux {
194 Some(pll_mux) => {
195 rcc.pllcfgr().modify(|w| {
196 w.set_pllm(pll_mux.prediv);
197 w.set_pllsrc(pll_mux.source.into());
198 });
199 }
200 _ => {}
201 };
202
203 match &config.pll {
204 Some(pll) => {
205 rcc.pllcfgr().modify(|w| {
206 w.set_plln(pll.mul);
207 pll.divp.map(|divp| {
208 w.set_pllpen(true);
209 w.set_pllp(divp)
210 });
211 pll.divq.map(|divq| {
212 w.set_pllqen(true);
213 w.set_pllq(divq)
214 });
215 pll.divr.map(|divr| {
216 w.set_pllren(true);
217 w.set_pllr(divr);
218 });
219 });
220
221 rcc.cr().modify(|w| w.set_pllon(true));
222
223 while !rcc.cr().read().pllrdy() {}
224 }
225 _ => {}
226 }
227
228 let _hsi48 = config.hsi48.then(|| {
229 rcc.crrcr().modify(|w| w.set_hsi48on(true));
230 while !rcc.crrcr().read().hsi48rdy() {}
231
232 Hertz(48_000_000)
233 });
234
235 rcc.cfgr().modify(|w| {
236 w.set_sw(config.sys.into());
237 w.set_hpre(config.ahb1_pre);
238 w.set_ppre1(config.apb1_pre);
239 w.set_ppre2(config.apb2_pre);
240 });
241
242 rcc.extcfgr().modify(|w| {
243 w.set_c2hpre(config.ahb2_pre);
244 w.set_shdhpre(config.ahb3_pre);
245 });
246
247 set_freqs(Clocks {
248 sys: sys_clk,
249 hclk1: ahb1_clk,
250 hclk2: ahb2_clk,
251 hclk3: ahb3_clk,
252 pclk1: apb1_clk,
253 pclk2: apb2_clk,
254 pclk1_tim: apb1_tim_clk,
255 pclk2_tim: apb2_tim_clk,
256 rtc,
257 })
258}
diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs
index 6e40f0ac0..5bec9d447 100644
--- a/examples/stm32h5/src/bin/eth.rs
+++ b/examples/stm32h5/src/bin/eth.rs
@@ -43,7 +43,7 @@ async fn main(spawner: Spawner) -> ! {
43 mode: HseMode::BypassDigital, 43 mode: HseMode::BypassDigital,
44 }); 44 });
45 config.rcc.pll1 = Some(Pll { 45 config.rcc.pll1 = Some(Pll {
46 source: PllSource::Hse, 46 source: PllSource::HSE,
47 prediv: PllPreDiv::DIV2, 47 prediv: PllPreDiv::DIV2,
48 mul: PllMul::MUL125, 48 mul: PllMul::MUL125,
49 divp: Some(PllDiv::DIV2), 49 divp: Some(PllDiv::DIV2),
@@ -54,7 +54,7 @@ async fn main(spawner: Spawner) -> ! {
54 config.rcc.apb1_pre = APBPrescaler::DIV1; 54 config.rcc.apb1_pre = APBPrescaler::DIV1;
55 config.rcc.apb2_pre = APBPrescaler::DIV1; 55 config.rcc.apb2_pre = APBPrescaler::DIV1;
56 config.rcc.apb3_pre = APBPrescaler::DIV1; 56 config.rcc.apb3_pre = APBPrescaler::DIV1;
57 config.rcc.sys = Sysclk::Pll1P; 57 config.rcc.sys = Sysclk::PLL1_P;
58 config.rcc.voltage_scale = VoltageScale::Scale0; 58 config.rcc.voltage_scale = VoltageScale::Scale0;
59 let p = embassy_stm32::init(config); 59 let p = embassy_stm32::init(config);
60 info!("Hello World!"); 60 info!("Hello World!");
diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs
index 3b3c38e17..735826a69 100644
--- a/examples/stm32h5/src/bin/usb_serial.rs
+++ b/examples/stm32h5/src/bin/usb_serial.rs
@@ -30,7 +30,7 @@ async fn main(_spawner: Spawner) {
30 mode: HseMode::BypassDigital, 30 mode: HseMode::BypassDigital,
31 }); 31 });
32 config.rcc.pll1 = Some(Pll { 32 config.rcc.pll1 = Some(Pll {
33 source: PllSource::Hse, 33 source: PllSource::HSE,
34 prediv: PllPreDiv::DIV2, 34 prediv: PllPreDiv::DIV2,
35 mul: PllMul::MUL125, 35 mul: PllMul::MUL125,
36 divp: Some(PllDiv::DIV2), // 250mhz 36 divp: Some(PllDiv::DIV2), // 250mhz
@@ -41,7 +41,7 @@ async fn main(_spawner: Spawner) {
41 config.rcc.apb1_pre = APBPrescaler::DIV4; 41 config.rcc.apb1_pre = APBPrescaler::DIV4;
42 config.rcc.apb2_pre = APBPrescaler::DIV2; 42 config.rcc.apb2_pre = APBPrescaler::DIV2;
43 config.rcc.apb3_pre = APBPrescaler::DIV4; 43 config.rcc.apb3_pre = APBPrescaler::DIV4;
44 config.rcc.sys = Sysclk::Pll1P; 44 config.rcc.sys = Sysclk::PLL1_P;
45 config.rcc.voltage_scale = VoltageScale::Scale0; 45 config.rcc.voltage_scale = VoltageScale::Scale0;
46 let p = embassy_stm32::init(config); 46 let p = embassy_stm32::init(config);
47 47
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs
index 4a358a35f..e367827e9 100644
--- a/examples/stm32h7/src/bin/adc.rs
+++ b/examples/stm32h7/src/bin/adc.rs
@@ -14,10 +14,10 @@ async fn main(_spawner: Spawner) {
14 let mut config = Config::default(); 14 let mut config = Config::default();
15 { 15 {
16 use embassy_stm32::rcc::*; 16 use embassy_stm32::rcc::*;
17 config.rcc.hsi = Some(Hsi::Mhz64); 17 config.rcc.hsi = Some(HSIPrescaler::DIV1);
18 config.rcc.csi = true; 18 config.rcc.csi = true;
19 config.rcc.pll_src = PllSource::Hsi;
20 config.rcc.pll1 = Some(Pll { 19 config.rcc.pll1 = Some(Pll {
20 source: PllSource::HSI,
21 prediv: PllPreDiv::DIV4, 21 prediv: PllPreDiv::DIV4,
22 mul: PllMul::MUL50, 22 mul: PllMul::MUL50,
23 divp: Some(PllDiv::DIV2), 23 divp: Some(PllDiv::DIV2),
@@ -25,13 +25,14 @@ async fn main(_spawner: Spawner) {
25 divr: None, 25 divr: None,
26 }); 26 });
27 config.rcc.pll2 = Some(Pll { 27 config.rcc.pll2 = Some(Pll {
28 source: PllSource::HSI,
28 prediv: PllPreDiv::DIV4, 29 prediv: PllPreDiv::DIV4,
29 mul: PllMul::MUL50, 30 mul: PllMul::MUL50,
30 divp: Some(PllDiv::DIV8), // 100mhz 31 divp: Some(PllDiv::DIV8), // 100mhz
31 divq: None, 32 divq: None,
32 divr: None, 33 divr: None,
33 }); 34 });
34 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 35 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
35 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 36 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
36 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 37 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
37 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 38 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs
index 8195430b2..23ece1c38 100644
--- a/examples/stm32h7/src/bin/camera.rs
+++ b/examples/stm32h7/src/bin/camera.rs
@@ -28,17 +28,17 @@ async fn main(_spawner: Spawner) {
28 let mut config = Config::default(); 28 let mut config = Config::default();
29 { 29 {
30 use embassy_stm32::rcc::*; 30 use embassy_stm32::rcc::*;
31 config.rcc.hsi = Some(Hsi::Mhz64); 31 config.rcc.hsi = Some(HSIPrescaler::DIV1);
32 config.rcc.csi = true; 32 config.rcc.csi = true;
33 config.rcc.pll_src = PllSource::Hsi;
34 config.rcc.pll1 = Some(Pll { 33 config.rcc.pll1 = Some(Pll {
34 source: PllSource::HSI,
35 prediv: PllPreDiv::DIV4, 35 prediv: PllPreDiv::DIV4,
36 mul: PllMul::MUL50, 36 mul: PllMul::MUL50,
37 divp: Some(PllDiv::DIV2), 37 divp: Some(PllDiv::DIV2),
38 divq: Some(PllDiv::DIV8), // 100mhz 38 divq: Some(PllDiv::DIV8), // 100mhz
39 divr: None, 39 divr: None,
40 }); 40 });
41 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 41 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
42 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 42 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
43 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 43 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
44 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 44 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/dac.rs b/examples/stm32h7/src/bin/dac.rs
index 821221897..35fd6550f 100644
--- a/examples/stm32h7/src/bin/dac.rs
+++ b/examples/stm32h7/src/bin/dac.rs
@@ -16,10 +16,10 @@ fn main() -> ! {
16 let mut config = Config::default(); 16 let mut config = Config::default();
17 { 17 {
18 use embassy_stm32::rcc::*; 18 use embassy_stm32::rcc::*;
19 config.rcc.hsi = Some(Hsi::Mhz64); 19 config.rcc.hsi = Some(HSIPrescaler::DIV1);
20 config.rcc.csi = true; 20 config.rcc.csi = true;
21 config.rcc.pll_src = PllSource::Hsi;
22 config.rcc.pll1 = Some(Pll { 21 config.rcc.pll1 = Some(Pll {
22 source: PllSource::HSI,
23 prediv: PllPreDiv::DIV4, 23 prediv: PllPreDiv::DIV4,
24 mul: PllMul::MUL50, 24 mul: PllMul::MUL50,
25 divp: Some(PllDiv::DIV2), 25 divp: Some(PllDiv::DIV2),
@@ -27,13 +27,14 @@ fn main() -> ! {
27 divr: None, 27 divr: None,
28 }); 28 });
29 config.rcc.pll2 = Some(Pll { 29 config.rcc.pll2 = Some(Pll {
30 source: PllSource::HSI,
30 prediv: PllPreDiv::DIV4, 31 prediv: PllPreDiv::DIV4,
31 mul: PllMul::MUL50, 32 mul: PllMul::MUL50,
32 divp: Some(PllDiv::DIV8), // 100mhz 33 divp: Some(PllDiv::DIV8), // 100mhz
33 divq: None, 34 divq: None,
34 divr: None, 35 divr: None,
35 }); 36 });
36 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 37 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
37 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 38 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
38 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 39 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
39 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 40 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs
index 334986a05..e141fc484 100644
--- a/examples/stm32h7/src/bin/dac_dma.rs
+++ b/examples/stm32h7/src/bin/dac_dma.rs
@@ -24,10 +24,10 @@ async fn main(spawner: Spawner) {
24 let mut config = embassy_stm32::Config::default(); 24 let mut config = embassy_stm32::Config::default();
25 { 25 {
26 use embassy_stm32::rcc::*; 26 use embassy_stm32::rcc::*;
27 config.rcc.hsi = Some(Hsi::Mhz64); 27 config.rcc.hsi = Some(HSIPrescaler::DIV1);
28 config.rcc.csi = true; 28 config.rcc.csi = true;
29 config.rcc.pll_src = PllSource::Hsi;
30 config.rcc.pll1 = Some(Pll { 29 config.rcc.pll1 = Some(Pll {
30 source: PllSource::HSI,
31 prediv: PllPreDiv::DIV4, 31 prediv: PllPreDiv::DIV4,
32 mul: PllMul::MUL50, 32 mul: PllMul::MUL50,
33 divp: Some(PllDiv::DIV2), 33 divp: Some(PllDiv::DIV2),
@@ -35,13 +35,14 @@ async fn main(spawner: Spawner) {
35 divr: None, 35 divr: None,
36 }); 36 });
37 config.rcc.pll2 = Some(Pll { 37 config.rcc.pll2 = Some(Pll {
38 source: PllSource::HSI,
38 prediv: PllPreDiv::DIV4, 39 prediv: PllPreDiv::DIV4,
39 mul: PllMul::MUL50, 40 mul: PllMul::MUL50,
40 divp: Some(PllDiv::DIV8), // 100mhz 41 divp: Some(PllDiv::DIV8), // 100mhz
41 divq: None, 42 divq: None,
42 divr: None, 43 divr: None,
43 }); 44 });
44 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 45 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
45 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 46 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
46 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 47 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
47 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 48 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs
index 81d9c7347..e37d8797b 100644
--- a/examples/stm32h7/src/bin/eth.rs
+++ b/examples/stm32h7/src/bin/eth.rs
@@ -34,18 +34,18 @@ async fn main(spawner: Spawner) -> ! {
34 let mut config = Config::default(); 34 let mut config = Config::default();
35 { 35 {
36 use embassy_stm32::rcc::*; 36 use embassy_stm32::rcc::*;
37 config.rcc.hsi = Some(Hsi::Mhz64); 37 config.rcc.hsi = Some(HSIPrescaler::DIV1);
38 config.rcc.csi = true; 38 config.rcc.csi = true;
39 config.rcc.hsi48 = true; // needed for RNG 39 config.rcc.hsi48 = true; // needed for RNG
40 config.rcc.pll_src = PllSource::Hsi;
41 config.rcc.pll1 = Some(Pll { 40 config.rcc.pll1 = Some(Pll {
41 source: PllSource::HSI,
42 prediv: PllPreDiv::DIV4, 42 prediv: PllPreDiv::DIV4,
43 mul: PllMul::MUL50, 43 mul: PllMul::MUL50,
44 divp: Some(PllDiv::DIV2), 44 divp: Some(PllDiv::DIV2),
45 divq: None, 45 divq: None,
46 divr: None, 46 divr: None,
47 }); 47 });
48 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 48 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
49 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 49 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
50 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 50 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
51 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 51 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs
index 338137069..88df53f01 100644
--- a/examples/stm32h7/src/bin/eth_client.rs
+++ b/examples/stm32h7/src/bin/eth_client.rs
@@ -35,18 +35,18 @@ async fn main(spawner: Spawner) -> ! {
35 let mut config = Config::default(); 35 let mut config = Config::default();
36 { 36 {
37 use embassy_stm32::rcc::*; 37 use embassy_stm32::rcc::*;
38 config.rcc.hsi = Some(Hsi::Mhz64); 38 config.rcc.hsi = Some(HSIPrescaler::DIV1);
39 config.rcc.csi = true; 39 config.rcc.csi = true;
40 config.rcc.hsi48 = true; // needed for RNG 40 config.rcc.hsi48 = true; // needed for RNG
41 config.rcc.pll_src = PllSource::Hsi;
42 config.rcc.pll1 = Some(Pll { 41 config.rcc.pll1 = Some(Pll {
42 source: PllSource::HSI,
43 prediv: PllPreDiv::DIV4, 43 prediv: PllPreDiv::DIV4,
44 mul: PllMul::MUL50, 44 mul: PllMul::MUL50,
45 divp: Some(PllDiv::DIV2), 45 divp: Some(PllDiv::DIV2),
46 divq: None, 46 divq: None,
47 divr: None, 47 divr: None,
48 }); 48 });
49 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 49 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
50 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 50 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
51 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 51 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
52 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 52 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs
index cffd47093..54e2c3629 100644
--- a/examples/stm32h7/src/bin/fmc.rs
+++ b/examples/stm32h7/src/bin/fmc.rs
@@ -14,17 +14,17 @@ async fn main(_spawner: Spawner) {
14 let mut config = Config::default(); 14 let mut config = Config::default();
15 { 15 {
16 use embassy_stm32::rcc::*; 16 use embassy_stm32::rcc::*;
17 config.rcc.hsi = Some(Hsi::Mhz64); 17 config.rcc.hsi = Some(HSIPrescaler::DIV1);
18 config.rcc.csi = true; 18 config.rcc.csi = true;
19 config.rcc.pll_src = PllSource::Hsi;
20 config.rcc.pll1 = Some(Pll { 19 config.rcc.pll1 = Some(Pll {
20 source: PllSource::HSI,
21 prediv: PllPreDiv::DIV4, 21 prediv: PllPreDiv::DIV4,
22 mul: PllMul::MUL50, 22 mul: PllMul::MUL50,
23 divp: Some(PllDiv::DIV2), 23 divp: Some(PllDiv::DIV2),
24 divq: Some(PllDiv::DIV8), // 100mhz 24 divq: Some(PllDiv::DIV8), // 100mhz
25 divr: None, 25 divr: None,
26 }); 26 });
27 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 27 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
28 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 28 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
29 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 29 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
30 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 30 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
index 0355ac073..e4bac8a5a 100644
--- a/examples/stm32h7/src/bin/low_level_timer_api.rs
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -17,18 +17,18 @@ async fn main(_spawner: Spawner) {
17 let mut config = Config::default(); 17 let mut config = Config::default();
18 { 18 {
19 use embassy_stm32::rcc::*; 19 use embassy_stm32::rcc::*;
20 config.rcc.hsi = Some(Hsi::Mhz64); 20 config.rcc.hsi = Some(HSIPrescaler::DIV1);
21 config.rcc.csi = true; 21 config.rcc.csi = true;
22 config.rcc.hsi48 = true; // needed for RNG 22 config.rcc.hsi48 = true; // needed for RNG
23 config.rcc.pll_src = PllSource::Hsi;
24 config.rcc.pll1 = Some(Pll { 23 config.rcc.pll1 = Some(Pll {
24 source: PllSource::HSI,
25 prediv: PllPreDiv::DIV4, 25 prediv: PllPreDiv::DIV4,
26 mul: PllMul::MUL50, 26 mul: PllMul::MUL50,
27 divp: Some(PllDiv::DIV2), 27 divp: Some(PllDiv::DIV2),
28 divq: Some(PllDiv::DIV8), // 100mhz 28 divq: Some(PllDiv::DIV8), // 100mhz
29 divr: None, 29 divr: None,
30 }); 30 });
31 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 31 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
32 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 32 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
33 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 33 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
34 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 34 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs
index 973a10cdd..c55d780a0 100644
--- a/examples/stm32h7/src/bin/pwm.rs
+++ b/examples/stm32h7/src/bin/pwm.rs
@@ -17,17 +17,17 @@ async fn main(_spawner: Spawner) {
17 let mut config = Config::default(); 17 let mut config = Config::default();
18 { 18 {
19 use embassy_stm32::rcc::*; 19 use embassy_stm32::rcc::*;
20 config.rcc.hsi = Some(Hsi::Mhz64); 20 config.rcc.hsi = Some(HSIPrescaler::DIV1);
21 config.rcc.csi = true; 21 config.rcc.csi = true;
22 config.rcc.pll_src = PllSource::Hsi;
23 config.rcc.pll1 = Some(Pll { 22 config.rcc.pll1 = Some(Pll {
23 source: PllSource::HSI,
24 prediv: PllPreDiv::DIV4, 24 prediv: PllPreDiv::DIV4,
25 mul: PllMul::MUL50, 25 mul: PllMul::MUL50,
26 divp: Some(PllDiv::DIV2), 26 divp: Some(PllDiv::DIV2),
27 divq: None, 27 divq: None,
28 divr: None, 28 divr: None,
29 }); 29 });
30 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 30 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
31 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 31 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
32 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 32 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
33 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 33 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs
index ecb8d6542..be968ff77 100644
--- a/examples/stm32h7/src/bin/sdmmc.rs
+++ b/examples/stm32h7/src/bin/sdmmc.rs
@@ -18,17 +18,17 @@ async fn main(_spawner: Spawner) -> ! {
18 let mut config = Config::default(); 18 let mut config = Config::default();
19 { 19 {
20 use embassy_stm32::rcc::*; 20 use embassy_stm32::rcc::*;
21 config.rcc.hsi = Some(Hsi::Mhz64); 21 config.rcc.hsi = Some(HSIPrescaler::DIV1);
22 config.rcc.csi = true; 22 config.rcc.csi = true;
23 config.rcc.pll_src = PllSource::Hsi;
24 config.rcc.pll1 = Some(Pll { 23 config.rcc.pll1 = Some(Pll {
24 source: PllSource::HSI,
25 prediv: PllPreDiv::DIV4, 25 prediv: PllPreDiv::DIV4,
26 mul: PllMul::MUL50, 26 mul: PllMul::MUL50,
27 divp: Some(PllDiv::DIV2), 27 divp: Some(PllDiv::DIV2),
28 divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz 28 divq: Some(PllDiv::DIV4), // default clock chosen by SDMMCSEL. 200 Mhz
29 divr: None, 29 divr: None,
30 }); 30 });
31 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 31 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
32 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 32 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
33 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 33 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
34 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 34 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs
index f128d4a56..a8db0ff77 100644
--- a/examples/stm32h7/src/bin/spi.rs
+++ b/examples/stm32h7/src/bin/spi.rs
@@ -40,17 +40,17 @@ fn main() -> ! {
40 let mut config = Config::default(); 40 let mut config = Config::default();
41 { 41 {
42 use embassy_stm32::rcc::*; 42 use embassy_stm32::rcc::*;
43 config.rcc.hsi = Some(Hsi::Mhz64); 43 config.rcc.hsi = Some(HSIPrescaler::DIV1);
44 config.rcc.csi = true; 44 config.rcc.csi = true;
45 config.rcc.pll_src = PllSource::Hsi;
46 config.rcc.pll1 = Some(Pll { 45 config.rcc.pll1 = Some(Pll {
46 source: PllSource::HSI,
47 prediv: PllPreDiv::DIV4, 47 prediv: PllPreDiv::DIV4,
48 mul: PllMul::MUL50, 48 mul: PllMul::MUL50,
49 divp: Some(PllDiv::DIV2), 49 divp: Some(PllDiv::DIV2),
50 divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. 50 divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
51 divr: None, 51 divr: None,
52 }); 52 });
53 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 53 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
54 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 54 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
55 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 55 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
56 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 56 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs
index d4c0bcdbd..561052e48 100644
--- a/examples/stm32h7/src/bin/spi_dma.rs
+++ b/examples/stm32h7/src/bin/spi_dma.rs
@@ -36,17 +36,17 @@ fn main() -> ! {
36 let mut config = Config::default(); 36 let mut config = Config::default();
37 { 37 {
38 use embassy_stm32::rcc::*; 38 use embassy_stm32::rcc::*;
39 config.rcc.hsi = Some(Hsi::Mhz64); 39 config.rcc.hsi = Some(HSIPrescaler::DIV1);
40 config.rcc.csi = true; 40 config.rcc.csi = true;
41 config.rcc.pll_src = PllSource::Hsi;
42 config.rcc.pll1 = Some(Pll { 41 config.rcc.pll1 = Some(Pll {
42 source: PllSource::HSI,
43 prediv: PllPreDiv::DIV4, 43 prediv: PllPreDiv::DIV4,
44 mul: PllMul::MUL50, 44 mul: PllMul::MUL50,
45 divp: Some(PllDiv::DIV2), 45 divp: Some(PllDiv::DIV2),
46 divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz. 46 divq: Some(PllDiv::DIV8), // used by SPI3. 100Mhz.
47 divr: None, 47 divr: None,
48 }); 48 });
49 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 49 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
50 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 50 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
51 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 51 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
52 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 52 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs
index c1e5144be..19d77183b 100644
--- a/examples/stm32h7/src/bin/usb_serial.rs
+++ b/examples/stm32h7/src/bin/usb_serial.rs
@@ -23,18 +23,18 @@ async fn main(_spawner: Spawner) {
23 let mut config = Config::default(); 23 let mut config = Config::default();
24 { 24 {
25 use embassy_stm32::rcc::*; 25 use embassy_stm32::rcc::*;
26 config.rcc.hsi = Some(Hsi::Mhz64); 26 config.rcc.hsi = Some(HSIPrescaler::DIV1);
27 config.rcc.csi = true; 27 config.rcc.csi = true;
28 config.rcc.hsi48 = true; // needed for USB 28 config.rcc.hsi48 = true; // needed for USB
29 config.rcc.pll_src = PllSource::Hsi;
30 config.rcc.pll1 = Some(Pll { 29 config.rcc.pll1 = Some(Pll {
30 source: PllSource::HSI,
31 prediv: PllPreDiv::DIV4, 31 prediv: PllPreDiv::DIV4,
32 mul: PllMul::MUL50, 32 mul: PllMul::MUL50,
33 divp: Some(PllDiv::DIV2), 33 divp: Some(PllDiv::DIV2),
34 divq: None, 34 divq: None,
35 divr: None, 35 divr: None,
36 }); 36 });
37 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 37 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
38 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 38 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
39 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 39 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
40 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 40 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs
index e26c274ad..35a6a8425 100644
--- a/examples/stm32wl/src/bin/lora_lorawan.rs
+++ b/examples/stm32wl/src/bin/lora_lorawan.rs
@@ -39,6 +39,7 @@ async fn main(_spawner: Spawner) {
39 config.rcc.hse = Some(Hse { 39 config.rcc.hse = Some(Hse {
40 freq: Hertz(32_000_000), 40 freq: Hertz(32_000_000),
41 mode: HseMode::Bypass, 41 mode: HseMode::Bypass,
42 prescaler: HsePrescaler::DIV1,
42 }); 43 });
43 config.rcc.mux = ClockSrc::PLL1_R; 44 config.rcc.mux = ClockSrc::PLL1_R;
44 config.rcc.pll = Some(Pll { 45 config.rcc.pll = Some(Pll {
diff --git a/examples/stm32wl/src/bin/lora_p2p_receive.rs b/examples/stm32wl/src/bin/lora_p2p_receive.rs
index be33f39c1..1c485d739 100644
--- a/examples/stm32wl/src/bin/lora_p2p_receive.rs
+++ b/examples/stm32wl/src/bin/lora_p2p_receive.rs
@@ -11,6 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
11use embassy_stm32::bind_interrupts; 11use embassy_stm32::bind_interrupts;
12use embassy_stm32::gpio::{Level, Output, Pin, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pin, Speed};
13use embassy_stm32::spi::Spi; 13use embassy_stm32::spi::Spi;
14use embassy_stm32::time::Hertz;
14use embassy_time::{Delay, Timer}; 15use embassy_time::{Delay, Timer};
15use lora_phy::mod_params::*; 16use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 17use lora_phy::sx1261_2::SX1261_2;
@@ -26,7 +27,23 @@ bind_interrupts!(struct Irqs{
26#[embassy_executor::main] 27#[embassy_executor::main]
27async fn main(_spawner: Spawner) { 28async fn main(_spawner: Spawner) {
28 let mut config = embassy_stm32::Config::default(); 29 let mut config = embassy_stm32::Config::default();
29 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; 30 {
31 use embassy_stm32::rcc::*;
32 config.rcc.hse = Some(Hse {
33 freq: Hertz(32_000_000),
34 mode: HseMode::Bypass,
35 prescaler: HsePrescaler::DIV1,
36 });
37 config.rcc.mux = ClockSrc::PLL1_R;
38 config.rcc.pll = Some(Pll {
39 source: PLLSource::HSE,
40 prediv: PllPreDiv::DIV2,
41 mul: PllMul::MUL6,
42 divp: None,
43 divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
44 divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
45 });
46 }
30 let p = embassy_stm32::init(config); 47 let p = embassy_stm32::init(config);
31 48
32 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 49 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
diff --git a/examples/stm32wl/src/bin/lora_p2p_send.rs b/examples/stm32wl/src/bin/lora_p2p_send.rs
index 85f6a84b7..3afa78acb 100644
--- a/examples/stm32wl/src/bin/lora_p2p_send.rs
+++ b/examples/stm32wl/src/bin/lora_p2p_send.rs
@@ -11,6 +11,7 @@ use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant};
11use embassy_stm32::bind_interrupts; 11use embassy_stm32::bind_interrupts;
12use embassy_stm32::gpio::{Level, Output, Pin, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pin, Speed};
13use embassy_stm32::spi::Spi; 13use embassy_stm32::spi::Spi;
14use embassy_stm32::time::Hertz;
14use embassy_time::Delay; 15use embassy_time::Delay;
15use lora_phy::mod_params::*; 16use lora_phy::mod_params::*;
16use lora_phy::sx1261_2::SX1261_2; 17use lora_phy::sx1261_2::SX1261_2;
@@ -26,7 +27,23 @@ bind_interrupts!(struct Irqs{
26#[embassy_executor::main] 27#[embassy_executor::main]
27async fn main(_spawner: Spawner) { 28async fn main(_spawner: Spawner) {
28 let mut config = embassy_stm32::Config::default(); 29 let mut config = embassy_stm32::Config::default();
29 config.rcc.mux = embassy_stm32::rcc::ClockSrc::HSE; 30 {
31 use embassy_stm32::rcc::*;
32 config.rcc.hse = Some(Hse {
33 freq: Hertz(32_000_000),
34 mode: HseMode::Bypass,
35 prescaler: HsePrescaler::DIV1,
36 });
37 config.rcc.mux = ClockSrc::PLL1_R;
38 config.rcc.pll = Some(Pll {
39 source: PLLSource::HSE,
40 prediv: PllPreDiv::DIV2,
41 mul: PllMul::MUL6,
42 divp: None,
43 divq: Some(PllQDiv::DIV2), // PLL1_Q clock (32 / 2 * 6 / 2), used for RNG
44 divr: Some(PllRDiv::DIV2), // sysclk 48Mhz clock (32 / 2 * 6 / 2)
45 });
46 }
30 let p = embassy_stm32::init(config); 47 let p = embassy_stm32::init(config);
31 48
32 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2); 49 let spi = Spi::new_subghz(p.SUBGHZSPI, p.DMA1_CH1, p.DMA1_CH2);
diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs
index 2cf7ef9d0..1a8822b42 100644
--- a/examples/stm32wl/src/bin/random.rs
+++ b/examples/stm32wl/src/bin/random.rs
@@ -21,6 +21,7 @@ async fn main(_spawner: Spawner) {
21 config.rcc.hse = Some(Hse { 21 config.rcc.hse = Some(Hse {
22 freq: Hertz(32_000_000), 22 freq: Hertz(32_000_000),
23 mode: HseMode::Bypass, 23 mode: HseMode::Bypass,
24 prescaler: HsePrescaler::DIV1,
24 }); 25 });
25 config.rcc.mux = ClockSrc::PLL1_R; 26 config.rcc.mux = ClockSrc::PLL1_R;
26 config.rcc.pll = Some(Pll { 27 config.rcc.pll = Some(Pll {
diff --git a/examples/stm32wl/src/bin/rtc.rs b/examples/stm32wl/src/bin/rtc.rs
index 9ebb05f22..b3b7f9c5c 100644
--- a/examples/stm32wl/src/bin/rtc.rs
+++ b/examples/stm32wl/src/bin/rtc.rs
@@ -5,20 +5,34 @@
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};
9use embassy_stm32::rtc::{Rtc, RtcConfig}; 8use embassy_stm32::rtc::{Rtc, RtcConfig};
9use embassy_stm32::time::Hertz;
10use embassy_stm32::Config; 10use embassy_stm32::Config;
11use embassy_time::Timer; 11use embassy_time::Timer;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14#[embassy_executor::main] 14#[embassy_executor::main]
15async fn main(_spawner: Spawner) { 15async fn main(_spawner: Spawner) {
16 let p = { 16 let mut config = Config::default();
17 let mut config = Config::default(); 17 {
18 config.rcc.mux = ClockSrc::HSE; 18 use embassy_stm32::rcc::*;
19 config.rcc.ls = LsConfig::default_lse(); 19 config.rcc.ls = LsConfig::default_lse();
20 embassy_stm32::init(config) 20 config.rcc.hse = Some(Hse {
21 }; 21 freq: Hertz(32_000_000),
22 mode: HseMode::Bypass,
23 prescaler: HsePrescaler::DIV1,
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 }
35 let p = embassy_stm32::init(config);
22 info!("Hello World!"); 36 info!("Hello World!");
23 37
24 let now = NaiveDate::from_ymd_opt(2020, 5, 15) 38 let now = NaiveDate::from_ymd_opt(2020, 5, 15)
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index cb1738154..ff808281a 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -227,6 +227,11 @@ pub fn config() -> Config {
227 #[allow(unused_mut)] 227 #[allow(unused_mut)]
228 let mut config = Config::default(); 228 let mut config = Config::default();
229 229
230 #[cfg(feature = "stm32wb55rg")]
231 {
232 config.rcc = embassy_stm32::rcc::WPAN_DEFAULT;
233 }
234
230 #[cfg(feature = "stm32f207zg")] 235 #[cfg(feature = "stm32f207zg")]
231 { 236 {
232 use embassy_stm32::rcc::*; 237 use embassy_stm32::rcc::*;
@@ -307,7 +312,7 @@ pub fn config() -> Config {
307 mode: HseMode::BypassDigital, 312 mode: HseMode::BypassDigital,
308 }); 313 });
309 config.rcc.pll1 = Some(Pll { 314 config.rcc.pll1 = Some(Pll {
310 source: PllSource::Hse, 315 source: PllSource::HSE,
311 prediv: PllPreDiv::DIV2, 316 prediv: PllPreDiv::DIV2,
312 mul: PllMul::MUL125, 317 mul: PllMul::MUL125,
313 divp: Some(PllDiv::DIV2), 318 divp: Some(PllDiv::DIV2),
@@ -318,18 +323,18 @@ pub fn config() -> Config {
318 config.rcc.apb1_pre = APBPrescaler::DIV1; 323 config.rcc.apb1_pre = APBPrescaler::DIV1;
319 config.rcc.apb2_pre = APBPrescaler::DIV1; 324 config.rcc.apb2_pre = APBPrescaler::DIV1;
320 config.rcc.apb3_pre = APBPrescaler::DIV1; 325 config.rcc.apb3_pre = APBPrescaler::DIV1;
321 config.rcc.sys = Sysclk::Pll1P; 326 config.rcc.sys = Sysclk::PLL1_P;
322 config.rcc.voltage_scale = VoltageScale::Scale0; 327 config.rcc.voltage_scale = VoltageScale::Scale0;
323 } 328 }
324 329
325 #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))] 330 #[cfg(any(feature = "stm32h755zi", feature = "stm32h753zi"))]
326 { 331 {
327 use embassy_stm32::rcc::*; 332 use embassy_stm32::rcc::*;
328 config.rcc.hsi = Some(Hsi::Mhz64); 333 config.rcc.hsi = Some(HSIPrescaler::DIV1);
329 config.rcc.csi = true; 334 config.rcc.csi = true;
330 config.rcc.hsi48 = true; // needed for RNG 335 config.rcc.hsi48 = true; // needed for RNG
331 config.rcc.pll_src = PllSource::Hsi;
332 config.rcc.pll1 = Some(Pll { 336 config.rcc.pll1 = Some(Pll {
337 source: PllSource::HSI,
333 prediv: PllPreDiv::DIV4, 338 prediv: PllPreDiv::DIV4,
334 mul: PllMul::MUL50, 339 mul: PllMul::MUL50,
335 divp: Some(PllDiv::DIV2), 340 divp: Some(PllDiv::DIV2),
@@ -337,13 +342,14 @@ pub fn config() -> Config {
337 divr: None, 342 divr: None,
338 }); 343 });
339 config.rcc.pll2 = Some(Pll { 344 config.rcc.pll2 = Some(Pll {
345 source: PllSource::HSI,
340 prediv: PllPreDiv::DIV4, 346 prediv: PllPreDiv::DIV4,
341 mul: PllMul::MUL50, 347 mul: PllMul::MUL50,
342 divp: Some(PllDiv::DIV8), // 100mhz 348 divp: Some(PllDiv::DIV8), // 100mhz
343 divq: None, 349 divq: None,
344 divr: None, 350 divr: None,
345 }); 351 });
346 config.rcc.sys = Sysclk::Pll1P; // 400 Mhz 352 config.rcc.sys = Sysclk::PLL1_P; // 400 Mhz
347 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz 353 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 200 Mhz
348 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz 354 config.rcc.apb1_pre = APBPrescaler::DIV2; // 100 Mhz
349 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz 355 config.rcc.apb2_pre = APBPrescaler::DIV2; // 100 Mhz
@@ -356,11 +362,11 @@ pub fn config() -> Config {
356 #[cfg(any(feature = "stm32h7a3zi"))] 362 #[cfg(any(feature = "stm32h7a3zi"))]
357 { 363 {
358 use embassy_stm32::rcc::*; 364 use embassy_stm32::rcc::*;
359 config.rcc.hsi = Some(Hsi::Mhz64); 365 config.rcc.hsi = Some(HSIPrescaler::DIV1);
360 config.rcc.csi = true; 366 config.rcc.csi = true;
361 config.rcc.hsi48 = true; // needed for RNG 367 config.rcc.hsi48 = true; // needed for RNG
362 config.rcc.pll_src = PllSource::Hsi;
363 config.rcc.pll1 = Some(Pll { 368 config.rcc.pll1 = Some(Pll {
369 source: PllSource::HSI,
364 prediv: PllPreDiv::DIV4, 370 prediv: PllPreDiv::DIV4,
365 mul: PllMul::MUL35, 371 mul: PllMul::MUL35,
366 divp: Some(PllDiv::DIV2), // 280 Mhz 372 divp: Some(PllDiv::DIV2), // 280 Mhz
@@ -368,13 +374,14 @@ pub fn config() -> Config {
368 divr: None, 374 divr: None,
369 }); 375 });
370 config.rcc.pll2 = Some(Pll { 376 config.rcc.pll2 = Some(Pll {
377 source: PllSource::HSI,
371 prediv: PllPreDiv::DIV4, 378 prediv: PllPreDiv::DIV4,
372 mul: PllMul::MUL35, 379 mul: PllMul::MUL35,
373 divp: Some(PllDiv::DIV8), // 70 Mhz 380 divp: Some(PllDiv::DIV8), // 70 Mhz
374 divq: None, 381 divq: None,
375 divr: None, 382 divr: None,
376 }); 383 });
377 config.rcc.sys = Sysclk::Pll1P; // 280 Mhz 384 config.rcc.sys = Sysclk::PLL1_P; // 280 Mhz
378 config.rcc.ahb_pre = AHBPrescaler::DIV1; // 280 Mhz 385 config.rcc.ahb_pre = AHBPrescaler::DIV1; // 280 Mhz
379 config.rcc.apb1_pre = APBPrescaler::DIV2; // 140 Mhz 386 config.rcc.apb1_pre = APBPrescaler::DIV2; // 140 Mhz
380 config.rcc.apb2_pre = APBPrescaler::DIV2; // 140 Mhz 387 config.rcc.apb2_pre = APBPrescaler::DIV2; // 140 Mhz
@@ -405,6 +412,7 @@ pub fn config() -> Config {
405 config.rcc.hse = Some(Hse { 412 config.rcc.hse = Some(Hse {
406 freq: Hertz(32_000_000), 413 freq: Hertz(32_000_000),
407 mode: HseMode::Bypass, 414 mode: HseMode::Bypass,
415 prescaler: HsePrescaler::DIV1,
408 }); 416 });
409 config.rcc.mux = ClockSrc::PLL1_R; 417 config.rcc.mux = ClockSrc::PLL1_R;
410 config.rcc.pll = Some(Pll { 418 config.rcc.pll = Some(Pll {