aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorTyler <[email protected]>2023-09-29 20:02:24 -0600
committerGitHub <[email protected]>2023-09-29 20:02:24 -0600
commit2f9b59c5cf21f1e2761a9ccefdfd86f0edea829c (patch)
tree8964744b4fb753cf98f6f413464106c4d2a72976 /embassy-stm32
parentce91fb2bfc846570ef543a09396c428d70675245 (diff)
parent95b3d9eb3b3657de3d7bc9c04f8fb83eae901640 (diff)
Merge branch 'main' into issue-1974-add-sai-driver
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/Cargo.toml19
-rw-r--r--embassy-stm32/build.rs96
-rw-r--r--embassy-stm32/src/adc/f1.rs53
-rw-r--r--embassy-stm32/src/adc/f3.rs195
-rw-r--r--embassy-stm32/src/adc/mod.rs113
-rw-r--r--embassy-stm32/src/adc/resolution.rs8
-rw-r--r--embassy-stm32/src/adc/sample_time.rs18
-rw-r--r--embassy-stm32/src/adc/v1.rs150
-rw-r--r--embassy-stm32/src/adc/v2.rs44
-rw-r--r--embassy-stm32/src/adc/v3.rs41
-rw-r--r--embassy-stm32/src/adc/v4.rs189
-rw-r--r--embassy-stm32/src/eth/v1/mod.rs1
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs9
-rw-r--r--embassy-stm32/src/exti.rs14
-rw-r--r--embassy-stm32/src/fmt.rs45
-rw-r--r--embassy-stm32/src/gpio.rs3
-rw-r--r--embassy-stm32/src/hrtim/mod.rs36
-rw-r--r--embassy-stm32/src/hrtim/traits.rs175
-rw-r--r--embassy-stm32/src/i2c/v1.rs6
-rw-r--r--embassy-stm32/src/i2c/v2.rs6
-rw-r--r--embassy-stm32/src/lib.rs16
-rw-r--r--embassy-stm32/src/low_power.rs92
-rw-r--r--embassy-stm32/src/rcc/bd.rs176
-rw-r--r--embassy-stm32/src/rcc/bus.rs56
-rw-r--r--embassy-stm32/src/rcc/c0.rs27
-rw-r--r--embassy-stm32/src/rcc/common.rs174
-rw-r--r--embassy-stm32/src/rcc/f1.rs6
-rw-r--r--embassy-stm32/src/rcc/f2.rs51
-rw-r--r--embassy-stm32/src/rcc/f3.rs164
-rw-r--r--embassy-stm32/src/rcc/f4.rs25
-rw-r--r--embassy-stm32/src/rcc/f7.rs26
-rw-r--r--embassy-stm32/src/rcc/g0.rs8
-rw-r--r--embassy-stm32/src/rcc/g4.rs144
-rw-r--r--embassy-stm32/src/rcc/h.rs772
-rw-r--r--embassy-stm32/src/rcc/h5.rs511
-rw-r--r--embassy-stm32/src/rcc/h7.rs879
-rw-r--r--embassy-stm32/src/rcc/l0.rs61
-rw-r--r--embassy-stm32/src/rcc/l1.rs14
-rw-r--r--embassy-stm32/src/rcc/l4.rs67
-rw-r--r--embassy-stm32/src/rcc/l5.rs19
-rw-r--r--embassy-stm32/src/rcc/mco.rs71
-rw-r--r--embassy-stm32/src/rcc/mod.rs53
-rw-r--r--embassy-stm32/src/rcc/u5.rs80
-rw-r--r--embassy-stm32/src/rcc/wb.rs71
-rw-r--r--embassy-stm32/src/rcc/wba.rs154
-rw-r--r--embassy-stm32/src/rcc/wl.rs138
-rw-r--r--embassy-stm32/src/rng.rs46
-rw-r--r--embassy-stm32/src/rtc/datetime.rs2
-rw-r--r--embassy-stm32/src/rtc/mod.rs215
-rw-r--r--embassy-stm32/src/rtc/v2.rs281
-rw-r--r--embassy-stm32/src/rtc/v3.rs71
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs56
-rw-r--r--embassy-stm32/src/spi/mod.rs6
-rw-r--r--embassy-stm32/src/time_driver.rs134
-rw-r--r--embassy-stm32/src/timer/mod.rs262
-rw-r--r--embassy-stm32/src/timer/qei.rs96
-rw-r--r--embassy-stm32/src/usart/buffered.rs64
-rw-r--r--embassy-stm32/src/usart/mod.rs215
-rw-r--r--embassy-stm32/src/usart/ringbuffered.rs33
-rw-r--r--embassy-stm32/src/usb/usb.rs5
-rw-r--r--embassy-stm32/src/usb_otg/usb.rs12
61 files changed, 3658 insertions, 2916 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 612a54f25..b3b3cd81c 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -8,31 +8,32 @@ license = "MIT OR Apache-2.0"
8src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/" 8src_base = "https://github.com/embassy-rs/embassy/blob/embassy-stm32-v$VERSION/embassy-stm32/src/"
9src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/" 9src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-stm32/src/"
10 10
11features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time", "low-power"] 11features = ["nightly", "defmt", "unstable-pac", "unstable-traits", "exti", "time-driver-any", "time"]
12flavors = [ 12flavors = [
13 { regex_feature = "stm32f0.*", target = "thumbv6m-none-eabi" }, 13 { regex_feature = "stm32f0.*", target = "thumbv6m-none-eabi" },
14 { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" }, 14 { regex_feature = "stm32f1.*", target = "thumbv7m-none-eabi" },
15 { regex_feature = "stm32f2.*", target = "thumbv7m-none-eabi" }, 15 { regex_feature = "stm32f2.*", target = "thumbv7m-none-eabi" },
16 { regex_feature = "stm32f3.*", target = "thumbv7em-none-eabi" }, 16 { regex_feature = "stm32f3.*", target = "thumbv7em-none-eabi" },
17 { regex_feature = "stm32f4.*", target = "thumbv7em-none-eabi" }, 17 { regex_feature = "stm32f4.*", target = "thumbv7em-none-eabi", features = ["low-power"] },
18 { regex_feature = "stm32f7.*", target = "thumbv7em-none-eabi" }, 18 { regex_feature = "stm32f7.*", target = "thumbv7em-none-eabi" },
19 { regex_feature = "stm32c0.*", target = "thumbv6m-none-eabi" }, 19 { regex_feature = "stm32c0.*", target = "thumbv6m-none-eabi" },
20 { regex_feature = "stm32g0.*", target = "thumbv6m-none-eabi" }, 20 { regex_feature = "stm32g0.*", target = "thumbv6m-none-eabi" },
21 { regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi" }, 21 { regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi" },
22 { regex_feature = "stm32h5.*", target = "thumbv8m.main-none-eabihf" }, 22 { regex_feature = "stm32h5.*", target = "thumbv8m.main-none-eabihf" },
23 { regex_feature = "stm32h7.*", target = "thumbv7em-none-eabi" }, 23 { regex_feature = "stm32h7.*", target = "thumbv7em-none-eabi" },
24 { regex_feature = "stm32l0.*", target = "thumbv6m-none-eabi" }, 24 { regex_feature = "stm32l0.*", target = "thumbv6m-none-eabi", features = ["low-power"] },
25 { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" }, 25 { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" },
26 { regex_feature = "stm32l4.*", target = "thumbv7em-none-eabi" }, 26 { regex_feature = "stm32l4.*", target = "thumbv7em-none-eabi" },
27 { regex_feature = "stm32l5.*", target = "thumbv8m.main-none-eabihf" }, 27 { regex_feature = "stm32l5.*", target = "thumbv8m.main-none-eabihf" },
28 { regex_feature = "stm32u5.*", target = "thumbv8m.main-none-eabihf" }, 28 { regex_feature = "stm32u5.*", target = "thumbv8m.main-none-eabihf" },
29 { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" }, 29 { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" },
30 { regex_feature = "stm32wba.*", target = "thumbv8m.main-none-eabihf" },
30 { regex_feature = "stm32wl.*", target = "thumbv7em-none-eabi" }, 31 { regex_feature = "stm32wl.*", target = "thumbv7em-none-eabi" },
31] 32]
32 33
33[dependencies] 34[dependencies]
34embassy-sync = { version = "0.2.0", path = "../embassy-sync" } 35embassy-sync = { version = "0.3.0", path = "../embassy-sync" }
35embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } 36embassy-time = { version = "0.1.3", path = "../embassy-time", optional = true }
36embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 37embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
37embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } 38embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] }
38embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } 39embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
@@ -62,7 +63,7 @@ stm32-metapac = "12"
62vcell = "0.1.3" 63vcell = "0.1.3"
63bxcan = "0.7.0" 64bxcan = "0.7.0"
64nb = "1.0.0" 65nb = "1.0.0"
65stm32-fmc = "0.2.4" 66stm32-fmc = "0.3.0"
66seq-macro = "0.3.0" 67seq-macro = "0.3.0"
67cfg-if = "1.0.0" 68cfg-if = "1.0.0"
68embedded-io = { version = "0.5.0" } 69embedded-io = { version = "0.5.0" }
@@ -77,7 +78,7 @@ critical-section = { version = "1.1", features = ["std"] }
77[build-dependencies] 78[build-dependencies]
78proc-macro2 = "1.0.36" 79proc-macro2 = "1.0.36"
79quote = "1.0.15" 80quote = "1.0.15"
80stm32-metapac = { path = "../../stm32-data-generated/stm32-metapac", default-features = false, features = ["metadata"]} 81stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-735cab337aad6161f3d6bcf3e49cd1f034bc3130", default-features = false, features = ["metadata"]}
81 82
82[features] 83[features]
83default = ["rt"] 84default = ["rt"]
@@ -1454,6 +1455,10 @@ stm32wb55vc = [ "stm32-metapac/stm32wb55vc" ]
1454stm32wb55ve = [ "stm32-metapac/stm32wb55ve" ] 1455stm32wb55ve = [ "stm32-metapac/stm32wb55ve" ]
1455stm32wb55vg = [ "stm32-metapac/stm32wb55vg" ] 1456stm32wb55vg = [ "stm32-metapac/stm32wb55vg" ]
1456stm32wb55vy = [ "stm32-metapac/stm32wb55vy" ] 1457stm32wb55vy = [ "stm32-metapac/stm32wb55vy" ]
1458stm32wba52ce = [ "stm32-metapac/stm32wba52ce" ]
1459stm32wba52cg = [ "stm32-metapac/stm32wba52cg" ]
1460stm32wba52ke = [ "stm32-metapac/stm32wba52ke" ]
1461stm32wba52kg = [ "stm32-metapac/stm32wba52kg" ]
1457stm32wl54cc-cm4 = [ "stm32-metapac/stm32wl54cc-cm4" ] 1462stm32wl54cc-cm4 = [ "stm32-metapac/stm32wl54cc-cm4" ]
1458stm32wl54cc-cm0p = [ "stm32-metapac/stm32wl54cc-cm0p" ] 1463stm32wl54cc-cm0p = [ "stm32-metapac/stm32wl54cc-cm0p" ]
1459stm32wl54jc-cm4 = [ "stm32-metapac/stm32wl54jc-cm4" ] 1464stm32wl54jc-cm4 = [ "stm32-metapac/stm32wl54jc-cm4" ]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 1b86dad7a..ccc9210df 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -308,13 +308,11 @@ fn main() {
308 // ======== 308 // ========
309 // Generate RccPeripheral impls 309 // Generate RccPeripheral impls
310 310
311 let refcounted_peripherals = HashSet::from(["usart", "adc"]);
312 let mut refcount_statics = HashSet::new();
313
311 for p in METADATA.peripherals { 314 for p in METADATA.peripherals {
312 // generating RccPeripheral impl for H7 ADC3 would result in bad frequency 315 if !singletons.contains(&p.name.to_string()) {
313 if !singletons.contains(&p.name.to_string())
314 || (p.name == "ADC3" && METADATA.line.starts_with("STM32H7"))
315 || (p.name.starts_with("ADC") && p.registers.as_ref().map_or(false, |r| r.version == "f3"))
316 || (p.name.starts_with("ADC") && p.registers.as_ref().map_or(false, |r| r.version == "v4"))
317 {
318 continue; 316 continue;
319 } 317 }
320 318
@@ -344,11 +342,36 @@ fn main() {
344 TokenStream::new() 342 TokenStream::new()
345 }; 343 };
346 344
345 let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" };
347 let pname = format_ident!("{}", p.name); 346 let pname = format_ident!("{}", p.name);
348 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase()); 347 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase());
349 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); 348 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
350 let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); 349 let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase());
351 350
351 let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype) {
352 let refcount_static =
353 format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase());
354
355 refcount_statics.insert(refcount_static.clone());
356
357 (
358 quote! {
359 unsafe { refcount_statics::#refcount_static += 1 };
360 if unsafe { refcount_statics::#refcount_static } > 1 {
361 return;
362 }
363 },
364 quote! {
365 unsafe { refcount_statics::#refcount_static -= 1 };
366 if unsafe { refcount_statics::#refcount_static } > 0 {
367 return;
368 }
369 },
370 )
371 } else {
372 (TokenStream::new(), TokenStream::new())
373 };
374
352 g.extend(quote! { 375 g.extend(quote! {
353 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { 376 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
354 fn frequency() -> crate::time::Hertz { 377 fn frequency() -> crate::time::Hertz {
@@ -356,6 +379,7 @@ fn main() {
356 } 379 }
357 fn enable() { 380 fn enable() {
358 critical_section::with(|_| { 381 critical_section::with(|_| {
382 #before_enable
359 #[cfg(feature = "low-power")] 383 #[cfg(feature = "low-power")]
360 crate::rcc::clock_refcount_add(); 384 crate::rcc::clock_refcount_add();
361 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); 385 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
@@ -364,6 +388,7 @@ fn main() {
364 } 388 }
365 fn disable() { 389 fn disable() {
366 critical_section::with(|_| { 390 critical_section::with(|_| {
391 #before_disable
367 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); 392 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
368 #[cfg(feature = "low-power")] 393 #[cfg(feature = "low-power")]
369 crate::rcc::clock_refcount_sub(); 394 crate::rcc::clock_refcount_sub();
@@ -379,6 +404,19 @@ fn main() {
379 } 404 }
380 } 405 }
381 406
407 let mut refcount_mod = TokenStream::new();
408 for refcount_static in refcount_statics {
409 refcount_mod.extend(quote! {
410 pub(crate) static mut #refcount_static: u8 = 0;
411 });
412 }
413
414 g.extend(quote! {
415 mod refcount_statics {
416 #refcount_mod
417 }
418 });
419
382 // ======== 420 // ========
383 // Generate fns to enable GPIO, DMA in RCC 421 // Generate fns to enable GPIO, DMA in RCC
384 422
@@ -673,6 +711,10 @@ fn main() {
673 711
674 // ADC is special 712 // ADC is special
675 if regs.kind == "adc" { 713 if regs.kind == "adc" {
714 if p.rcc.is_none() {
715 continue;
716 }
717
676 let peri = format_ident!("{}", p.name); 718 let peri = format_ident!("{}", p.name);
677 let pin_name = format_ident!("{}", pin.pin); 719 let pin_name = format_ident!("{}", pin.pin);
678 720
@@ -786,6 +828,17 @@ fn main() {
786 let mut peripherals_table: Vec<Vec<String>> = Vec::new(); 828 let mut peripherals_table: Vec<Vec<String>> = Vec::new();
787 let mut pins_table: Vec<Vec<String>> = Vec::new(); 829 let mut pins_table: Vec<Vec<String>> = Vec::new();
788 let mut dma_channels_table: Vec<Vec<String>> = Vec::new(); 830 let mut dma_channels_table: Vec<Vec<String>> = Vec::new();
831 let mut adc_common_table: Vec<Vec<String>> = Vec::new();
832
833 /*
834 If ADC3_COMMON exists, ADC3 and higher are assigned to it
835 All other ADCs are assigned to ADC_COMMON
836
837 ADC3 and higher are assigned to the adc34 clock in the table
838 The adc3_common cfg directive is added if ADC3_COMMON exists
839 */
840 let has_adc3 = METADATA.peripherals.iter().find(|p| p.name == "ADC3_COMMON").is_some();
841 let set_adc345 = HashSet::from(["ADC3", "ADC4", "ADC5"]);
789 842
790 for m in METADATA 843 for m in METADATA
791 .memory 844 .memory
@@ -823,6 +876,17 @@ fn main() {
823 } 876 }
824 } 877 }
825 878
879 if regs.kind == "adc" {
880 let (adc_common, adc_clock) = if set_adc345.contains(p.name) && has_adc3 {
881 ("ADC3_COMMON", "adc34")
882 } else {
883 ("ADC_COMMON", "adc")
884 };
885
886 let row = vec![p.name.to_string(), adc_common.to_string(), adc_clock.to_string()];
887 adc_common_table.push(row);
888 }
889
826 for irq in p.interrupts { 890 for irq in p.interrupts {
827 let row = vec![ 891 let row = vec![
828 p.name.to_string(), 892 p.name.to_string(),
@@ -901,6 +965,7 @@ fn main() {
901 make_table(&mut m, "foreach_peripheral", &peripherals_table); 965 make_table(&mut m, "foreach_peripheral", &peripherals_table);
902 make_table(&mut m, "foreach_pin", &pins_table); 966 make_table(&mut m, "foreach_pin", &pins_table);
903 make_table(&mut m, "foreach_dma_channel", &dma_channels_table); 967 make_table(&mut m, "foreach_dma_channel", &dma_channels_table);
968 make_table(&mut m, "foreach_adc", &adc_common_table);
904 969
905 let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 970 let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
906 let out_file = out_dir.join("_macros.rs").to_string_lossy().to_string(); 971 let out_file = out_dir.join("_macros.rs").to_string_lossy().to_string();
@@ -943,12 +1008,23 @@ fn main() {
943 } 1008 }
944 1009
945 // ======= 1010 // =======
1011 // ADC3_COMMON is present
1012 if has_adc3 {
1013 println!("cargo:rustc-cfg={}", "adc3_common");
1014 }
1015
1016 // =======
946 // Features for targeting groups of chips 1017 // Features for targeting groups of chips
947 1018
948 println!("cargo:rustc-cfg={}", &chip_name[..7]); // stm32f4 1019 if &chip_name[..8] == "stm32wba" {
949 println!("cargo:rustc-cfg={}", &chip_name[..9]); // stm32f429 1020 println!("cargo:rustc-cfg={}", &chip_name[..8]); // stm32wba
950 println!("cargo:rustc-cfg={}x", &chip_name[..8]); // stm32f42x 1021 println!("cargo:rustc-cfg={}", &chip_name[..10]); // stm32wba52
951 println!("cargo:rustc-cfg={}x{}", &chip_name[..7], &chip_name[8..9]); // stm32f4x9 1022 } else {
1023 println!("cargo:rustc-cfg={}", &chip_name[..7]); // stm32f4
1024 println!("cargo:rustc-cfg={}", &chip_name[..9]); // stm32f429
1025 println!("cargo:rustc-cfg={}x", &chip_name[..8]); // stm32f42x
1026 println!("cargo:rustc-cfg={}x{}", &chip_name[..7], &chip_name[8..9]); // stm32f4x9
1027 }
952 1028
953 // Handle time-driver-XXXX features. 1029 // Handle time-driver-XXXX features.
954 if env::var("CARGO_FEATURE_TIME_DRIVER_ANY").is_ok() {} 1030 if env::var("CARGO_FEATURE_TIME_DRIVER_ANY").is_ok() {}
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs
index e577ec289..c13264819 100644
--- a/embassy-stm32/src/adc/f1.rs
+++ b/embassy-stm32/src/adc/f1.rs
@@ -1,16 +1,37 @@
1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::task::Poll;
4
1use embassy_hal_internal::into_ref; 5use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs; 6use embedded_hal_02::blocking::delay::DelayUs;
3 7
4use crate::adc::{Adc, AdcPin, Instance, SampleTime}; 8use crate::adc::{Adc, AdcPin, Instance, SampleTime};
5use crate::rcc::get_freqs; 9use crate::rcc::get_freqs;
6use crate::time::Hertz; 10use crate::time::Hertz;
7use crate::Peripheral; 11use crate::{interrupt, Peripheral};
8 12
9pub const VDDA_CALIB_MV: u32 = 3300; 13pub const VDDA_CALIB_MV: u32 = 3300;
10pub const ADC_MAX: u32 = (1 << 12) - 1; 14pub const ADC_MAX: u32 = (1 << 12) - 1;
11// No calibration data for F103, voltage should be 1.2v 15// No calibration data for F103, voltage should be 1.2v
12pub const VREF_INT: u32 = 1200; 16pub const VREF_INT: u32 = 1200;
13 17
18/// Interrupt handler.
19pub struct InterruptHandler<T: Instance> {
20 _phantom: PhantomData<T>,
21}
22
23impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
24 unsafe fn on_interrupt() {
25 if T::regs().sr().read().eoc() {
26 T::regs().cr1().modify(|w| w.set_eocie(false));
27 } else {
28 return;
29 }
30
31 T::state().waker.wake();
32 }
33}
34
14pub struct Vref; 35pub struct Vref;
15impl<T: Instance> AdcPin<T> for Vref {} 36impl<T: Instance> AdcPin<T> for Vref {}
16impl<T: Instance> super::sealed::AdcPin<T> for Vref { 37impl<T: Instance> super::sealed::AdcPin<T> for Vref {
@@ -60,7 +81,7 @@ impl<'d, T: Instance> Adc<'d, T> {
60 } 81 }
61 82
62 fn freq() -> Hertz { 83 fn freq() -> Hertz {
63 unsafe { get_freqs() }.adc 84 unsafe { get_freqs() }.adc.unwrap()
64 } 85 }
65 86
66 pub fn sample_time_for_us(&self, us: u32) -> SampleTime { 87 pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
@@ -95,18 +116,28 @@ impl<'d, T: Instance> Adc<'d, T> {
95 } 116 }
96 117
97 /// Perform a single conversion. 118 /// Perform a single conversion.
98 fn convert(&mut self) -> u16 { 119 async fn convert(&mut self) -> u16 {
99 T::regs().cr2().modify(|reg| { 120 T::regs().cr2().modify(|reg| {
100 reg.set_adon(true); 121 reg.set_adon(true);
101 reg.set_swstart(true); 122 reg.set_swstart(true);
102 }); 123 });
103 while T::regs().cr2().read().swstart() {} 124 T::regs().cr1().modify(|w| w.set_eocie(true));
104 while !T::regs().sr().read().eoc() {} 125
126 poll_fn(|cx| {
127 T::state().waker.register(cx.waker());
128
129 if !T::regs().cr2().read().swstart() && T::regs().sr().read().eoc() {
130 Poll::Ready(())
131 } else {
132 Poll::Pending
133 }
134 })
135 .await;
105 136
106 T::regs().dr().read().0 as u16 137 T::regs().dr().read().0 as u16
107 } 138 }
108 139
109 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { 140 pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
110 Self::set_channel_sample_time(pin.channel(), self.sample_time); 141 Self::set_channel_sample_time(pin.channel(), self.sample_time);
111 T::regs().cr1().modify(|reg| { 142 T::regs().cr1().modify(|reg| {
112 reg.set_scan(false); 143 reg.set_scan(false);
@@ -123,7 +154,7 @@ impl<'d, T: Instance> Adc<'d, T> {
123 154
124 // Configure the channel to sample 155 // Configure the channel to sample
125 T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())); 156 T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel()));
126 self.convert() 157 self.convert().await
127 } 158 }
128 159
129 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 160 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
@@ -135,3 +166,11 @@ impl<'d, T: Instance> Adc<'d, T> {
135 } 166 }
136 } 167 }
137} 168}
169
170impl<'d, T: Instance> Drop for Adc<'d, T> {
171 fn drop(&mut self) {
172 T::regs().cr2().modify(|reg| reg.set_adon(false));
173
174 T::disable();
175 }
176}
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs
new file mode 100644
index 000000000..7c13f8106
--- /dev/null
+++ b/embassy-stm32/src/adc/f3.rs
@@ -0,0 +1,195 @@
1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::task::Poll;
4
5use embassy_hal_internal::into_ref;
6use embedded_hal_02::blocking::delay::DelayUs;
7
8use crate::adc::{Adc, AdcPin, Instance, SampleTime};
9use crate::interrupt::typelevel::Interrupt;
10use crate::time::Hertz;
11use crate::{interrupt, Peripheral};
12
13pub const VDDA_CALIB_MV: u32 = 3300;
14pub const ADC_MAX: u32 = (1 << 12) - 1;
15pub const VREF_INT: u32 = 1230;
16
17/// Interrupt handler.
18pub struct InterruptHandler<T: Instance> {
19 _phantom: PhantomData<T>,
20}
21
22impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
23 unsafe fn on_interrupt() {
24 if T::regs().isr().read().eoc() {
25 T::regs().ier().modify(|w| w.set_eocie(false));
26 } else {
27 return;
28 }
29
30 T::state().waker.wake();
31 }
32}
33
34pub struct Vref;
35impl<T: Instance> AdcPin<T> for Vref {}
36impl<T: Instance> super::sealed::AdcPin<T> for Vref {
37 fn channel(&self) -> u8 {
38 18
39 }
40}
41
42impl Vref {
43 /// The value that vref would be if vdda was at 3300mv
44 pub fn value(&self) -> u16 {
45 crate::pac::VREFINTCAL.data().read().value()
46 }
47}
48
49pub struct Temperature;
50impl<T: Instance> AdcPin<T> for Temperature {}
51impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
52 fn channel(&self) -> u8 {
53 16
54 }
55}
56
57impl<'d, T: Instance> Adc<'d, T> {
58 pub fn new(
59 adc: impl Peripheral<P = T> + 'd,
60 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
61 delay: &mut impl DelayUs<u32>,
62 ) -> Self {
63 use crate::pac::adc::vals;
64
65 into_ref!(adc);
66
67 T::enable();
68 T::reset();
69
70 // Enable the adc regulator
71 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::INTERMEDIATE));
72 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::ENABLED));
73
74 // Wait for the regulator to stabilize
75 delay.delay_us(10);
76
77 assert!(!T::regs().cr().read().aden());
78
79 // Begin calibration
80 T::regs().cr().modify(|w| w.set_adcaldif(false));
81 T::regs().cr().modify(|w| w.set_adcal(true));
82
83 while T::regs().cr().read().adcal() {}
84
85 // Wait more than 4 clock cycles after adcal is cleared (RM0364 p. 223)
86 delay.delay_us(1 + (6 * 1_000_000 / Self::freq().0));
87
88 // Enable the adc
89 T::regs().cr().modify(|w| w.set_aden(true));
90
91 // Wait until the adc is ready
92 while !T::regs().isr().read().adrdy() {}
93
94 T::Interrupt::unpend();
95 unsafe {
96 T::Interrupt::enable();
97 }
98
99 Self {
100 adc,
101 sample_time: Default::default(),
102 }
103 }
104
105 fn freq() -> Hertz {
106 <T as crate::adc::sealed::Instance>::frequency()
107 }
108
109 pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
110 match us * Self::freq().0 / 1_000_000 {
111 0..=1 => SampleTime::Cycles1_5,
112 2..=4 => SampleTime::Cycles4_5,
113 5..=7 => SampleTime::Cycles7_5,
114 8..=19 => SampleTime::Cycles19_5,
115 20..=61 => SampleTime::Cycles61_5,
116 62..=181 => SampleTime::Cycles181_5,
117 _ => SampleTime::Cycles601_5,
118 }
119 }
120
121 pub fn enable_vref(&self, _delay: &mut impl DelayUs<u32>) -> Vref {
122 T::common_regs().ccr().modify(|w| w.set_vrefen(true));
123
124 Vref {}
125 }
126
127 pub fn enable_temperature(&self) -> Temperature {
128 T::common_regs().ccr().modify(|w| w.set_tsen(true));
129
130 Temperature {}
131 }
132
133 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
134 self.sample_time = sample_time;
135 }
136
137 /// Perform a single conversion.
138 async fn convert(&mut self) -> u16 {
139 T::regs().isr().write(|_| {});
140 T::regs().ier().modify(|w| w.set_eocie(true));
141 T::regs().cr().modify(|w| w.set_adstart(true));
142
143 poll_fn(|cx| {
144 T::state().waker.register(cx.waker());
145
146 if T::regs().isr().read().eoc() {
147 Poll::Ready(())
148 } else {
149 Poll::Pending
150 }
151 })
152 .await;
153
154 T::regs().isr().write(|_| {});
155
156 T::regs().dr().read().rdata()
157 }
158
159 pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
160 Self::set_channel_sample_time(pin.channel(), self.sample_time);
161
162 // Configure the channel to sample
163 T::regs().sqr1().write(|w| w.set_sq(0, pin.channel()));
164 self.convert().await
165 }
166
167 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
168 let sample_time = sample_time.into();
169 if ch <= 9 {
170 T::regs().smpr1().modify(|reg| reg.set_smp(ch as _, sample_time));
171 } else {
172 T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
173 }
174 }
175}
176
177impl<'d, T: Instance> Drop for Adc<'d, T> {
178 fn drop(&mut self) {
179 use crate::pac::adc::vals;
180
181 T::regs().cr().modify(|w| w.set_adstp(true));
182
183 while T::regs().cr().read().adstp() {}
184
185 T::regs().cr().modify(|w| w.set_addis(true));
186
187 while T::regs().cr().read().aden() {}
188
189 // Disable the adc regulator
190 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::INTERMEDIATE));
191 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::DISABLED));
192
193 T::disable();
194 }
195}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index e57889aa6..365738a31 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -1,23 +1,24 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg(not(any(adc_f3, adc_f3_v2)))] 3#[cfg(not(adc_f3_v2))]
4#[cfg_attr(adc_f1, path = "f1.rs")] 4#[cfg_attr(adc_f1, path = "f1.rs")]
5#[cfg_attr(adc_f3, path = "f3.rs")]
5#[cfg_attr(adc_v1, path = "v1.rs")] 6#[cfg_attr(adc_v1, path = "v1.rs")]
6#[cfg_attr(adc_v2, path = "v2.rs")] 7#[cfg_attr(adc_v2, path = "v2.rs")]
7#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")] 8#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")]
8#[cfg_attr(adc_v4, path = "v4.rs")] 9#[cfg_attr(adc_v4, path = "v4.rs")]
9mod _version; 10mod _version;
10 11
11#[cfg(not(any(adc_f1, adc_f3, adc_f3_v2)))] 12#[cfg(not(any(adc_f1, adc_f3_v2)))]
12mod resolution; 13mod resolution;
13mod sample_time; 14mod sample_time;
14 15
15#[cfg(not(any(adc_f3, adc_f3_v2)))]
16#[allow(unused)] 16#[allow(unused)]
17#[cfg(not(adc_f3_v2))]
17pub use _version::*; 18pub use _version::*;
18#[cfg(not(any(adc_f1, adc_f3, adc_f3_v2)))] 19#[cfg(not(any(adc_f1, adc_f3, adc_f3_v2)))]
19pub use resolution::Resolution; 20pub use resolution::Resolution;
20#[cfg(not(any(adc_f3, adc_f3_v2)))] 21#[cfg(not(adc_f3_v2))]
21pub use sample_time::SampleTime; 22pub use sample_time::SampleTime;
22 23
23use crate::peripherals; 24use crate::peripherals;
@@ -25,18 +26,46 @@ use crate::peripherals;
25pub struct Adc<'d, T: Instance> { 26pub struct Adc<'d, T: Instance> {
26 #[allow(unused)] 27 #[allow(unused)]
27 adc: crate::PeripheralRef<'d, T>, 28 adc: crate::PeripheralRef<'d, T>,
28 #[cfg(not(any(adc_f3, adc_f3_v2)))] 29 #[cfg(not(adc_f3_v2))]
29 sample_time: SampleTime, 30 sample_time: SampleTime,
30} 31}
31 32
32pub(crate) mod sealed { 33pub(crate) mod sealed {
33 pub trait Instance { 34 #[cfg(any(adc_f1, adc_f3, adc_v1))]
35 use embassy_sync::waitqueue::AtomicWaker;
36
37 #[cfg(any(adc_f1, adc_f3, adc_v1))]
38 pub struct State {
39 pub waker: AtomicWaker,
40 }
41
42 #[cfg(any(adc_f1, adc_f3, adc_v1))]
43 impl State {
44 pub const fn new() -> Self {
45 Self {
46 waker: AtomicWaker::new(),
47 }
48 }
49 }
50
51 pub trait InterruptableInstance {
52 type Interrupt: crate::interrupt::typelevel::Interrupt;
53 }
54
55 pub trait Instance: InterruptableInstance {
34 fn regs() -> crate::pac::adc::Adc; 56 fn regs() -> crate::pac::adc::Adc;
35 #[cfg(not(any(adc_f1, adc_v1, adc_f3, adc_f3_v2)))] 57 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_g0)))]
36 fn common_regs() -> crate::pac::adccommon::AdcCommon; 58 fn common_regs() -> crate::pac::adccommon::AdcCommon;
59 #[cfg(adc_f3)]
60 fn frequency() -> crate::time::Hertz;
61 #[cfg(any(adc_f1, adc_f3, adc_v1))]
62 fn state() -> &'static State;
37 } 63 }
38 64
39 pub trait AdcPin<T: Instance> { 65 pub trait AdcPin<T: Instance> {
66 #[cfg(any(adc_v1, adc_v2))]
67 fn set_as_analog(&mut self) {}
68
40 fn channel(&self) -> u8; 69 fn channel(&self) -> u8;
41 } 70 }
42 71
@@ -45,68 +74,45 @@ pub(crate) mod sealed {
45 } 74 }
46} 75}
47 76
48#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v4)))] 77#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v4, adc_f3)))]
49pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} 78pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
50#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v4))] 79#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v4, adc_f3))]
51pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} 80pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
52 81
53pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} 82pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}
54pub trait InternalChannel<T>: sealed::InternalChannel<T> {} 83pub trait InternalChannel<T>: sealed::InternalChannel<T> {}
55 84
56#[cfg(not(stm32h7))] 85foreach_adc!(
57foreach_peripheral!( 86 ($inst:ident, $common_inst:ident, $clock:ident) => {
58 (adc, $inst:ident) => {
59 impl crate::adc::sealed::Instance for peripherals::$inst { 87 impl crate::adc::sealed::Instance for peripherals::$inst {
60 fn regs() -> crate::pac::adc::Adc { 88 fn regs() -> crate::pac::adc::Adc {
61 crate::pac::$inst 89 crate::pac::$inst
62 } 90 }
63 #[cfg(not(any(adc_f1, adc_v1, adc_f3, adc_f3_v2)))] 91
92 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_g0)))]
64 fn common_regs() -> crate::pac::adccommon::AdcCommon { 93 fn common_regs() -> crate::pac::adccommon::AdcCommon {
65 foreach_peripheral!{ 94 return crate::pac::$common_inst
66 (adccommon, $common_inst:ident) => {
67 return crate::pac::$common_inst
68 };
69 }
70 } 95 }
71 }
72
73 impl crate::adc::Instance for peripherals::$inst {}
74 };
75);
76 96
77#[cfg(stm32h7)] 97 #[cfg(adc_f3)]
78foreach_peripheral!( 98 fn frequency() -> crate::time::Hertz {
79 (adc, ADC3) => { 99 unsafe { crate::rcc::get_freqs() }.$clock.unwrap()
80 impl crate::adc::sealed::Instance for peripherals::ADC3 {
81 fn regs() -> crate::pac::adc::Adc {
82 crate::pac::ADC3
83 } 100 }
84 #[cfg(all(not(adc_f1), not(adc_v1)))] 101
85 fn common_regs() -> crate::pac::adccommon::AdcCommon { 102 #[cfg(any(adc_f1, adc_f3, adc_v1))]
86 foreach_peripheral!{ 103 fn state() -> &'static sealed::State {
87 (adccommon, ADC3_COMMON) => { 104 static STATE: sealed::State = sealed::State::new();
88 return crate::pac::ADC3_COMMON 105 &STATE
89 };
90 }
91 } 106 }
92 } 107 }
93 108
94 impl crate::adc::Instance for peripherals::ADC3 {} 109 foreach_interrupt!(
95 }; 110 ($inst,adc,ADC,GLOBAL,$irq:ident) => {
96 (adc, $inst:ident) => { 111 impl sealed::InterruptableInstance for peripherals::$inst {
97 impl crate::adc::sealed::Instance for peripherals::$inst { 112 type Interrupt = crate::interrupt::typelevel::$irq;
98 fn regs() -> crate::pac::adc::Adc {
99 crate::pac::$inst
100 }
101 #[cfg(all(not(adc_f1), not(adc_v1)))]
102 fn common_regs() -> crate::pac::adccommon::AdcCommon {
103 foreach_peripheral!{
104 (adccommon, ADC_COMMON) => {
105 return crate::pac::ADC_COMMON
106 };
107 } 113 }
108 } 114 };
109 } 115 );
110 116
111 impl crate::adc::Instance for peripherals::$inst {} 117 impl crate::adc::Instance for peripherals::$inst {}
112 }; 118 };
@@ -117,6 +123,11 @@ macro_rules! impl_adc_pin {
117 impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {} 123 impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {}
118 124
119 impl crate::adc::sealed::AdcPin<peripherals::$inst> for crate::peripherals::$pin { 125 impl crate::adc::sealed::AdcPin<peripherals::$inst> for crate::peripherals::$pin {
126 #[cfg(any(adc_v1, adc_v2))]
127 fn set_as_analog(&mut self) {
128 <Self as crate::gpio::sealed::Pin>::set_as_analog(self);
129 }
130
120 fn channel(&self) -> u8 { 131 fn channel(&self) -> u8 {
121 $ch 132 $ch
122 } 133 }
diff --git a/embassy-stm32/src/adc/resolution.rs b/embassy-stm32/src/adc/resolution.rs
index 67fb9b8c0..5668137b5 100644
--- a/embassy-stm32/src/adc/resolution.rs
+++ b/embassy-stm32/src/adc/resolution.rs
@@ -1,4 +1,4 @@
1#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0))] 1#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
2#[derive(Clone, Copy, Debug, Eq, PartialEq)] 2#[derive(Clone, Copy, Debug, Eq, PartialEq)]
3pub enum Resolution { 3pub enum Resolution {
4 TwelveBit, 4 TwelveBit,
@@ -19,7 +19,7 @@ pub enum Resolution {
19 19
20impl Default for Resolution { 20impl Default for Resolution {
21 fn default() -> Self { 21 fn default() -> Self {
22 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0))] 22 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
23 { 23 {
24 Self::TwelveBit 24 Self::TwelveBit
25 } 25 }
@@ -40,7 +40,7 @@ impl From<Resolution> for crate::pac::adc::vals::Res {
40 Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT, 40 Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT,
41 Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT, 41 Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT,
42 Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT, 42 Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT,
43 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0))] 43 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
44 Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT, 44 Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT,
45 } 45 }
46 } 46 }
@@ -56,7 +56,7 @@ impl Resolution {
56 Resolution::TwelveBit => (1 << 12) - 1, 56 Resolution::TwelveBit => (1 << 12) - 1,
57 Resolution::TenBit => (1 << 10) - 1, 57 Resolution::TenBit => (1 << 10) - 1,
58 Resolution::EightBit => (1 << 8) - 1, 58 Resolution::EightBit => (1 << 8) - 1,
59 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0))] 59 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
60 Resolution::SixBit => (1 << 6) - 1, 60 Resolution::SixBit => (1 << 6) - 1,
61 } 61 }
62 } 62 }
diff --git a/embassy-stm32/src/adc/sample_time.rs b/embassy-stm32/src/adc/sample_time.rs
index 5480e7a77..6a6619299 100644
--- a/embassy-stm32/src/adc/sample_time.rs
+++ b/embassy-stm32/src/adc/sample_time.rs
@@ -1,4 +1,4 @@
1#[cfg(not(any(adc_f3, adc_f3_v2)))] 1#[cfg(not(adc_f3_v2))]
2macro_rules! impl_sample_time { 2macro_rules! impl_sample_time {
3 ($default_doc:expr, $default:ident, ($(($doc:expr, $variant:ident, $pac_variant:ident)),*)) => { 3 ($default_doc:expr, $default:ident, ($(($doc:expr, $variant:ident, $pac_variant:ident)),*)) => {
4 #[doc = concat!("ADC sample time\n\nThe default setting is ", $default_doc, " ADC clock cycles.")] 4 #[doc = concat!("ADC sample time\n\nThe default setting is ", $default_doc, " ADC clock cycles.")]
@@ -105,3 +105,19 @@ impl_sample_time!(
105 ("810.5", Cycles810_5, CYCLES810_5) 105 ("810.5", Cycles810_5, CYCLES810_5)
106 ) 106 )
107); 107);
108
109#[cfg(adc_f3)]
110impl_sample_time!(
111 "1.5",
112 Cycles1_5,
113 (
114 ("1.5", Cycles1_5, CYCLES1_5),
115 ("2.5", Cycles2_5, CYCLES2_5),
116 ("4.5", Cycles4_5, CYCLES4_5),
117 ("7.5", Cycles7_5, CYCLES7_5),
118 ("19.5", Cycles19_5, CYCLES19_5),
119 ("61.5", Cycles61_5, CYCLES61_5),
120 ("181.5", Cycles181_5, CYCLES181_5),
121 ("601.5", Cycles601_5, CYCLES601_5)
122 )
123);
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index e8245884e..fded26e40 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -1,39 +1,65 @@
1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::task::Poll;
4
1use embassy_hal_internal::into_ref; 5use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs; 6use embedded_hal_02::blocking::delay::DelayUs;
3 7
4use crate::adc::{Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime}; 8use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
9use crate::interrupt::typelevel::Interrupt;
5use crate::peripherals::ADC; 10use crate::peripherals::ADC;
6use crate::Peripheral; 11use crate::{interrupt, Peripheral};
7 12
8pub const VDDA_CALIB_MV: u32 = 3300; 13pub const VDDA_CALIB_MV: u32 = 3300;
9pub const VREF_INT: u32 = 1230; 14pub const VREF_INT: u32 = 1230;
10 15
16/// Interrupt handler.
17pub struct InterruptHandler<T: Instance> {
18 _phantom: PhantomData<T>,
19}
20
21impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
22 unsafe fn on_interrupt() {
23 if T::regs().isr().read().eoc() {
24 T::regs().ier().modify(|w| w.set_eocie(false));
25 } else {
26 return;
27 }
28
29 T::state().waker.wake();
30 }
31}
32
11pub struct Vbat; 33pub struct Vbat;
12impl InternalChannel<ADC> for Vbat {} 34impl AdcPin<ADC> for Vbat {}
13impl super::sealed::InternalChannel<ADC> for Vbat { 35impl super::sealed::AdcPin<ADC> for Vbat {
14 fn channel(&self) -> u8 { 36 fn channel(&self) -> u8 {
15 18 37 18
16 } 38 }
17} 39}
18 40
19pub struct Vref; 41pub struct Vref;
20impl InternalChannel<ADC> for Vref {} 42impl AdcPin<ADC> for Vref {}
21impl super::sealed::InternalChannel<ADC> for Vref { 43impl super::sealed::AdcPin<ADC> for Vref {
22 fn channel(&self) -> u8 { 44 fn channel(&self) -> u8 {
23 17 45 17
24 } 46 }
25} 47}
26 48
27pub struct Temperature; 49pub struct Temperature;
28impl InternalChannel<ADC> for Temperature {} 50impl AdcPin<ADC> for Temperature {}
29impl super::sealed::InternalChannel<ADC> for Temperature { 51impl super::sealed::AdcPin<ADC> for Temperature {
30 fn channel(&self) -> u8 { 52 fn channel(&self) -> u8 {
31 16 53 16
32 } 54 }
33} 55}
34 56
35impl<'d, T: Instance> Adc<'d, T> { 57impl<'d, T: Instance> Adc<'d, T> {
36 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 58 pub fn new(
59 adc: impl Peripheral<P = T> + 'd,
60 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
61 delay: &mut impl DelayUs<u32>,
62 ) -> Self {
37 into_ref!(adc); 63 into_ref!(adc);
38 T::enable(); 64 T::enable();
39 T::reset(); 65 T::reset();
@@ -44,12 +70,32 @@ impl<'d, T: Instance> Adc<'d, T> {
44 // tstab = 14 * 1/fadc 70 // tstab = 14 * 1/fadc
45 delay.delay_us(1); 71 delay.delay_us(1);
46 72
47 let s = Self { 73 // A.7.1 ADC calibration code example
74 T::regs().cfgr1().modify(|reg| reg.set_dmaen(false));
75 T::regs().cr().modify(|reg| reg.set_adcal(true));
76 while T::regs().cr().read().adcal() {}
77
78 // A.7.2 ADC enable sequence code example
79 if T::regs().isr().read().adrdy() {
80 T::regs().isr().modify(|reg| reg.set_adrdy(true));
81 }
82 T::regs().cr().modify(|reg| reg.set_aden(true));
83 while !T::regs().isr().read().adrdy() {
84 // ES0233, 2.4.3 ADEN bit cannot be set immediately after the ADC calibration
85 // Workaround: When the ADC calibration is complete (ADCAL = 0), keep setting the
86 // ADEN bit until the ADRDY flag goes high.
87 T::regs().cr().modify(|reg| reg.set_aden(true));
88 }
89
90 T::Interrupt::unpend();
91 unsafe {
92 T::Interrupt::enable();
93 }
94
95 Self {
48 adc, 96 adc,
49 sample_time: Default::default(), 97 sample_time: Default::default(),
50 }; 98 }
51 s.calibrate();
52 s
53 } 99 }
54 100
55 pub fn enable_vbat(&self, _delay: &mut impl DelayUs<u32>) -> Vbat { 101 pub fn enable_vbat(&self, _delay: &mut impl DelayUs<u32>) -> Vbat {
@@ -80,21 +126,6 @@ impl<'d, T: Instance> Adc<'d, T> {
80 Temperature 126 Temperature
81 } 127 }
82 128
83 fn calibrate(&self) {
84 // A.7.1 ADC calibration code example
85 if T::regs().cr().read().aden() {
86 T::regs().cr().modify(|reg| reg.set_addis(true));
87 }
88 while T::regs().cr().read().aden() {
89 // spin
90 }
91 T::regs().cfgr1().modify(|reg| reg.set_dmaen(false));
92 T::regs().cr().modify(|reg| reg.set_adcal(true));
93 while T::regs().cr().read().adcal() {
94 // spin
95 }
96 }
97
98 pub fn set_sample_time(&mut self, sample_time: SampleTime) { 129 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
99 self.sample_time = sample_time; 130 self.sample_time = sample_time;
100 } 131 }
@@ -103,57 +134,50 @@ impl<'d, T: Instance> Adc<'d, T> {
103 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); 134 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
104 } 135 }
105 136
106 pub fn read<P>(&mut self, pin: &mut P) -> u16 137 pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
107 where
108 P: AdcPin<T> + crate::gpio::sealed::Pin,
109 {
110 let channel = pin.channel(); 138 let channel = pin.channel();
111 pin.set_as_analog(); 139 pin.set_as_analog();
112 self.read_channel(channel)
113 }
114 140
115 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { 141 // A.7.5 Single conversion sequence code example - Software trigger
116 let channel = channel.channel(); 142 T::regs().chselr().write(|reg| reg.set_chselx(channel as usize, true));
117 self.read_channel(channel)
118 }
119 143
120 fn read_channel(&mut self, channel: u8) -> u16 { 144 self.convert().await
121 // A.7.2 ADC enable sequence code example 145 }
122 if T::regs().isr().read().adrdy() {
123 T::regs().isr().modify(|reg| reg.set_adrdy(true));
124 }
125 T::regs().cr().modify(|reg| reg.set_aden(true));
126 while !T::regs().isr().read().adrdy() {
127 // ES0233, 2.4.3 ADEN bit cannot be set immediately after the ADC calibration
128 // Workaround: When the ADC calibration is complete (ADCAL = 0), keep setting the
129 // ADEN bit until the ADRDY flag goes high.
130 T::regs().cr().modify(|reg| reg.set_aden(true));
131 }
132 146
147 async fn convert(&mut self) -> u16 {
133 T::regs().isr().modify(|reg| { 148 T::regs().isr().modify(|reg| {
134 reg.set_eoc(true); 149 reg.set_eoc(true);
135 reg.set_eosmp(true); 150 reg.set_eosmp(true);
136 }); 151 });
137 152
138 // A.7.5 Single conversion sequence code example - Software trigger
139 T::regs().chselr().write(|reg| reg.set_chselx(channel as usize, true));
140 T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into())); 153 T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into()));
154 T::regs().ier().modify(|w| w.set_eocie(true));
141 T::regs().cr().modify(|reg| reg.set_adstart(true)); 155 T::regs().cr().modify(|reg| reg.set_adstart(true));
142 while !T::regs().isr().read().eoc() {
143 // spin
144 }
145 let value = T::regs().dr().read().0 as u16;
146 156
157 poll_fn(|cx| {
158 T::state().waker.register(cx.waker());
159
160 if T::regs().isr().read().eoc() {
161 Poll::Ready(())
162 } else {
163 Poll::Pending
164 }
165 })
166 .await;
167
168 T::regs().dr().read().data()
169 }
170}
171
172impl<'d, T: Instance> Drop for Adc<'d, T> {
173 fn drop(&mut self) {
147 // A.7.3 ADC disable code example 174 // A.7.3 ADC disable code example
148 T::regs().cr().modify(|reg| reg.set_adstp(true)); 175 T::regs().cr().modify(|reg| reg.set_adstp(true));
149 while T::regs().cr().read().adstp() { 176 while T::regs().cr().read().adstp() {}
150 // spin 177
151 }
152 T::regs().cr().modify(|reg| reg.set_addis(true)); 178 T::regs().cr().modify(|reg| reg.set_addis(true));
153 while T::regs().cr().read().aden() { 179 while T::regs().cr().read().aden() {}
154 // spin
155 }
156 180
157 value 181 T::disable();
158 } 182 }
159} 183}
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs
index 9a7acea53..a669013c9 100644
--- a/embassy-stm32/src/adc/v2.rs
+++ b/embassy-stm32/src/adc/v2.rs
@@ -1,7 +1,6 @@
1use embassy_hal_internal::into_ref; 1use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs; 2use embedded_hal_02::blocking::delay::DelayUs;
3 3
4use super::InternalChannel;
5use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime}; 4use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
6use crate::peripherals::ADC1; 5use crate::peripherals::ADC1;
7use crate::time::Hertz; 6use crate::time::Hertz;
@@ -16,8 +15,8 @@ pub const VREF_CALIB_MV: u32 = 3300;
16pub const ADC_POWERUP_TIME_US: u32 = 3; 15pub const ADC_POWERUP_TIME_US: u32 = 3;
17 16
18pub struct VrefInt; 17pub struct VrefInt;
19impl InternalChannel<ADC1> for VrefInt {} 18impl AdcPin<ADC1> for VrefInt {}
20impl super::sealed::InternalChannel<ADC1> for VrefInt { 19impl super::sealed::AdcPin<ADC1> for VrefInt {
21 fn channel(&self) -> u8 { 20 fn channel(&self) -> u8 {
22 17 21 17
23 } 22 }
@@ -31,8 +30,8 @@ impl VrefInt {
31} 30}
32 31
33pub struct Temperature; 32pub struct Temperature;
34impl InternalChannel<ADC1> for Temperature {} 33impl AdcPin<ADC1> for Temperature {}
35impl super::sealed::InternalChannel<ADC1> for Temperature { 34impl super::sealed::AdcPin<ADC1> for Temperature {
36 fn channel(&self) -> u8 { 35 fn channel(&self) -> u8 {
37 cfg_if::cfg_if! { 36 cfg_if::cfg_if! {
38 if #[cfg(any(stm32f40, stm32f41))] { 37 if #[cfg(any(stm32f40, stm32f41))] {
@@ -52,8 +51,8 @@ impl Temperature {
52} 51}
53 52
54pub struct Vbat; 53pub struct Vbat;
55impl InternalChannel<ADC1> for Vbat {} 54impl AdcPin<ADC1> for Vbat {}
56impl super::sealed::InternalChannel<ADC1> for Vbat { 55impl super::sealed::AdcPin<ADC1> for Vbat {
57 fn channel(&self) -> u8 { 56 fn channel(&self) -> u8 {
58 18 57 18
59 } 58 }
@@ -102,7 +101,7 @@ where
102 let presc = Prescaler::from_pclk2(T::frequency()); 101 let presc = Prescaler::from_pclk2(T::frequency());
103 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); 102 T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre()));
104 T::regs().cr2().modify(|reg| { 103 T::regs().cr2().modify(|reg| {
105 reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); 104 reg.set_adon(true);
106 }); 105 });
107 106
108 delay.delay_us(ADC_POWERUP_TIME_US); 107 delay.delay_us(ADC_POWERUP_TIME_US);
@@ -125,7 +124,7 @@ where
125 /// [Adc::read_internal()] to perform conversion. 124 /// [Adc::read_internal()] to perform conversion.
126 pub fn enable_vrefint(&self) -> VrefInt { 125 pub fn enable_vrefint(&self) -> VrefInt {
127 T::common_regs().ccr().modify(|reg| { 126 T::common_regs().ccr().modify(|reg| {
128 reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); 127 reg.set_tsvrefe(true);
129 }); 128 });
130 129
131 VrefInt {} 130 VrefInt {}
@@ -138,7 +137,7 @@ where
138 /// temperature sensor will return vbat value. 137 /// temperature sensor will return vbat value.
139 pub fn enable_temperature(&self) -> Temperature { 138 pub fn enable_temperature(&self) -> Temperature {
140 T::common_regs().ccr().modify(|reg| { 139 T::common_regs().ccr().modify(|reg| {
141 reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); 140 reg.set_tsvrefe(true);
142 }); 141 });
143 142
144 Temperature {} 143 Temperature {}
@@ -148,7 +147,7 @@ where
148 /// [Adc::read_internal()] to perform conversion. 147 /// [Adc::read_internal()] to perform conversion.
149 pub fn enable_vbat(&self) -> Vbat { 148 pub fn enable_vbat(&self) -> Vbat {
150 T::common_regs().ccr().modify(|reg| { 149 T::common_regs().ccr().modify(|reg| {
151 reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); 150 reg.set_vbate(true);
152 }); 151 });
153 152
154 Vbat {} 153 Vbat {}
@@ -176,22 +175,11 @@ where
176 T::regs().dr().read().0 as u16 175 T::regs().dr().read().0 as u16
177 } 176 }
178 177
179 pub fn read<P>(&mut self, pin: &mut P) -> u16 178 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
180 where
181 P: AdcPin<T>,
182 P: crate::gpio::sealed::Pin,
183 {
184 pin.set_as_analog(); 179 pin.set_as_analog();
185 180
186 self.read_channel(pin.channel())
187 }
188
189 pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
190 self.read_channel(channel.channel())
191 }
192
193 fn read_channel(&mut self, channel: u8) -> u16 {
194 // Configure ADC 181 // Configure ADC
182 let channel = pin.channel();
195 183
196 // Select channel 184 // Select channel
197 T::regs().sqr3().write(|reg| reg.set_sq(0, channel)); 185 T::regs().sqr3().write(|reg| reg.set_sq(0, channel));
@@ -199,9 +187,7 @@ where
199 // Configure channel 187 // Configure channel
200 Self::set_channel_sample_time(channel, self.sample_time); 188 Self::set_channel_sample_time(channel, self.sample_time);
201 189
202 let val = self.convert(); 190 self.convert()
203
204 val
205 } 191 }
206 192
207 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 193 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
@@ -216,6 +202,10 @@ where
216 202
217impl<'d, T: Instance> Drop for Adc<'d, T> { 203impl<'d, T: Instance> Drop for Adc<'d, T> {
218 fn drop(&mut self) { 204 fn drop(&mut self) {
205 T::regs().cr2().modify(|reg| {
206 reg.set_adon(false);
207 });
208
219 T::disable(); 209 T::disable();
220 } 210 }
221} 211}
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 821cc7f6a..011ecc281 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -13,7 +13,7 @@ pub const VREF_CALIB_MV: u32 = 3000;
13/// configuration. 13/// configuration.
14fn enable() { 14fn enable() {
15 critical_section::with(|_| { 15 critical_section::with(|_| {
16 #[cfg(stm32h7)] 16 #[cfg(any(stm32h7, stm32wl))]
17 crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true)); 17 crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true));
18 #[cfg(stm32g0)] 18 #[cfg(stm32g0)]
19 crate::pac::RCC.apbenr2().modify(|w| w.set_adcen(true)); 19 crate::pac::RCC.apbenr2().modify(|w| w.set_adcen(true));
@@ -26,9 +26,9 @@ pub struct VrefInt;
26impl<T: Instance> AdcPin<T> for VrefInt {} 26impl<T: Instance> AdcPin<T> for VrefInt {}
27impl<T: Instance> super::sealed::AdcPin<T> for VrefInt { 27impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
28 fn channel(&self) -> u8 { 28 fn channel(&self) -> u8 {
29 #[cfg(not(stm32g0))] 29 #[cfg(not(adc_g0))]
30 let val = 0; 30 let val = 0;
31 #[cfg(stm32g0)] 31 #[cfg(adc_g0)]
32 let val = 13; 32 let val = 13;
33 val 33 val
34 } 34 }
@@ -38,9 +38,9 @@ pub struct Temperature;
38impl<T: Instance> AdcPin<T> for Temperature {} 38impl<T: Instance> AdcPin<T> for Temperature {}
39impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 39impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
40 fn channel(&self) -> u8 { 40 fn channel(&self) -> u8 {
41 #[cfg(not(stm32g0))] 41 #[cfg(not(adc_g0))]
42 let val = 17; 42 let val = 17;
43 #[cfg(stm32g0)] 43 #[cfg(adc_g0)]
44 let val = 12; 44 let val = 12;
45 val 45 val
46 } 46 }
@@ -50,9 +50,9 @@ pub struct Vbat;
50impl<T: Instance> AdcPin<T> for Vbat {} 50impl<T: Instance> AdcPin<T> for Vbat {}
51impl<T: Instance> super::sealed::AdcPin<T> for Vbat { 51impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
52 fn channel(&self) -> u8 { 52 fn channel(&self) -> u8 {
53 #[cfg(not(stm32g0))] 53 #[cfg(not(adc_g0))]
54 let val = 18; 54 let val = 18;
55 #[cfg(stm32g0)] 55 #[cfg(adc_g0)]
56 let val = 14; 56 let val = 14;
57 val 57 val
58 } 58 }
@@ -92,9 +92,14 @@ impl<'d, T: Instance> Adc<'d, T> {
92 } 92 }
93 93
94 pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt { 94 pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt {
95 #[cfg(not(adc_g0))]
95 T::common_regs().ccr().modify(|reg| { 96 T::common_regs().ccr().modify(|reg| {
96 reg.set_vrefen(true); 97 reg.set_vrefen(true);
97 }); 98 });
99 #[cfg(adc_g0)]
100 T::regs().ccr().modify(|reg| {
101 reg.set_vrefen(true);
102 });
98 103
99 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us 104 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
100 // to stabilize the internal voltage reference, we wait a little more. 105 // to stabilize the internal voltage reference, we wait a little more.
@@ -106,17 +111,27 @@ impl<'d, T: Instance> Adc<'d, T> {
106 } 111 }
107 112
108 pub fn enable_temperature(&self) -> Temperature { 113 pub fn enable_temperature(&self) -> Temperature {
114 #[cfg(not(adc_g0))]
109 T::common_regs().ccr().modify(|reg| { 115 T::common_regs().ccr().modify(|reg| {
110 reg.set_ch17sel(true); 116 reg.set_ch17sel(true);
111 }); 117 });
118 #[cfg(adc_g0)]
119 T::regs().ccr().modify(|reg| {
120 reg.set_tsen(true);
121 });
112 122
113 Temperature {} 123 Temperature {}
114 } 124 }
115 125
116 pub fn enable_vbat(&self) -> Vbat { 126 pub fn enable_vbat(&self) -> Vbat {
127 #[cfg(not(adc_g0))]
117 T::common_regs().ccr().modify(|reg| { 128 T::common_regs().ccr().modify(|reg| {
118 reg.set_ch18sel(true); 129 reg.set_ch18sel(true);
119 }); 130 });
131 #[cfg(adc_g0)]
132 T::regs().ccr().modify(|reg| {
133 reg.set_vbaten(true);
134 });
120 135
121 Vbat {} 136 Vbat {}
122 } 137 }
@@ -126,9 +141,9 @@ impl<'d, T: Instance> Adc<'d, T> {
126 } 141 }
127 142
128 pub fn set_resolution(&mut self, resolution: Resolution) { 143 pub fn set_resolution(&mut self, resolution: Resolution) {
129 #[cfg(not(stm32g0))] 144 #[cfg(not(adc_g0))]
130 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); 145 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
131 #[cfg(stm32g0)] 146 #[cfg(adc_g0)]
132 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); 147 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
133 } 148 }
134 149
@@ -182,9 +197,9 @@ impl<'d, T: Instance> Adc<'d, T> {
182 Self::set_channel_sample_time(pin.channel(), self.sample_time); 197 Self::set_channel_sample_time(pin.channel(), self.sample_time);
183 198
184 // Select channel 199 // Select channel
185 #[cfg(not(stm32g0))] 200 #[cfg(not(adc_g0))]
186 T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); 201 T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel()));
187 #[cfg(stm32g0)] 202 #[cfg(adc_g0)]
188 T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel())); 203 T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel()));
189 204
190 // Some models are affected by an erratum: 205 // Some models are affected by an erratum:
@@ -203,12 +218,12 @@ impl<'d, T: Instance> Adc<'d, T> {
203 val 218 val
204 } 219 }
205 220
206 #[cfg(stm32g0)] 221 #[cfg(adc_g0)]
207 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { 222 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
208 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); 223 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into()));
209 } 224 }
210 225
211 #[cfg(not(stm32g0))] 226 #[cfg(not(adc_g0))]
212 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 227 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
213 let sample_time = sample_time.into(); 228 let sample_time = sample_time.into();
214 T::regs() 229 T::regs()
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs
index 64d0f0c75..655c0cb6a 100644
--- a/embassy-stm32/src/adc/v4.rs
+++ b/embassy-stm32/src/adc/v4.rs
@@ -1,6 +1,5 @@
1use core::sync::atomic::{AtomicU8, Ordering};
2
3use embedded_hal_02::blocking::delay::DelayUs; 1use embedded_hal_02::blocking::delay::DelayUs;
2#[allow(unused)]
4use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel}; 3use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel};
5use pac::adccommon::vals::Presc; 4use pac::adccommon::vals::Presc;
6 5
@@ -13,12 +12,31 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
13/// VREF voltage used for factory calibration of VREFINTCAL register. 12/// VREF voltage used for factory calibration of VREFINTCAL register.
14pub const VREF_CALIB_MV: u32 = 3300; 13pub const VREF_CALIB_MV: u32 = 3300;
15 14
16// NOTE: Vrefint/Temperature/Vbat are only available on ADC3 on H7, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs 15/// Max single ADC operation clock frequency
16#[cfg(stm32g4)]
17const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60);
18#[cfg(stm32h7)]
19const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50);
20
21#[cfg(stm32g4)]
22const VREF_CHANNEL: u8 = 18;
23#[cfg(stm32g4)]
24const TEMP_CHANNEL: u8 = 16;
25
26#[cfg(stm32h7)]
27const VREF_CHANNEL: u8 = 19;
28#[cfg(stm32h7)]
29const TEMP_CHANNEL: u8 = 18;
30
31// TODO this should be 14 for H7a/b/35
32const VBAT_CHANNEL: u8 = 17;
33
34// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
17pub struct VrefInt; 35pub struct VrefInt;
18impl<T: Instance> InternalChannel<T> for VrefInt {} 36impl<T: Instance> InternalChannel<T> for VrefInt {}
19impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { 37impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt {
20 fn channel(&self) -> u8 { 38 fn channel(&self) -> u8 {
21 19 39 VREF_CHANNEL
22 } 40 }
23} 41}
24 42
@@ -26,7 +44,7 @@ pub struct Temperature;
26impl<T: Instance> InternalChannel<T> for Temperature {} 44impl<T: Instance> InternalChannel<T> for Temperature {}
27impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { 45impl<T: Instance> super::sealed::InternalChannel<T> for Temperature {
28 fn channel(&self) -> u8 { 46 fn channel(&self) -> u8 {
29 18 47 TEMP_CHANNEL
30 } 48 }
31} 49}
32 50
@@ -34,128 +52,10 @@ pub struct Vbat;
34impl<T: Instance> InternalChannel<T> for Vbat {} 52impl<T: Instance> InternalChannel<T> for Vbat {}
35impl<T: Instance> super::sealed::InternalChannel<T> for Vbat { 53impl<T: Instance> super::sealed::InternalChannel<T> for Vbat {
36 fn channel(&self) -> u8 { 54 fn channel(&self) -> u8 {
37 // TODO this should be 14 for H7a/b/35 55 VBAT_CHANNEL
38 17
39 } 56 }
40} 57}
41 58
42static ADC12_ENABLE_COUNTER: AtomicU8 = AtomicU8::new(0);
43
44#[cfg(stm32h7)]
45foreach_peripheral!(
46 (adc, ADC1) => {
47 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC1 {
48 fn frequency() -> crate::time::Hertz {
49 critical_section::with(|_| {
50 match unsafe { crate::rcc::get_freqs() }.adc {
51 Some(ck) => ck,
52 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.")
53 }
54 })
55 }
56
57 fn enable() {
58 critical_section::with(|_| {
59 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true))
60 });
61 ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst);
62 }
63
64 fn disable() {
65 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 {
66 critical_section::with(|_| {
67 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false));
68 })
69 }
70 ADC12_ENABLE_COUNTER.fetch_sub(1, Ordering::SeqCst);
71 }
72
73 fn reset() {
74 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 {
75 critical_section::with(|_| {
76 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true));
77 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false));
78 });
79 }
80 }
81 }
82
83 impl crate::rcc::RccPeripheral for crate::peripherals::ADC1 {}
84 };
85 (adc, ADC2) => {
86 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC2 {
87 fn frequency() -> crate::time::Hertz {
88 critical_section::with(|_| {
89 match unsafe { crate::rcc::get_freqs() }.adc {
90 Some(ck) => ck,
91 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.")
92 }
93 })
94 }
95
96 fn enable() {
97 critical_section::with(|_| {
98 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(true))
99 });
100 ADC12_ENABLE_COUNTER.fetch_add(1, Ordering::SeqCst);
101 }
102
103 fn disable() {
104 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 {
105 critical_section::with(|_| {
106 crate::pac::RCC.ahb1enr().modify(|w| w.set_adc12en(false));
107 })
108 }
109 ADC12_ENABLE_COUNTER.fetch_sub(1, Ordering::SeqCst);
110 }
111
112 fn reset() {
113 if ADC12_ENABLE_COUNTER.load(Ordering::SeqCst) == 1 {
114 critical_section::with(|_| {
115 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(true));
116 crate::pac::RCC.ahb1rstr().modify(|w| w.set_adc12rst(false));
117 });
118 }
119 }
120 }
121
122 impl crate::rcc::RccPeripheral for crate::peripherals::ADC2 {}
123 };
124 (adc, ADC3) => {
125 impl crate::rcc::sealed::RccPeripheral for crate::peripherals::ADC3 {
126 fn frequency() -> crate::time::Hertz {
127 critical_section::with(|_| {
128 match unsafe { crate::rcc::get_freqs() }.adc {
129 Some(ck) => ck,
130 None => panic!("Invalid ADC clock configuration, AdcClockSource was likely not properly configured.")
131 }
132 })
133 }
134
135 fn enable() {
136 critical_section::with(|_| {
137 crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(true))
138 });
139 }
140
141 fn disable() {
142 critical_section::with(|_| {
143 crate::pac::RCC.ahb4enr().modify(|w| w.set_adc3en(false));
144 })
145 }
146
147 fn reset() {
148 critical_section::with(|_| {
149 crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(true));
150 crate::pac::RCC.ahb4rstr().modify(|w| w.set_adc3rst(false));
151 });
152 }
153 }
154
155 impl crate::rcc::RccPeripheral for crate::peripherals::ADC3 {}
156 };
157);
158
159// NOTE (unused): The prescaler enum closely copies the hardware capabilities, 59// NOTE (unused): The prescaler enum closely copies the hardware capabilities,
160// but high prescaling doesn't make a lot of sense in the current implementation and is ommited. 60// but high prescaling doesn't make a lot of sense in the current implementation and is ommited.
161#[allow(unused)] 61#[allow(unused)]
@@ -176,7 +76,7 @@ enum Prescaler {
176 76
177impl Prescaler { 77impl Prescaler {
178 fn from_ker_ck(frequency: Hertz) -> Self { 78 fn from_ker_ck(frequency: Hertz) -> Self {
179 let raw_prescaler = frequency.0 / 50_000_000; 79 let raw_prescaler = frequency.0 / MAX_ADC_CLK_FREQ.0;
180 match raw_prescaler { 80 match raw_prescaler {
181 0 => Self::NotDivided, 81 0 => Self::NotDivided,
182 1 => Self::DividedBy2, 82 1 => Self::DividedBy2,
@@ -237,20 +137,23 @@ impl<'d, T: Instance> Adc<'d, T> {
237 let frequency = Hertz(T::frequency().0 / prescaler.divisor()); 137 let frequency = Hertz(T::frequency().0 / prescaler.divisor());
238 info!("ADC frequency set to {} Hz", frequency.0); 138 info!("ADC frequency set to {} Hz", frequency.0);
239 139
240 if frequency > Hertz::mhz(50) { 140 if frequency > MAX_ADC_CLK_FREQ {
241 panic!("Maximal allowed frequency for the ADC is 50 MHz and it varies with different packages, refer to ST docs for more information."); 141 panic!("Maximal allowed frequency for the ADC is {} MHz and it varies with different packages, refer to ST docs for more information.", MAX_ADC_CLK_FREQ.0 / 1_000_000 );
242 } 142 }
243 let boost = if frequency < Hertz::khz(6_250) {
244 Boost::LT6_25
245 } else if frequency < Hertz::khz(12_500) {
246 Boost::LT12_5
247 } else if frequency < Hertz::mhz(25) {
248 Boost::LT25
249 } else {
250 Boost::LT50
251 };
252 T::regs().cr().modify(|w| w.set_boost(boost));
253 143
144 #[cfg(stm32h7)]
145 {
146 let boost = if frequency < Hertz::khz(6_250) {
147 Boost::LT6_25
148 } else if frequency < Hertz::khz(12_500) {
149 Boost::LT12_5
150 } else if frequency < Hertz::mhz(25) {
151 Boost::LT25
152 } else {
153 Boost::LT50
154 };
155 T::regs().cr().modify(|w| w.set_boost(boost));
156 }
254 let mut s = Self { 157 let mut s = Self {
255 adc, 158 adc,
256 sample_time: Default::default(), 159 sample_time: Default::default(),
@@ -379,10 +282,14 @@ impl<'d, T: Instance> Adc<'d, T> {
379 // Configure channel 282 // Configure channel
380 Self::set_channel_sample_time(channel, self.sample_time); 283 Self::set_channel_sample_time(channel, self.sample_time);
381 284
382 T::regs().cfgr2().modify(|w| w.set_lshift(0)); 285 #[cfg(stm32h7)]
383 T::regs() 286 {
384 .pcsel() 287 T::regs().cfgr2().modify(|w| w.set_lshift(0));
385 .write(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED)); 288 T::regs()
289 .pcsel()
290 .write(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED));
291 }
292
386 T::regs().sqr1().write(|reg| { 293 T::regs().sqr1().write(|reg| {
387 reg.set_sq(0, channel); 294 reg.set_sq(0, channel);
388 reg.set_l(0); 295 reg.set_l(0);
diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs
index a1e0240c8..4d19103dd 100644
--- a/embassy-stm32/src/eth/v1/mod.rs
+++ b/embassy-stm32/src/eth/v1/mod.rs
@@ -129,7 +129,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
129 129
130 #[cfg(any(eth_v1b, eth_v1c))] 130 #[cfg(any(eth_v1b, eth_v1c))]
131 critical_section::with(|_| { 131 critical_section::with(|_| {
132 RCC.apb2enr().modify(|w| w.set_syscfgen(true));
133 RCC.ahb1enr().modify(|w| { 132 RCC.ahb1enr().modify(|w| {
134 w.set_ethen(true); 133 w.set_ethen(true);
135 w.set_ethtxen(true); 134 w.set_ethtxen(true);
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index ada495fdb..6efd40e3e 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -34,8 +34,6 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::ETH> for InterruptHandl
34 } 34 }
35} 35}
36 36
37const MTU: usize = 1514; // 14 Ethernet header + 1500 IP packet
38
39pub struct Ethernet<'d, T: Instance, P: PHY> { 37pub struct Ethernet<'d, T: Instance, P: PHY> {
40 _peri: PeripheralRef<'d, T>, 38 _peri: PeripheralRef<'d, T>,
41 pub(crate) tx: TDesRing<'d>, 39 pub(crate) tx: TDesRing<'d>,
@@ -80,7 +78,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
80 // Enable the necessary Clocks 78 // Enable the necessary Clocks
81 #[cfg(not(rcc_h5))] 79 #[cfg(not(rcc_h5))]
82 critical_section::with(|_| { 80 critical_section::with(|_| {
83 crate::pac::RCC.apb4enr().modify(|w| w.set_syscfgen(true));
84 crate::pac::RCC.ahb1enr().modify(|w| { 81 crate::pac::RCC.ahb1enr().modify(|w| {
85 w.set_eth1macen(true); 82 w.set_eth1macen(true);
86 w.set_eth1txen(true); 83 w.set_eth1txen(true);
@@ -102,9 +99,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
102 }); 99 });
103 100
104 // RMII 101 // RMII
105 crate::pac::SBS 102 crate::pac::SYSCFG
106 .pmcr() 103 .pmcr()
107 .modify(|w| w.set_eth_sel_phy(crate::pac::sbs::vals::EthSelPhy::B_0X4)); 104 .modify(|w| w.set_eth_sel_phy(crate::pac::syscfg::vals::EthSelPhy::B_0X4));
108 }); 105 });
109 106
110 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); 107 config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en);
@@ -164,7 +161,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
164 dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ? 161 dma.dmactx_cr().modify(|w| w.set_txpbl(1)); // 32 ?
165 dma.dmacrx_cr().modify(|w| { 162 dma.dmacrx_cr().modify(|w| {
166 w.set_rxpbl(1); // 32 ? 163 w.set_rxpbl(1); // 32 ?
167 w.set_rbsz(MTU as u16); 164 w.set_rbsz(RX_BUFFER_SIZE as u16);
168 }); 165 });
169 166
170 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called 167 // NOTE(unsafe) We got the peripheral singleton, which means that `rcc::init` was called
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 925cf39be..62f321709 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -6,7 +6,7 @@ use core::task::{Context, Poll};
6use embassy_hal_internal::impl_peripheral; 6use embassy_hal_internal::impl_peripheral;
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8 8
9use crate::gpio::{AnyPin, Input, Pin as GpioPin}; 9use crate::gpio::{AnyPin, Input, Level, Pin as GpioPin};
10use crate::pac::exti::regs::Lines; 10use crate::pac::exti::regs::Lines;
11use crate::pac::EXTI; 11use crate::pac::EXTI;
12use crate::{interrupt, pac, peripherals, Peripheral}; 12use crate::{interrupt, pac, peripherals, Peripheral};
@@ -39,6 +39,9 @@ fn exticr_regs() -> pac::afio::Afio {
39} 39}
40 40
41pub unsafe fn on_irq() { 41pub unsafe fn on_irq() {
42 #[cfg(feature = "low-power")]
43 crate::low_power::on_wakeup_irq();
44
42 #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))] 45 #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))]
43 let bits = EXTI.pr(0).read().0; 46 let bits = EXTI.pr(0).read().0;
44 #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))] 47 #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))]
@@ -98,6 +101,10 @@ impl<'d, T: GpioPin> ExtiInput<'d, T> {
98 self.pin.is_low() 101 self.pin.is_low()
99 } 102 }
100 103
104 pub fn get_level(&self) -> Level {
105 self.pin.get_level()
106 }
107
101 pub async fn wait_for_high<'a>(&'a mut self) { 108 pub async fn wait_for_high<'a>(&'a mut self) {
102 let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false); 109 let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false);
103 if self.is_high() { 110 if self.is_high() {
@@ -364,9 +371,4 @@ pub(crate) unsafe fn init() {
364 use crate::interrupt::typelevel::Interrupt; 371 use crate::interrupt::typelevel::Interrupt;
365 372
366 foreach_exti_irq!(enable_irq); 373 foreach_exti_irq!(enable_irq);
367
368 #[cfg(not(any(rcc_wb, rcc_wl5, rcc_wle, stm32f1, exti_h5, exti_h50)))]
369 <crate::peripherals::SYSCFG as crate::rcc::sealed::RccPeripheral>::enable();
370 #[cfg(stm32f1)]
371 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable();
372} 374}
diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs
index 066970813..78e583c1c 100644
--- a/embassy-stm32/src/fmt.rs
+++ b/embassy-stm32/src/fmt.rs
@@ -1,6 +1,8 @@
1#![macro_use] 1#![macro_use]
2#![allow(unused_macros)] 2#![allow(unused_macros)]
3 3
4use core::fmt::{Debug, Display, LowerHex};
5
4#[cfg(all(feature = "defmt", feature = "log"))] 6#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features."); 7compile_error!("You may not enable both `defmt` and `log` features.");
6 8
@@ -81,14 +83,17 @@ macro_rules! todo {
81 }; 83 };
82} 84}
83 85
86#[cfg(not(feature = "defmt"))]
84macro_rules! unreachable { 87macro_rules! unreachable {
85 ($($x:tt)*) => { 88 ($($x:tt)*) => {
86 { 89 ::core::unreachable!($($x)*)
87 #[cfg(not(feature = "defmt"))] 90 };
88 ::core::unreachable!($($x)*); 91}
89 #[cfg(feature = "defmt")] 92
90 ::defmt::unreachable!($($x)*); 93#[cfg(feature = "defmt")]
91 } 94macro_rules! unreachable {
95 ($($x:tt)*) => {
96 ::defmt::unreachable!($($x)*)
92 }; 97 };
93} 98}
94 99
@@ -223,3 +228,31 @@ impl<T, E> Try for Result<T, E> {
223 self 228 self
224 } 229 }
225} 230}
231
232#[allow(unused)]
233pub(crate) struct Bytes<'a>(pub &'a [u8]);
234
235impl<'a> Debug for Bytes<'a> {
236 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
237 write!(f, "{:#02x?}", self.0)
238 }
239}
240
241impl<'a> Display for Bytes<'a> {
242 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
243 write!(f, "{:#02x?}", self.0)
244 }
245}
246
247impl<'a> LowerHex for Bytes<'a> {
248 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
249 write!(f, "{:#02x?}", self.0)
250 }
251}
252
253#[cfg(feature = "defmt")]
254impl<'a> defmt::Format for Bytes<'a> {
255 fn format(&self, fmt: defmt::Formatter) {
256 defmt::write!(fmt, "{:02x}", self.0)
257 }
258}
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index a382cb742..c709d46da 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -758,6 +758,9 @@ foreach_pin!(
758); 758);
759 759
760pub(crate) unsafe fn init() { 760pub(crate) unsafe fn init() {
761 #[cfg(afio)]
762 <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable();
763
761 crate::_generated::init_gpio(); 764 crate::_generated::init_gpio();
762} 765}
763 766
diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs
index 31c488144..c47b0c092 100644
--- a/embassy-stm32/src/hrtim/mod.rs
+++ b/embassy-stm32/src/hrtim/mod.rs
@@ -8,6 +8,8 @@ pub use traits::Instance;
8#[allow(unused_imports)] 8#[allow(unused_imports)]
9use crate::gpio::sealed::{AFType, Pin}; 9use crate::gpio::sealed::{AFType, Pin};
10use crate::gpio::AnyPin; 10use crate::gpio::AnyPin;
11#[cfg(stm32f334)]
12use crate::rcc::get_freqs;
11use crate::time::Hertz; 13use crate::time::Hertz;
12use crate::Peripheral; 14use crate::Peripheral;
13 15
@@ -158,17 +160,29 @@ impl<'d, T: Instance> AdvancedPwm<'d, T> {
158 T::enable(); 160 T::enable();
159 <T as crate::rcc::sealed::RccPeripheral>::reset(); 161 <T as crate::rcc::sealed::RccPeripheral>::reset();
160 162
161 // // Enable and and stabilize the DLL 163 #[cfg(stm32f334)]
162 // T::regs().dllcr().modify(|w| { 164 if unsafe { get_freqs() }.hrtim.is_some() {
163 // // w.set_calen(true); 165 // Enable and and stabilize the DLL
164 // // w.set_calrte(11); 166 T::regs().dllcr().modify(|w| {
165 // w.set_cal(true); 167 w.set_cal(true);
166 // }); 168 });
167 // 169
168 // debug!("wait for dll calibration"); 170 trace!("hrtim: wait for dll calibration");
169 // while !T::regs().isr().read().dllrdy() {} 171 while !T::regs().isr().read().dllrdy() {}
170 // 172
171 // debug!("dll calibration complete"); 173 trace!("hrtim: dll calibration complete");
174
175 // Enable periodic calibration
176 // Cal must be disabled before we can enable it
177 T::regs().dllcr().modify(|w| {
178 w.set_cal(false);
179 });
180
181 T::regs().dllcr().modify(|w| {
182 w.set_calen(true);
183 w.set_calrte(11);
184 });
185 }
172 186
173 Self { 187 Self {
174 _inner: tim, 188 _inner: tim,
diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs
index 158a68862..34a363a1f 100644
--- a/embassy-stm32/src/hrtim/traits.rs
+++ b/embassy-stm32/src/hrtim/traits.rs
@@ -1,31 +1,17 @@
1use crate::rcc::sealed::RccPeripheral; 1use crate::rcc::sealed::RccPeripheral;
2use crate::time::Hertz; 2use crate::time::Hertz;
3 3
4#[repr(u8)]
4#[derive(Clone, Copy)] 5#[derive(Clone, Copy)]
5pub(crate) enum Prescaler { 6pub(crate) enum Prescaler {
6 Div1, 7 Div1 = 1,
7 Div2, 8 Div2 = 2,
8 Div4, 9 Div4 = 4,
9 Div8, 10 Div8 = 8,
10 Div16, 11 Div16 = 16,
11 Div32, 12 Div32 = 32,
12 Div64, 13 Div64 = 64,
13 Div128, 14 Div128 = 128,
14}
15
16impl From<Prescaler> for u32 {
17 fn from(val: Prescaler) -> Self {
18 match val {
19 Prescaler::Div1 => 1,
20 Prescaler::Div2 => 2,
21 Prescaler::Div4 => 4,
22 Prescaler::Div8 => 8,
23 Prescaler::Div16 => 16,
24 Prescaler::Div32 => 32,
25 Prescaler::Div64 => 64,
26 Prescaler::Div128 => 128,
27 }
28 }
29} 15}
30 16
31impl From<Prescaler> for u8 { 17impl From<Prescaler> for u8 {
@@ -72,7 +58,7 @@ impl Prescaler {
72 Prescaler::Div128, 58 Prescaler::Div128,
73 ] 59 ]
74 .iter() 60 .iter()
75 .skip_while(|psc| <Prescaler as Into<u32>>::into(**psc) <= val) 61 .skip_while(|psc| **psc as u32 <= val)
76 .next() 62 .next()
77 .unwrap() 63 .unwrap()
78 } 64 }
@@ -80,7 +66,7 @@ impl Prescaler {
80 pub fn compute_min_low_res(val: u32) -> Self { 66 pub fn compute_min_low_res(val: u32) -> Self {
81 *[Prescaler::Div32, Prescaler::Div64, Prescaler::Div128] 67 *[Prescaler::Div32, Prescaler::Div64, Prescaler::Div128]
82 .iter() 68 .iter()
83 .skip_while(|psc| <Prescaler as Into<u32>>::into(**psc) <= val) 69 .skip_while(|psc| **psc as u32 <= val)
84 .next() 70 .next()
85 .unwrap() 71 .unwrap()
86 } 72 }
@@ -92,97 +78,90 @@ pub(crate) mod sealed {
92 pub trait Instance: RccPeripheral { 78 pub trait Instance: RccPeripheral {
93 fn regs() -> crate::pac::hrtim::Hrtim; 79 fn regs() -> crate::pac::hrtim::Hrtim;
94 80
95 fn set_master_frequency(frequency: Hertz); 81 fn set_master_frequency(frequency: Hertz) {
96 82 let f = frequency.0;
97 fn set_channel_frequency(channnel: usize, frequency: Hertz); 83 #[cfg(not(stm32f334))]
98 84 let timer_f = Self::frequency().0;
99 /// Set the dead time as a proportion of max_duty 85 #[cfg(stm32f334)]
100 fn set_channel_dead_time(channnel: usize, dead_time: u16); 86 let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
101
102 // fn enable_outputs(enable: bool);
103 //
104 // fn enable_channel(&mut self, channel: usize, enable: bool);
105 }
106}
107 87
108pub trait Instance: sealed::Instance + 'static {} 88 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
109 89 let psc = if Self::regs().isr().read().dllrdy() {
110foreach_interrupt! { 90 Prescaler::compute_min_high_res(psc_min)
111 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { 91 } else {
112 impl sealed::Instance for crate::peripherals::$inst { 92 Prescaler::compute_min_low_res(psc_min)
113 fn regs() -> crate::pac::hrtim::Hrtim { 93 };
114 crate::pac::$inst
115 }
116 94
117 fn set_master_frequency(frequency: Hertz) { 95 let timer_f = 32 * (timer_f / psc as u32);
118 use crate::rcc::sealed::RccPeripheral; 96 let per: u16 = (timer_f / f) as u16;
119 97
120 let f = frequency.0; 98 let regs = Self::regs();
121 let timer_f = Self::frequency().0;
122 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
123 let psc = if Self::regs().isr().read().dllrdy() {
124 Prescaler::compute_min_high_res(psc_min)
125 } else {
126 Prescaler::compute_min_low_res(psc_min)
127 };
128 99
129 let psc_val: u32 = psc.into(); 100 regs.mcr().modify(|w| w.set_ckpsc(psc.into()));
130 let timer_f = 32 * (timer_f / psc_val); 101 regs.mper().modify(|w| w.set_mper(per));
131 let per: u16 = (timer_f / f) as u16; 102 }
132 103
133 let regs = Self::regs(); 104 fn set_channel_frequency(channel: usize, frequency: Hertz) {
105 let f = frequency.0;
106 #[cfg(not(stm32f334))]
107 let timer_f = Self::frequency().0;
108 #[cfg(stm32f334)]
109 let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0;
134 110
135 regs.mcr().modify(|w| w.set_ckpsc(psc.into())); 111 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
136 regs.mper().modify(|w| w.set_mper(per)); 112 let psc = if Self::regs().isr().read().dllrdy() {
137 } 113 Prescaler::compute_min_high_res(psc_min)
114 } else {
115 Prescaler::compute_min_low_res(psc_min)
116 };
138 117
139 fn set_channel_frequency(channel: usize, frequency: Hertz) { 118 let timer_f = 32 * (timer_f / psc as u32);
140 use crate::rcc::sealed::RccPeripheral; 119 let per: u16 = (timer_f / f) as u16;
141 120
142 let f = frequency.0; 121 let regs = Self::regs();
143 let timer_f = Self::frequency().0;
144 let psc_min = (timer_f / f) / (u16::MAX as u32 / 32);
145 let psc = if Self::regs().isr().read().dllrdy() {
146 Prescaler::compute_min_high_res(psc_min)
147 } else {
148 Prescaler::compute_min_low_res(psc_min)
149 };
150 122
151 let psc_val: u32 = psc.into(); 123 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into()));
152 let timer_f = 32 * (timer_f / psc_val); 124 regs.tim(channel).per().modify(|w| w.set_per(per));
153 let per: u16 = (timer_f / f) as u16; 125 }
154 126
155 let regs = Self::regs(); 127 /// Set the dead time as a proportion of max_duty
156 128
157 regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); 129 fn set_channel_dead_time(channel: usize, dead_time: u16) {
158 regs.tim(channel).per().modify(|w| w.set_per(per)); 130 let regs = Self::regs();
159 }
160 131
161 fn set_channel_dead_time(channel: usize, dead_time: u16) { 132 let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into();
162 133
163 let regs = Self::regs(); 134 // The dead-time base clock runs 4 times slower than the hrtim base clock
135 // u9::MAX = 511
136 let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511);
137 let psc = if Self::regs().isr().read().dllrdy() {
138 Prescaler::compute_min_high_res(psc_min)
139 } else {
140 Prescaler::compute_min_low_res(psc_min)
141 };
164 142
165 let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); 143 let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32);
166 let psc_val: u32 = channel_psc.into();
167 144
145 regs.tim(channel).dt().modify(|w| {
146 w.set_dtprsc(psc.into());
147 w.set_dtf(dt_val as u16);
148 w.set_dtr(dt_val as u16);
149 });
150 }
168 151
169 // The dead-time base clock runs 4 times slower than the hrtim base clock 152 // fn enable_outputs(enable: bool);
170 // u9::MAX = 511 153 //
171 let psc_min = (psc_val * dead_time as u32) / (4 * 511); 154 // fn enable_channel(&mut self, channel: usize, enable: bool);
172 let psc = if Self::regs().isr().read().dllrdy() { 155 }
173 Prescaler::compute_min_high_res(psc_min) 156}
174 } else {
175 Prescaler::compute_min_low_res(psc_min)
176 };
177 157
178 let dt_psc_val: u32 = psc.into(); 158pub trait Instance: sealed::Instance + 'static {}
179 let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val);
180 159
181 regs.tim(channel).dt().modify(|w| { 160foreach_interrupt! {
182 w.set_dtprsc(psc.into()); 161 ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => {
183 w.set_dtf(dt_val as u16); 162 impl sealed::Instance for crate::peripherals::$inst {
184 w.set_dtr(dt_val as u16); 163 fn regs() -> crate::pac::hrtim::Hrtim {
185 }); 164 crate::pac::$inst
186 } 165 }
187 } 166 }
188 167
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index 618d85af2..f32dd0f0c 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -339,6 +339,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
339 } 339 }
340} 340}
341 341
342impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
343 fn drop(&mut self) {
344 T::disable();
345 }
346}
347
342impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> { 348impl<'d, T: Instance> embedded_hal_02::blocking::i2c::Read for I2c<'d, T> {
343 type Error = Error; 349 type Error = Error;
344 350
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 4327899bb..36f70e32e 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -838,6 +838,12 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> {
838 } 838 }
839} 839}
840 840
841impl<'d, T: Instance, TXDMA, RXDMA> Drop for I2c<'d, T, TXDMA, RXDMA> {
842 fn drop(&mut self) {
843 T::disable();
844 }
845}
846
841mod eh02 { 847mod eh02 {
842 use super::*; 848 use super::*;
843 849
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index b5a128596..2718c96da 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -90,6 +90,7 @@ pub use crate::_generated::interrupt;
90#[macro_export] 90#[macro_export]
91macro_rules! bind_interrupts { 91macro_rules! bind_interrupts {
92 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { 92 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
93 #[derive(Copy, Clone)]
93 $vis struct $name; 94 $vis struct $name;
94 95
95 $( 96 $(
@@ -119,6 +120,7 @@ pub(crate) use stm32_metapac as pac;
119use crate::interrupt::Priority; 120use crate::interrupt::Priority;
120#[cfg(feature = "rt")] 121#[cfg(feature = "rt")]
121pub use crate::pac::NVIC_PRIO_BITS; 122pub use crate::pac::NVIC_PRIO_BITS;
123use crate::rcc::sealed::RccPeripheral;
122 124
123#[non_exhaustive] 125#[non_exhaustive]
124pub struct Config { 126pub struct Config {
@@ -156,7 +158,7 @@ pub fn init(config: Config) -> Peripherals {
156 #[cfg(dbgmcu)] 158 #[cfg(dbgmcu)]
157 if config.enable_debug_during_sleep { 159 if config.enable_debug_during_sleep {
158 crate::pac::DBGMCU.cr().modify(|cr| { 160 crate::pac::DBGMCU.cr().modify(|cr| {
159 #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5))] 161 #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u5, dbgmcu_wba))]
160 { 162 {
161 cr.set_dbg_stop(true); 163 cr.set_dbg_stop(true);
162 cr.set_dbg_standby(true); 164 cr.set_dbg_standby(true);
@@ -181,6 +183,13 @@ pub fn init(config: Config) -> Peripherals {
181 }); 183 });
182 } 184 }
183 185
186 #[cfg(not(any(stm32f1, stm32wb, stm32wl)))]
187 peripherals::SYSCFG::enable();
188 #[cfg(not(any(stm32h5, stm32h7, stm32wb, stm32wl)))]
189 peripherals::PWR::enable();
190 #[cfg(not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7)))]
191 peripherals::FLASH::enable();
192
184 unsafe { 193 unsafe {
185 gpio::init(); 194 gpio::init();
186 dma::init( 195 dma::init(
@@ -199,6 +208,11 @@ pub fn init(config: Config) -> Peripherals {
199 // must be after rcc init 208 // must be after rcc init
200 #[cfg(feature = "_time-driver")] 209 #[cfg(feature = "_time-driver")]
201 time_driver::init(); 210 time_driver::init();
211
212 #[cfg(feature = "low-power")]
213 while !crate::rcc::low_power_ready() {
214 crate::rcc::clock_refcount_sub();
215 }
202 } 216 }
203 217
204 p 218 p
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 7814fa384..ce8afb578 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -3,45 +3,33 @@ use core::marker::PhantomData;
3 3
4use cortex_m::peripheral::SCB; 4use cortex_m::peripheral::SCB;
5use embassy_executor::*; 5use embassy_executor::*;
6use embassy_time::Duration;
7 6
8use crate::interrupt; 7use crate::interrupt;
9use crate::interrupt::typelevel::Interrupt;
10use crate::pac::EXTI;
11use crate::rcc::low_power_ready; 8use crate::rcc::low_power_ready;
9use crate::time_driver::{get_driver, RtcDriver};
12 10
13const THREAD_PENDER: usize = usize::MAX; 11const THREAD_PENDER: usize = usize::MAX;
14const THRESHOLD: Duration = Duration::from_millis(500);
15 12
16use crate::rtc::{Rtc, RtcInstant}; 13use crate::rtc::Rtc;
17 14
18static mut RTC: Option<&'static Rtc> = None; 15static mut EXECUTOR: Option<Executor> = None;
19 16
20foreach_interrupt! { 17foreach_interrupt! {
21 (RTC, rtc, $block:ident, WKUP, $irq:ident) => { 18 (RTC, rtc, $block:ident, WKUP, $irq:ident) => {
22 #[interrupt] 19 #[interrupt]
23 unsafe fn $irq() { 20 unsafe fn $irq() {
24 Executor::on_wakeup_irq(); 21 EXECUTOR.as_mut().unwrap().on_wakeup_irq();
25 } 22 }
26 }; 23 };
27} 24}
28 25
29pub fn stop_with_rtc(rtc: &'static Rtc) { 26#[allow(dead_code)]
30 crate::interrupt::typelevel::RTC_WKUP::unpend(); 27pub(crate) unsafe fn on_wakeup_irq() {
31 unsafe { crate::interrupt::typelevel::RTC_WKUP::enable() }; 28 EXECUTOR.as_mut().unwrap().on_wakeup_irq();
32
33 EXTI.rtsr(0).modify(|w| w.set_line(22, true));
34 EXTI.imr(0).modify(|w| w.set_line(22, true));
35
36 unsafe { RTC = Some(rtc) };
37} 29}
38 30
39pub fn start_wakeup_alarm(requested_duration: embassy_time::Duration) -> RtcInstant { 31pub fn stop_with_rtc(rtc: &'static Rtc) {
40 unsafe { RTC }.unwrap().start_wakeup_alarm(requested_duration) 32 unsafe { EXECUTOR.as_mut().unwrap() }.stop_with_rtc(rtc)
41}
42
43pub fn stop_wakeup_alarm() -> RtcInstant {
44 unsafe { RTC }.unwrap().stop_wakeup_alarm()
45} 33}
46 34
47/// Thread mode executor, using WFE/SEV. 35/// Thread mode executor, using WFE/SEV.
@@ -57,54 +45,58 @@ pub fn stop_wakeup_alarm() -> RtcInstant {
57pub struct Executor { 45pub struct Executor {
58 inner: raw::Executor, 46 inner: raw::Executor,
59 not_send: PhantomData<*mut ()>, 47 not_send: PhantomData<*mut ()>,
48 scb: SCB,
49 time_driver: &'static RtcDriver,
60} 50}
61 51
62impl Executor { 52impl Executor {
63 /// Create a new Executor. 53 /// Create a new Executor.
64 pub fn new() -> Self { 54 pub fn take() -> &'static mut Self {
65 Self { 55 unsafe {
66 inner: raw::Executor::new(THREAD_PENDER as *mut ()), 56 assert!(EXECUTOR.is_none());
67 not_send: PhantomData, 57
58 EXECUTOR = Some(Self {
59 inner: raw::Executor::new(THREAD_PENDER as *mut ()),
60 not_send: PhantomData,
61 scb: cortex_m::Peripherals::steal().SCB,
62 time_driver: get_driver(),
63 });
64
65 EXECUTOR.as_mut().unwrap()
68 } 66 }
69 } 67 }
70 68
71 unsafe fn on_wakeup_irq() { 69 unsafe fn on_wakeup_irq(&mut self) {
72 info!("on wakeup irq"); 70 trace!("low power: on wakeup irq");
73 71
74 cortex_m::asm::bkpt(); 72 self.time_driver.resume_time();
73 trace!("low power: resume time");
75 } 74 }
76 75
77 fn time_until_next_alarm(&self) -> Duration { 76 pub(self) fn stop_with_rtc(&mut self, rtc: &'static Rtc) {
78 Duration::from_secs(3) 77 self.time_driver.set_rtc(rtc);
79 } 78
79 rtc.enable_wakeup_line();
80 80
81 fn get_scb() -> SCB { 81 trace!("low power: stop with rtc configured");
82 unsafe { cortex_m::Peripherals::steal() }.SCB
83 } 82 }
84 83
85 fn configure_pwr(&self) { 84 fn configure_pwr(&mut self) {
86 trace!("configure_pwr"); 85 trace!("low power: configure_pwr");
87 86
87 self.scb.clear_sleepdeep();
88 if !low_power_ready() { 88 if !low_power_ready() {
89 trace!("low power: configure_pwr: low power not ready");
89 return; 90 return;
90 } 91 }
91 92
92 let time_until_next_alarm = self.time_until_next_alarm(); 93 if self.time_driver.pause_time().is_err() {
93 if time_until_next_alarm < THRESHOLD { 94 trace!("low power: configure_pwr: time driver failed to pause");
94 return; 95 return;
95 } 96 }
96 97
97 trace!("low power stop required"); 98 trace!("low power: enter stop...");
98 99 self.scb.set_sleepdeep();
99 critical_section::with(|_| {
100 trace!("executor: set wakeup alarm...");
101
102 start_wakeup_alarm(time_until_next_alarm);
103
104 trace!("low power wait for rtc ready...");
105
106 Self::get_scb().set_sleepdeep();
107 });
108 } 100 }
109 101
110 /// Run the executor. 102 /// Run the executor.
@@ -126,11 +118,11 @@ impl Executor {
126 /// 118 ///
127 /// This function never returns. 119 /// This function never returns.
128 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! { 120 pub fn run(&'static mut self, init: impl FnOnce(Spawner)) -> ! {
129 init(self.inner.spawner()); 121 init(unsafe { EXECUTOR.as_mut().unwrap() }.inner.spawner());
130 122
131 loop { 123 loop {
132 unsafe { 124 unsafe {
133 self.inner.poll(); 125 EXECUTOR.as_mut().unwrap().inner.poll();
134 self.configure_pwr(); 126 self.configure_pwr();
135 asm!("wfe"); 127 asm!("wfe");
136 }; 128 };
diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs
new file mode 100644
index 000000000..de27130f2
--- /dev/null
+++ b/embassy-stm32/src/rcc/bd.rs
@@ -0,0 +1,176 @@
1#[allow(dead_code)]
2#[derive(Default, Clone, Copy)]
3pub enum LseDrive {
4 #[cfg(any(rtc_v2f7, rtc_v2l4))]
5 Low = 0,
6 MediumLow = 0x01,
7 #[default]
8 MediumHigh = 0x02,
9 #[cfg(any(rtc_v2f7, rtc_v2l4))]
10 High = 0x03,
11}
12
13#[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))]
14impl From<LseDrive> for crate::pac::rcc::vals::Lsedrv {
15 fn from(value: LseDrive) -> Self {
16 use crate::pac::rcc::vals::Lsedrv;
17
18 match value {
19 #[cfg(any(rtc_v2f7, rtc_v2l4))]
20 LseDrive::Low => Lsedrv::LOW,
21 LseDrive::MediumLow => Lsedrv::MEDIUMLOW,
22 LseDrive::MediumHigh => Lsedrv::MEDIUMHIGH,
23 #[cfg(any(rtc_v2f7, rtc_v2l4))]
24 LseDrive::High => Lsedrv::HIGH,
25 }
26 }
27}
28
29pub use crate::pac::rcc::vals::Rtcsel as RtcClockSource;
30
31#[cfg(not(any(rtc_v2l0, rtc_v2l1, stm32c0)))]
32#[allow(dead_code)]
33type Bdcr = crate::pac::rcc::regs::Bdcr;
34
35#[cfg(any(rtc_v2l0, rtc_v2l1))]
36#[allow(dead_code)]
37type Bdcr = crate::pac::rcc::regs::Csr;
38
39#[allow(dead_code)]
40pub struct BackupDomain {}
41
42impl BackupDomain {
43 #[cfg(any(
44 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3,
45 rtc_v3u5
46 ))]
47 #[allow(dead_code, unused_variables)]
48 fn modify<R>(f: impl FnOnce(&mut Bdcr) -> R) -> R {
49 #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1, rtc_v2l0))]
50 let cr = crate::pac::PWR.cr();
51 #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
52 let cr = crate::pac::PWR.cr1();
53
54 // TODO: Missing from PAC for l0 and f0?
55 #[cfg(not(any(rtc_v2f0, rtc_v3u5)))]
56 {
57 cr.modify(|w| w.set_dbp(true));
58 while !cr.read().dbp() {}
59 }
60
61 #[cfg(any(rtc_v2l0, rtc_v2l1))]
62 let cr = crate::pac::RCC.csr();
63
64 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
65 let cr = crate::pac::RCC.bdcr();
66
67 cr.modify(|w| f(w))
68 }
69
70 #[cfg(any(
71 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3,
72 rtc_v3u5
73 ))]
74 #[allow(dead_code)]
75 fn read() -> Bdcr {
76 #[cfg(any(rtc_v2l0, rtc_v2l1))]
77 let r = crate::pac::RCC.csr().read();
78
79 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
80 let r = crate::pac::RCC.bdcr().read();
81
82 r
83 }
84
85 #[cfg(any(
86 rtc_v2f0, rtc_v2f2, rtc_v2f3, rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l1, rtc_v2l4, rtc_v2wb, rtc_v3,
87 rtc_v3u5
88 ))]
89 #[allow(dead_code, unused_variables)]
90 pub fn configure_ls(clock_source: RtcClockSource, lsi: bool, lse: Option<LseDrive>) {
91 if lsi {
92 #[cfg(rtc_v3u5)]
93 let csr = crate::pac::RCC.bdcr();
94
95 #[cfg(not(rtc_v3u5))]
96 let csr = crate::pac::RCC.csr();
97
98 // Disable backup domain write protection
99 Self::modify(|_| {});
100
101 #[cfg(not(any(rcc_wb, rcc_wba)))]
102 csr.modify(|w| w.set_lsion(true));
103
104 #[cfg(any(rcc_wb, rcc_wba))]
105 csr.modify(|w| w.set_lsi1on(true));
106
107 #[cfg(not(any(rcc_wb, rcc_wba)))]
108 while !csr.read().lsirdy() {}
109
110 #[cfg(any(rcc_wb, rcc_wba))]
111 while !csr.read().lsi1rdy() {}
112 }
113
114 if let Some(lse_drive) = lse {
115 Self::modify(|w| {
116 #[cfg(any(rtc_v2f7, rtc_v2h7, rtc_v2l0, rtc_v2l4))]
117 w.set_lsedrv(lse_drive.into());
118 w.set_lseon(true);
119 });
120
121 while !Self::read().lserdy() {}
122 }
123
124 match clock_source {
125 RtcClockSource::LSI => assert!(lsi),
126 RtcClockSource::LSE => assert!(&lse.is_some()),
127 _ => {}
128 };
129
130 if clock_source == RtcClockSource::NOCLOCK {
131 // disable it
132 Self::modify(|w| {
133 #[cfg(not(rcc_wba))]
134 w.set_rtcen(false);
135 w.set_rtcsel(clock_source);
136 });
137 } else {
138 // check if it's already enabled and in the source we want.
139 let reg = Self::read();
140 let ok = reg.rtcsel() == clock_source;
141 #[cfg(not(rcc_wba))]
142 let ok = ok & reg.rtcen();
143
144 // if not, configure it.
145 if !ok {
146 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
147 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
148
149 #[cfg(not(any(rcc_l0, rcc_l1)))]
150 Self::modify(|w| w.set_bdrst(true));
151
152 Self::modify(|w| {
153 // Reset
154 #[cfg(not(any(rcc_l0, rcc_l1)))]
155 w.set_bdrst(false);
156
157 #[cfg(not(rcc_wba))]
158 w.set_rtcen(true);
159 w.set_rtcsel(clock_source);
160
161 // Restore bcdr
162 #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
163 w.set_lscosel(reg.lscosel());
164 #[cfg(any(rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
165 w.set_lscoen(reg.lscoen());
166
167 w.set_lseon(reg.lseon());
168
169 #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb, rtc_v3, rtc_v3u5))]
170 w.set_lsedrv(reg.lsedrv());
171 w.set_lsebyp(reg.lsebyp());
172 });
173 }
174 }
175 }
176}
diff --git a/embassy-stm32/src/rcc/bus.rs b/embassy-stm32/src/rcc/bus.rs
new file mode 100644
index 000000000..495cf7fe1
--- /dev/null
+++ b/embassy-stm32/src/rcc/bus.rs
@@ -0,0 +1,56 @@
1use core::ops::Div;
2
3#[allow(unused_imports)]
4use crate::pac::rcc;
5pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
6use crate::time::Hertz;
7
8impl Div<AHBPrescaler> for Hertz {
9 type Output = Hertz;
10
11 fn div(self, rhs: AHBPrescaler) -> Self::Output {
12 let divisor = match rhs {
13 AHBPrescaler::DIV1 => 1,
14 AHBPrescaler::DIV2 => 2,
15 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
16 AHBPrescaler::DIV3 => 3,
17 AHBPrescaler::DIV4 => 4,
18 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
19 AHBPrescaler::DIV5 => 5,
20 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
21 AHBPrescaler::DIV6 => 6,
22 AHBPrescaler::DIV8 => 8,
23 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
24 AHBPrescaler::DIV10 => 10,
25 AHBPrescaler::DIV16 => 16,
26 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
27 AHBPrescaler::DIV32 => 32,
28 #[cfg(not(rcc_wba))]
29 AHBPrescaler::DIV64 => 64,
30 #[cfg(not(rcc_wba))]
31 AHBPrescaler::DIV128 => 128,
32 #[cfg(not(rcc_wba))]
33 AHBPrescaler::DIV256 => 256,
34 #[cfg(not(rcc_wba))]
35 AHBPrescaler::DIV512 => 512,
36 _ => unreachable!(),
37 };
38 Hertz(self.0 / divisor)
39 }
40}
41
42impl Div<APBPrescaler> for Hertz {
43 type Output = Hertz;
44
45 fn div(self, rhs: APBPrescaler) -> Self::Output {
46 let divisor = match rhs {
47 APBPrescaler::DIV1 => 1,
48 APBPrescaler::DIV2 => 2,
49 APBPrescaler::DIV4 => 4,
50 APBPrescaler::DIV8 => 8,
51 APBPrescaler::DIV16 => 16,
52 _ => unreachable!(),
53 };
54 Hertz(self.0 / divisor)
55 }
56}
diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs
index 6a9326347..8f45e7c0f 100644
--- a/embassy-stm32/src/rcc/c0.rs
+++ b/embassy-stm32/src/rcc/c0.rs
@@ -1,4 +1,4 @@
1pub use super::common::{AHBPrescaler, APBPrescaler}; 1pub use super::bus::{AHBPrescaler, APBPrescaler};
2use crate::pac::flash::vals::Latency; 2use crate::pac::flash::vals::Latency;
3use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; 3use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw};
4use crate::pac::{FLASH, RCC}; 4use crate::pac::{FLASH, RCC};
@@ -58,8 +58,8 @@ impl Default for Config {
58 fn default() -> Config { 58 fn default() -> Config {
59 Config { 59 Config {
60 mux: ClockSrc::HSI(HSIPrescaler::NotDivided), 60 mux: ClockSrc::HSI(HSIPrescaler::NotDivided),
61 ahb_pre: AHBPrescaler::NotDivided, 61 ahb_pre: AHBPrescaler::DIV1,
62 apb_pre: APBPrescaler::NotDivided, 62 apb_pre: APBPrescaler::DIV1,
63 } 63 }
64 } 64 }
65} 65}
@@ -151,20 +151,21 @@ pub(crate) unsafe fn init(config: Config) {
151 } 151 }
152 152
153 let ahb_div = match config.ahb_pre { 153 let ahb_div = match config.ahb_pre {
154 AHBPrescaler::NotDivided => 1, 154 AHBPrescaler::DIV1 => 1,
155 AHBPrescaler::Div2 => 2, 155 AHBPrescaler::DIV2 => 2,
156 AHBPrescaler::Div4 => 4, 156 AHBPrescaler::DIV4 => 4,
157 AHBPrescaler::Div8 => 8, 157 AHBPrescaler::DIV8 => 8,
158 AHBPrescaler::Div16 => 16, 158 AHBPrescaler::DIV16 => 16,
159 AHBPrescaler::Div64 => 64, 159 AHBPrescaler::DIV64 => 64,
160 AHBPrescaler::Div128 => 128, 160 AHBPrescaler::DIV128 => 128,
161 AHBPrescaler::Div256 => 256, 161 AHBPrescaler::DIV256 => 256,
162 AHBPrescaler::Div512 => 512, 162 AHBPrescaler::DIV512 => 512,
163 _ => unreachable!(),
163 }; 164 };
164 let ahb_freq = sys_clk / ahb_div; 165 let ahb_freq = sys_clk / ahb_div;
165 166
166 let (apb_freq, apb_tim_freq) = match config.apb_pre { 167 let (apb_freq, apb_tim_freq) = match config.apb_pre {
167 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 168 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
168 pre => { 169 pre => {
169 let pre: Ppre = pre.into(); 170 let pre: Ppre = pre.into();
170 let pre: u8 = 1 << (pre.to_bits() - 3); 171 let pre: u8 = 1 << (pre.to_bits() - 3);
diff --git a/embassy-stm32/src/rcc/common.rs b/embassy-stm32/src/rcc/common.rs
deleted file mode 100644
index 62736a43a..000000000
--- a/embassy-stm32/src/rcc/common.rs
+++ /dev/null
@@ -1,174 +0,0 @@
1use core::ops::Div;
2
3#[allow(unused_imports)]
4use crate::pac::rcc;
5use crate::time::Hertz;
6
7/// Voltage Scale
8///
9/// Represents the voltage range feeding the CPU core. The maximum core
10/// clock frequency depends on this value.
11///
12/// Scale0 represents the highest voltage range
13#[derive(Copy, Clone, PartialEq)]
14pub enum VoltageScale {
15 Scale0,
16 Scale1,
17 #[cfg(not(any(rcc_wl5, rcc_wle)))]
18 Scale2,
19 #[cfg(not(any(rcc_wl5, rcc_wle)))]
20 Scale3,
21}
22
23/// AHB prescaler
24#[derive(Clone, Copy, PartialEq)]
25pub enum AHBPrescaler {
26 NotDivided,
27 Div2,
28 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
29 Div3,
30 Div4,
31 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
32 Div5,
33 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
34 Div6,
35 Div8,
36 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
37 Div10,
38 Div16,
39 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
40 Div32,
41 Div64,
42 Div128,
43 Div256,
44 Div512,
45}
46
47impl Div<AHBPrescaler> for Hertz {
48 type Output = Hertz;
49
50 fn div(self, rhs: AHBPrescaler) -> Self::Output {
51 let divisor = match rhs {
52 AHBPrescaler::NotDivided => 1,
53 AHBPrescaler::Div2 => 2,
54 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
55 AHBPrescaler::Div3 => 3,
56 AHBPrescaler::Div4 => 4,
57 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
58 AHBPrescaler::Div5 => 5,
59 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
60 AHBPrescaler::Div6 => 6,
61 AHBPrescaler::Div8 => 8,
62 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
63 AHBPrescaler::Div10 => 10,
64 AHBPrescaler::Div16 => 16,
65 #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
66 AHBPrescaler::Div32 => 32,
67 AHBPrescaler::Div64 => 64,
68 AHBPrescaler::Div128 => 128,
69 AHBPrescaler::Div256 => 256,
70 AHBPrescaler::Div512 => 512,
71 };
72 Hertz(self.0 / divisor)
73 }
74}
75
76#[cfg(not(any(rcc_g4, rcc_wb, rcc_wl5, rcc_wle)))]
77impl From<AHBPrescaler> for rcc::vals::Hpre {
78 fn from(val: AHBPrescaler) -> rcc::vals::Hpre {
79 use rcc::vals::Hpre;
80
81 match val {
82 #[cfg(not(rcc_u5))]
83 AHBPrescaler::NotDivided => Hpre::DIV1,
84 #[cfg(rcc_u5)]
85 AHBPrescaler::NotDivided => Hpre::NONE,
86 AHBPrescaler::Div2 => Hpre::DIV2,
87 AHBPrescaler::Div4 => Hpre::DIV4,
88 AHBPrescaler::Div8 => Hpre::DIV8,
89 AHBPrescaler::Div16 => Hpre::DIV16,
90 AHBPrescaler::Div64 => Hpre::DIV64,
91 AHBPrescaler::Div128 => Hpre::DIV128,
92 AHBPrescaler::Div256 => Hpre::DIV256,
93 AHBPrescaler::Div512 => Hpre::DIV512,
94 }
95 }
96}
97
98#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
99impl From<AHBPrescaler> for u8 {
100 fn from(val: AHBPrescaler) -> u8 {
101 match val {
102 AHBPrescaler::NotDivided => 0x0,
103 AHBPrescaler::Div2 => 0x08,
104 AHBPrescaler::Div3 => 0x01,
105 AHBPrescaler::Div4 => 0x09,
106 AHBPrescaler::Div5 => 0x02,
107 AHBPrescaler::Div6 => 0x05,
108 AHBPrescaler::Div8 => 0x0a,
109 AHBPrescaler::Div10 => 0x06,
110 AHBPrescaler::Div16 => 0x0b,
111 AHBPrescaler::Div32 => 0x07,
112 AHBPrescaler::Div64 => 0x0c,
113 AHBPrescaler::Div128 => 0x0d,
114 AHBPrescaler::Div256 => 0x0e,
115 AHBPrescaler::Div512 => 0x0f,
116 }
117 }
118}
119
120/// APB prescaler
121#[derive(Clone, Copy)]
122pub enum APBPrescaler {
123 NotDivided,
124 Div2,
125 Div4,
126 Div8,
127 Div16,
128}
129
130impl Div<APBPrescaler> for Hertz {
131 type Output = Hertz;
132
133 fn div(self, rhs: APBPrescaler) -> Self::Output {
134 let divisor = match rhs {
135 APBPrescaler::NotDivided => 1,
136 APBPrescaler::Div2 => 2,
137 APBPrescaler::Div4 => 4,
138 APBPrescaler::Div8 => 8,
139 APBPrescaler::Div16 => 16,
140 };
141 Hertz(self.0 / divisor)
142 }
143}
144
145#[cfg(not(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_g4, rcc_h7, rcc_h7ab, rcc_wb, rcc_wl5, rcc_wle)))]
146impl From<APBPrescaler> for rcc::vals::Ppre {
147 fn from(val: APBPrescaler) -> rcc::vals::Ppre {
148 use rcc::vals::Ppre;
149
150 match val {
151 #[cfg(not(rcc_u5))]
152 APBPrescaler::NotDivided => Ppre::DIV1,
153 #[cfg(rcc_u5)]
154 APBPrescaler::NotDivided => Ppre::NONE,
155 APBPrescaler::Div2 => Ppre::DIV2,
156 APBPrescaler::Div4 => Ppre::DIV4,
157 APBPrescaler::Div8 => Ppre::DIV8,
158 APBPrescaler::Div16 => Ppre::DIV16,
159 }
160 }
161}
162
163#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))]
164impl From<APBPrescaler> for u8 {
165 fn from(val: APBPrescaler) -> u8 {
166 match val {
167 APBPrescaler::NotDivided => 1,
168 APBPrescaler::Div2 => 0x04,
169 APBPrescaler::Div4 => 0x05,
170 APBPrescaler::Div8 => 0x06,
171 APBPrescaler::Div16 => 0x07,
172 }
173 }
174}
diff --git a/embassy-stm32/src/rcc/f1.rs b/embassy-stm32/src/rcc/f1.rs
index b6200231e..081c0c767 100644
--- a/embassy-stm32/src/rcc/f1.rs
+++ b/embassy-stm32/src/rcc/f1.rs
@@ -163,8 +163,8 @@ pub(crate) unsafe fn init(config: Config) {
163 // Only needed for stm32f103? 163 // Only needed for stm32f103?
164 RCC.cfgr().modify(|w| { 164 RCC.cfgr().modify(|w| {
165 w.set_adcpre(Adcpre::from_bits(apre_bits)); 165 w.set_adcpre(Adcpre::from_bits(apre_bits));
166 w.set_ppre2(Ppre1::from_bits(ppre2_bits)); 166 w.set_ppre2(Ppre::from_bits(ppre2_bits));
167 w.set_ppre1(Ppre1::from_bits(ppre1_bits)); 167 w.set_ppre1(Ppre::from_bits(ppre1_bits));
168 w.set_hpre(Hpre::from_bits(hpre_bits)); 168 w.set_hpre(Hpre::from_bits(hpre_bits));
169 #[cfg(not(rcc_f100))] 169 #[cfg(not(rcc_f100))]
170 w.set_usbpre(Usbpre::from_bits(usbpre as u8)); 170 w.set_usbpre(Usbpre::from_bits(usbpre as u8));
@@ -184,6 +184,6 @@ pub(crate) unsafe fn init(config: Config) {
184 apb1_tim: Hertz(pclk1 * timer_mul1), 184 apb1_tim: Hertz(pclk1 * timer_mul1),
185 apb2_tim: Hertz(pclk2 * timer_mul2), 185 apb2_tim: Hertz(pclk2 * timer_mul2),
186 ahb1: Hertz(hclk), 186 ahb1: Hertz(hclk),
187 adc: Hertz(adcclk), 187 adc: Some(Hertz(adcclk)),
188 }); 188 });
189} 189}
diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs
index ec4ed99b8..44de5bf19 100644
--- a/embassy-stm32/src/rcc/f2.rs
+++ b/embassy-stm32/src/rcc/f2.rs
@@ -1,11 +1,13 @@
1use core::convert::TryFrom; 1use core::convert::TryFrom;
2use core::ops::{Div, Mul}; 2use core::ops::{Div, Mul};
3 3
4pub use super::common::{AHBPrescaler, APBPrescaler}; 4pub use super::bus::{AHBPrescaler, APBPrescaler};
5use crate::pac::flash::vals::Latency; 5use crate::pac::flash::vals::Latency;
6use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw}; 6use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw};
7use crate::pac::{FLASH, RCC}; 7use crate::pac::{FLASH, RCC};
8use crate::rcc::bd::BackupDomain;
8use crate::rcc::{set_freqs, Clocks}; 9use crate::rcc::{set_freqs, Clocks};
10use crate::rtc::RtcClockSource;
9use crate::time::Hertz; 11use crate::time::Hertz;
10 12
11/// HSI speed 13/// HSI speed
@@ -201,7 +203,20 @@ pub struct PLLClocks {
201 pub pll48_freq: Hertz, 203 pub pll48_freq: Hertz,
202} 204}
203 205
204pub use super::common::VoltageScale; 206/// Voltage range of the power supply used.
207///
208/// Used to calculate flash waitstates. See
209/// RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock frequency
210pub enum VoltageScale {
211 /// 2.7 to 3.6 V
212 Range0,
213 /// 2.4 to 2.7 V
214 Range1,
215 /// 2.1 to 2.4 V
216 Range2,
217 /// 1.8 to 2.1 V
218 Range3,
219}
205 220
206impl VoltageScale { 221impl VoltageScale {
207 const fn wait_states(&self, ahb_freq: Hertz) -> Option<Latency> { 222 const fn wait_states(&self, ahb_freq: Hertz) -> Option<Latency> {
@@ -209,7 +224,7 @@ impl VoltageScale {
209 // Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock 224 // Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock
210 // frequency 225 // frequency
211 match self { 226 match self {
212 VoltageScale::Scale3 => { 227 VoltageScale::Range3 => {
213 if ahb_freq <= 16_000_000 { 228 if ahb_freq <= 16_000_000 {
214 Some(Latency::WS0) 229 Some(Latency::WS0)
215 } else if ahb_freq <= 32_000_000 { 230 } else if ahb_freq <= 32_000_000 {
@@ -230,7 +245,7 @@ impl VoltageScale {
230 None 245 None
231 } 246 }
232 } 247 }
233 VoltageScale::Scale2 => { 248 VoltageScale::Range2 => {
234 if ahb_freq <= 18_000_000 { 249 if ahb_freq <= 18_000_000 {
235 Some(Latency::WS0) 250 Some(Latency::WS0)
236 } else if ahb_freq <= 36_000_000 { 251 } else if ahb_freq <= 36_000_000 {
@@ -249,7 +264,7 @@ impl VoltageScale {
249 None 264 None
250 } 265 }
251 } 266 }
252 VoltageScale::Scale1 => { 267 VoltageScale::Range1 => {
253 if ahb_freq <= 24_000_000 { 268 if ahb_freq <= 24_000_000 {
254 Some(Latency::WS0) 269 Some(Latency::WS0)
255 } else if ahb_freq <= 48_000_000 { 270 } else if ahb_freq <= 48_000_000 {
@@ -264,7 +279,7 @@ impl VoltageScale {
264 None 279 None
265 } 280 }
266 } 281 }
267 VoltageScale::Scale0 => { 282 VoltageScale::Range0 => {
268 if ahb_freq <= 30_000_000 { 283 if ahb_freq <= 30_000_000 {
269 Some(Latency::WS0) 284 Some(Latency::WS0)
270 } else if ahb_freq <= 60_000_000 { 285 } else if ahb_freq <= 60_000_000 {
@@ -288,6 +303,9 @@ pub struct Config {
288 pub pll_mux: PLLSrc, 303 pub pll_mux: PLLSrc,
289 pub pll: PLLConfig, 304 pub pll: PLLConfig,
290 pub mux: ClockSrc, 305 pub mux: ClockSrc,
306 pub rtc: Option<RtcClockSource>,
307 pub lsi: bool,
308 pub lse: Option<Hertz>,
291 pub voltage: VoltageScale, 309 pub voltage: VoltageScale,
292 pub ahb_pre: AHBPrescaler, 310 pub ahb_pre: AHBPrescaler,
293 pub apb1_pre: APBPrescaler, 311 pub apb1_pre: APBPrescaler,
@@ -302,11 +320,14 @@ impl Default for Config {
302 hsi: true, 320 hsi: true,
303 pll_mux: PLLSrc::HSI, 321 pll_mux: PLLSrc::HSI,
304 pll: PLLConfig::default(), 322 pll: PLLConfig::default(),
305 voltage: VoltageScale::Scale3, 323 voltage: VoltageScale::Range3,
306 mux: ClockSrc::HSI, 324 mux: ClockSrc::HSI,
307 ahb_pre: AHBPrescaler::NotDivided, 325 rtc: None,
308 apb1_pre: APBPrescaler::NotDivided, 326 lsi: false,
309 apb2_pre: APBPrescaler::NotDivided, 327 lse: None,
328 ahb_pre: AHBPrescaler::DIV1,
329 apb1_pre: APBPrescaler::DIV1,
330 apb2_pre: APBPrescaler::DIV1,
310 } 331 }
311 } 332 }
312} 333}
@@ -379,7 +400,7 @@ pub(crate) unsafe fn init(config: Config) {
379 assert!(ahb_freq <= Hertz(120_000_000)); 400 assert!(ahb_freq <= Hertz(120_000_000));
380 401
381 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 402 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
382 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 403 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
383 pre => { 404 pre => {
384 let freq = ahb_freq / pre; 405 let freq = ahb_freq / pre;
385 (freq, Hertz(freq.0 * 2)) 406 (freq, Hertz(freq.0 * 2))
@@ -389,7 +410,7 @@ pub(crate) unsafe fn init(config: Config) {
389 assert!(apb1_freq <= Hertz(30_000_000)); 410 assert!(apb1_freq <= Hertz(30_000_000));
390 411
391 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 412 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
392 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 413 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
393 pre => { 414 pre => {
394 let freq = ahb_freq / pre; 415 let freq = ahb_freq / pre;
395 (freq, Hertz(freq.0 * 2)) 416 (freq, Hertz(freq.0 * 2))
@@ -414,6 +435,12 @@ pub(crate) unsafe fn init(config: Config) {
414 RCC.cr().modify(|w| w.set_hsion(false)); 435 RCC.cr().modify(|w| w.set_hsion(false));
415 } 436 }
416 437
438 BackupDomain::configure_ls(
439 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
440 config.lsi,
441 config.lse.map(|_| Default::default()),
442 );
443
417 set_freqs(Clocks { 444 set_freqs(Clocks {
418 sys: sys_clk, 445 sys: sys_clk,
419 ahb1: ahb_freq, 446 ahb1: ahb_freq,
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index 321270a70..630dbd4fe 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -1,5 +1,7 @@
1#[cfg(rcc_f3)]
2use crate::pac::adccommon::vals::Ckmode;
1use crate::pac::flash::vals::Latency; 3use crate::pac::flash::vals::Latency;
2use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}; 4use crate::pac::rcc::vals::{Adcpres, Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
3use crate::pac::{FLASH, RCC}; 5use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks}; 6use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz; 7use crate::time::Hertz;
@@ -10,6 +12,82 @@ pub const HSI_FREQ: Hertz = Hertz(8_000_000);
10/// LSI speed 12/// LSI speed
11pub const LSI_FREQ: Hertz = Hertz(40_000); 13pub const LSI_FREQ: Hertz = Hertz(40_000);
12 14
15impl From<AdcClockSource> for Adcpres {
16 fn from(value: AdcClockSource) -> Self {
17 match value {
18 AdcClockSource::PllDiv1 => Adcpres::DIV1,
19 AdcClockSource::PllDiv2 => Adcpres::DIV2,
20 AdcClockSource::PllDiv4 => Adcpres::DIV4,
21 AdcClockSource::PllDiv6 => Adcpres::DIV6,
22 AdcClockSource::PllDiv8 => Adcpres::DIV8,
23 AdcClockSource::PllDiv12 => Adcpres::DIV12,
24 AdcClockSource::PllDiv16 => Adcpres::DIV16,
25 AdcClockSource::PllDiv32 => Adcpres::DIV32,
26 AdcClockSource::PllDiv64 => Adcpres::DIV64,
27 AdcClockSource::PllDiv128 => Adcpres::DIV128,
28 AdcClockSource::PllDiv256 => Adcpres::DIV256,
29 _ => unreachable!(),
30 }
31 }
32}
33
34#[cfg(rcc_f3)]
35impl From<AdcClockSource> for Ckmode {
36 fn from(value: AdcClockSource) -> Self {
37 match value {
38 AdcClockSource::BusDiv1 => Ckmode::SYNCDIV1,
39 AdcClockSource::BusDiv2 => Ckmode::SYNCDIV2,
40 AdcClockSource::BusDiv4 => Ckmode::SYNCDIV4,
41 _ => unreachable!(),
42 }
43 }
44}
45
46#[derive(Clone, Copy)]
47pub enum AdcClockSource {
48 PllDiv1 = 1,
49 PllDiv2 = 2,
50 PllDiv4 = 4,
51 PllDiv6 = 6,
52 PllDiv8 = 8,
53 PllDiv12 = 12,
54 PllDiv16 = 16,
55 PllDiv32 = 32,
56 PllDiv64 = 64,
57 PllDiv128 = 128,
58 PllDiv256 = 256,
59 BusDiv1,
60 BusDiv2,
61 BusDiv4,
62}
63
64impl AdcClockSource {
65 pub fn is_bus(&self) -> bool {
66 match self {
67 Self::BusDiv1 => true,
68 Self::BusDiv2 => true,
69 Self::BusDiv4 => true,
70 _ => false,
71 }
72 }
73
74 pub fn bus_div(&self) -> u32 {
75 match self {
76 Self::BusDiv1 => 1,
77 Self::BusDiv2 => 2,
78 Self::BusDiv4 => 4,
79 _ => unreachable!(),
80 }
81 }
82}
83
84#[derive(Default)]
85pub enum HrtimClockSource {
86 #[default]
87 BusClk,
88 PllClk,
89}
90
13/// Clocks configutation 91/// Clocks configutation
14#[non_exhaustive] 92#[non_exhaustive]
15#[derive(Default)] 93#[derive(Default)]
@@ -36,9 +114,20 @@ pub struct Config {
36 /// - The System clock frequency is either 48MHz or 72MHz 114 /// - The System clock frequency is either 48MHz or 72MHz
37 /// - APB1 clock has a minimum frequency of 10MHz 115 /// - APB1 clock has a minimum frequency of 10MHz
38 pub pll48: bool, 116 pub pll48: bool,
117 #[cfg(rcc_f3)]
118 /// ADC clock setup
119 /// - For AHB, a psc of 4 or less must be used
120 pub adc: Option<AdcClockSource>,
121 #[cfg(rcc_f3)]
122 /// ADC clock setup
123 /// - For AHB, a psc of 4 or less must be used
124 pub adc34: Option<AdcClockSource>,
125 #[cfg(stm32f334)]
126 pub hrtim: HrtimClockSource,
39} 127}
40 128
41// Information required to setup the PLL clock 129// Information required to setup the PLL clock
130#[derive(Clone, Copy)]
42struct PllConfig { 131struct PllConfig {
43 pll_src: Pllsrc, 132 pll_src: Pllsrc,
44 pll_mul: Pllmul, 133 pll_mul: Pllmul,
@@ -170,6 +259,65 @@ pub(crate) unsafe fn init(config: Config) {
170 }) 259 })
171 }); 260 });
172 261
262 #[cfg(rcc_f3)]
263 let adc = config.adc.map(|adc| {
264 if !adc.is_bus() {
265 RCC.cfgr2().modify(|w| {
266 // Make sure that we're using the PLL
267 pll_config.unwrap();
268 w.set_adc12pres(adc.into());
269
270 Hertz(sysclk / adc as u32)
271 })
272 } else {
273 crate::pac::ADC_COMMON.ccr().modify(|w| {
274 assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1));
275
276 w.set_ckmode(adc.into());
277
278 Hertz(sysclk / adc.bus_div() as u32)
279 })
280 }
281 });
282
283 #[cfg(all(rcc_f3, adc3_common))]
284 let adc34 = config.adc.map(|adc| {
285 if !adc.is_bus() {
286 RCC.cfgr2().modify(|w| {
287 // Make sure that we're using the PLL
288 pll_config.unwrap();
289 w.set_adc12pres(adc.into());
290
291 Hertz(sysclk / adc as u32)
292 })
293 } else {
294 crate::pac::ADC3_COMMON.ccr().modify(|w| {
295 assert!(!(adc.bus_div() == 1 && hpre_bits != Hpre::DIV1));
296
297 w.set_ckmode(adc.into());
298
299 Hertz(sysclk / adc.bus_div() as u32)
300 })
301 }
302 });
303
304 #[cfg(stm32f334)]
305 let hrtim = match config.hrtim {
306 // Must be configured after the bus is ready, otherwise it won't work
307 HrtimClockSource::BusClk => None,
308 HrtimClockSource::PllClk => {
309 use crate::pac::rcc::vals::Timsw;
310
311 // Make sure that we're using the PLL
312 pll_config.unwrap();
313 assert!((pclk2 == sysclk) || (pclk2 * 2 == sysclk));
314
315 RCC.cfgr3().modify(|w| w.set_hrtim1sw(Timsw::PLL));
316
317 Some(Hertz(sysclk * 2))
318 }
319 };
320
173 set_freqs(Clocks { 321 set_freqs(Clocks {
174 sys: Hertz(sysclk), 322 sys: Hertz(sysclk),
175 apb1: Hertz(pclk1), 323 apb1: Hertz(pclk1),
@@ -177,6 +325,14 @@ pub(crate) unsafe fn init(config: Config) {
177 apb1_tim: Hertz(pclk1 * timer_mul1), 325 apb1_tim: Hertz(pclk1 * timer_mul1),
178 apb2_tim: Hertz(pclk2 * timer_mul2), 326 apb2_tim: Hertz(pclk2 * timer_mul2),
179 ahb1: Hertz(hclk), 327 ahb1: Hertz(hclk),
328 #[cfg(rcc_f3)]
329 adc: adc,
330 #[cfg(all(rcc_f3, adc3_common))]
331 adc34: adc34,
332 #[cfg(all(rcc_f3, not(adc3_common)))]
333 adc34: None,
334 #[cfg(stm32f334)]
335 hrtim: hrtim,
180 }); 336 });
181} 337}
182 338
@@ -201,9 +357,9 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) {
201 // Calculates the Multiplier and the Divisor to arrive at 357 // Calculates the Multiplier and the Divisor to arrive at
202 // the required System clock from PLL source frequency 358 // the required System clock from PLL source frequency
203 let get_mul_div = |sysclk, pllsrcclk| { 359 let get_mul_div = |sysclk, pllsrcclk| {
204 let common_div = gcd(sysclk, pllsrcclk); 360 let bus_div = gcd(sysclk, pllsrcclk);
205 let mut multiplier = sysclk / common_div; 361 let mut multiplier = sysclk / bus_div;
206 let mut divisor = pllsrcclk / common_div; 362 let mut divisor = pllsrcclk / bus_div;
207 // Minimum PLL multiplier is two 363 // Minimum PLL multiplier is two
208 if multiplier == 1 { 364 if multiplier == 1 {
209 multiplier *= 2; 365 multiplier *= 2;
diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs
index 72bdbd5db..2c027ebed 100644
--- a/embassy-stm32/src/rcc/f4.rs
+++ b/embassy-stm32/src/rcc/f4.rs
@@ -3,13 +3,12 @@ use core::marker::PhantomData;
3use embassy_hal_internal::into_ref; 3use embassy_hal_internal::into_ref;
4use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre}; 4use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre};
5 5
6use super::sealed::RccPeripheral;
7use crate::gpio::sealed::AFType; 6use crate::gpio::sealed::AFType;
8use crate::gpio::Speed; 7use crate::gpio::Speed;
9use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; 8use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
10use crate::pac::{FLASH, PWR, RCC}; 9use crate::pac::{FLASH, PWR, RCC};
10use crate::rcc::bd::{BackupDomain, RtcClockSource};
11use crate::rcc::{set_freqs, Clocks}; 11use crate::rcc::{set_freqs, Clocks};
12use crate::rtc::{Rtc, RtcClockSource};
13use crate::time::Hertz; 12use crate::time::Hertz;
14use crate::{peripherals, Peripheral}; 13use crate::{peripherals, Peripheral};
15 14
@@ -38,6 +37,8 @@ pub struct Config {
38 37
39 pub pll48: bool, 38 pub pll48: bool,
40 pub rtc: Option<RtcClockSource>, 39 pub rtc: Option<RtcClockSource>,
40 pub lsi: bool,
41 pub lse: Option<Hertz>,
41} 42}
42 43
43#[cfg(stm32f410)] 44#[cfg(stm32f410)]
@@ -360,8 +361,6 @@ fn flash_setup(sysclk: u32) {
360} 361}
361 362
362pub(crate) unsafe fn init(config: Config) { 363pub(crate) unsafe fn init(config: Config) {
363 crate::peripherals::PWR::enable();
364
365 let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0); 364 let pllsrcclk = config.hse.map(|hse| hse.0).unwrap_or(HSI_FREQ.0);
366 let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk); 365 let sysclk = config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk);
367 let sysclk_on_pll = sysclk != pllsrcclk; 366 let sysclk_on_pll = sysclk != pllsrcclk;
@@ -501,20 +500,15 @@ pub(crate) unsafe fn init(config: Config) {
501 }) 500 })
502 }); 501 });
503 502
504 match config.rtc { 503 BackupDomain::configure_ls(
505 Some(RtcClockSource::LSI) => { 504 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
506 RCC.csr().modify(|w| w.set_lsion(true)); 505 config.lsi,
507 while !RCC.csr().read().lsirdy() {} 506 config.lse.map(|_| Default::default()),
508 } 507 );
509 _ => {}
510 }
511
512 config.rtc.map(|clock_source| {
513 Rtc::set_clock_source(clock_source);
514 });
515 508
516 let rtc = match config.rtc { 509 let rtc = match config.rtc {
517 Some(RtcClockSource::LSI) => Some(LSI_FREQ), 510 Some(RtcClockSource::LSI) => Some(LSI_FREQ),
511 Some(RtcClockSource::LSE) => Some(config.lse.unwrap()),
518 _ => None, 512 _ => None,
519 }; 513 };
520 514
@@ -539,6 +533,7 @@ pub(crate) unsafe fn init(config: Config) {
539 pllsai: plls.pllsaiclk.map(Hertz), 533 pllsai: plls.pllsaiclk.map(Hertz),
540 534
541 rtc: rtc, 535 rtc: rtc,
536 rtc_hse: None,
542 }); 537 });
543} 538}
544 539
diff --git a/embassy-stm32/src/rcc/f7.rs b/embassy-stm32/src/rcc/f7.rs
index 85cb9c661..f32559e26 100644
--- a/embassy-stm32/src/rcc/f7.rs
+++ b/embassy-stm32/src/rcc/f7.rs
@@ -1,7 +1,7 @@
1use super::sealed::RccPeripheral;
2use crate::pac::pwr::vals::Vos; 1use crate::pac::pwr::vals::Vos;
3use crate::pac::rcc::vals::{Hpre, Ppre, Sw}; 2use crate::pac::rcc::vals::{Hpre, Ppre, Sw};
4use crate::pac::{FLASH, PWR, RCC}; 3use crate::pac::{FLASH, PWR, RCC};
4use crate::rcc::bd::{BackupDomain, RtcClockSource};
5use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz; 6use crate::time::Hertz;
7 7
@@ -23,6 +23,9 @@ pub struct Config {
23 pub pclk2: Option<Hertz>, 23 pub pclk2: Option<Hertz>,
24 24
25 pub pll48: bool, 25 pub pll48: bool,
26 pub rtc: Option<RtcClockSource>,
27 pub lsi: bool,
28 pub lse: Option<Hertz>,
26} 29}
27 30
28fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults { 31fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option<u32>, pll48clk: bool) -> PllResults {
@@ -111,8 +114,6 @@ fn flash_setup(sysclk: u32) {
111} 114}
112 115
113pub(crate) unsafe fn init(config: Config) { 116pub(crate) unsafe fn init(config: Config) {
114 crate::peripherals::PWR::enable();
115
116 if let Some(hse) = config.hse { 117 if let Some(hse) = config.hse {
117 if config.bypass_hse { 118 if config.bypass_hse {
118 assert!((max::HSE_BYPASS_MIN..=max::HSE_BYPASS_MAX).contains(&hse.0)); 119 assert!((max::HSE_BYPASS_MIN..=max::HSE_BYPASS_MAX).contains(&hse.0));
@@ -212,10 +213,7 @@ pub(crate) unsafe fn init(config: Config) {
212 if plls.use_pll { 213 if plls.use_pll {
213 RCC.cr().modify(|w| w.set_pllon(false)); 214 RCC.cr().modify(|w| w.set_pllon(false));
214 215
215 // enable PWR and setup VOSScale 216 // setup VOSScale
216
217 RCC.apb1enr().modify(|w| w.set_pwren(true));
218
219 let vos_scale = if sysclk <= 144_000_000 { 217 let vos_scale = if sysclk <= 144_000_000 {
220 3 218 3
221 } else if sysclk <= 168_000_000 { 219 } else if sysclk <= 168_000_000 {
@@ -265,6 +263,18 @@ pub(crate) unsafe fn init(config: Config) {
265 }) 263 })
266 }); 264 });
267 265
266 BackupDomain::configure_ls(
267 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
268 config.lsi,
269 config.lse.map(|_| Default::default()),
270 );
271
272 let rtc = match config.rtc {
273 Some(RtcClockSource::LSI) => Some(LSI_FREQ),
274 Some(RtcClockSource::LSE) => Some(config.lse.unwrap()),
275 _ => None,
276 };
277
268 set_freqs(Clocks { 278 set_freqs(Clocks {
269 sys: Hertz(sysclk), 279 sys: Hertz(sysclk),
270 apb1: Hertz(pclk1), 280 apb1: Hertz(pclk1),
@@ -278,6 +288,8 @@ pub(crate) unsafe fn init(config: Config) {
278 ahb3: Hertz(hclk), 288 ahb3: Hertz(hclk),
279 289
280 pll48: plls.pll48clk.map(Hertz), 290 pll48: plls.pll48clk.map(Hertz),
291
292 rtc,
281 }); 293 });
282} 294}
283 295
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index bf2d5199e..7f0a2c7fb 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -1,4 +1,4 @@
1pub use super::common::{AHBPrescaler, APBPrescaler}; 1pub use super::bus::{AHBPrescaler, APBPrescaler};
2use crate::pac::flash::vals::Latency; 2use crate::pac::flash::vals::Latency;
3use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw}; 3use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw};
4use crate::pac::{FLASH, PWR, RCC}; 4use crate::pac::{FLASH, PWR, RCC};
@@ -186,8 +186,8 @@ impl Default for Config {
186 fn default() -> Config { 186 fn default() -> Config {
187 Config { 187 Config {
188 mux: ClockSrc::HSI16(HSI16Prescaler::NotDivided), 188 mux: ClockSrc::HSI16(HSI16Prescaler::NotDivided),
189 ahb_pre: AHBPrescaler::NotDivided, 189 ahb_pre: AHBPrescaler::DIV1,
190 apb_pre: APBPrescaler::NotDivided, 190 apb_pre: APBPrescaler::DIV1,
191 low_power_run: false, 191 low_power_run: false,
192 } 192 }
193 } 193 }
@@ -377,7 +377,7 @@ pub(crate) unsafe fn init(config: Config) {
377 let ahb_freq = Hertz(sys_clk) / config.ahb_pre; 377 let ahb_freq = Hertz(sys_clk) / config.ahb_pre;
378 378
379 let (apb_freq, apb_tim_freq) = match config.apb_pre { 379 let (apb_freq, apb_tim_freq) = match config.apb_pre {
380 APBPrescaler::NotDivided => (ahb_freq.0, ahb_freq.0), 380 APBPrescaler::DIV1 => (ahb_freq.0, ahb_freq.0),
381 pre => { 381 pre => {
382 let pre: Ppre = pre.into(); 382 let pre: Ppre = pre.into();
383 let pre: u8 = 1 << (pre.to_bits() - 3); 383 let pre: u8 = 1 << (pre.to_bits() - 3);
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs
index dff04023e..41bebc918 100644
--- a/embassy-stm32/src/rcc/g4.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -1,8 +1,8 @@
1use stm32_metapac::flash::vals::Latency; 1use stm32_metapac::flash::vals::Latency;
2use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; 2use stm32_metapac::rcc::vals::{Adcsel, Pllsrc, Sw};
3use stm32_metapac::FLASH; 3use stm32_metapac::FLASH;
4 4
5pub use super::common::{AHBPrescaler, APBPrescaler}; 5pub use super::bus::{AHBPrescaler, APBPrescaler};
6use crate::pac::{PWR, RCC}; 6use crate::pac::{PWR, RCC};
7use crate::rcc::sealed::RccPeripheral; 7use crate::rcc::sealed::RccPeripheral;
8use crate::rcc::{set_freqs, Clocks}; 8use crate::rcc::{set_freqs, Clocks};
@@ -14,6 +14,29 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000);
14/// LSI speed 14/// LSI speed
15pub const LSI_FREQ: Hertz = Hertz(32_000); 15pub const LSI_FREQ: Hertz = Hertz(32_000);
16 16
17#[derive(Clone, Copy)]
18pub enum AdcClockSource {
19 NoClk,
20 SysClk,
21 PllP,
22}
23
24impl AdcClockSource {
25 pub fn adcsel(&self) -> Adcsel {
26 match self {
27 AdcClockSource::NoClk => Adcsel::NOCLK,
28 AdcClockSource::SysClk => Adcsel::SYSCLK,
29 AdcClockSource::PllP => Adcsel::PLLP,
30 }
31 }
32}
33
34impl Default for AdcClockSource {
35 fn default() -> Self {
36 Self::NoClk
37 }
38}
39
17/// System clock mux source 40/// System clock mux source
18#[derive(Clone, Copy)] 41#[derive(Clone, Copy)]
19pub enum ClockSrc { 42pub enum ClockSrc {
@@ -238,59 +261,29 @@ pub struct Pll {
238 pub div_r: Option<PllR>, 261 pub div_r: Option<PllR>,
239} 262}
240 263
241impl AHBPrescaler { 264fn ahb_div(ahb: AHBPrescaler) -> u32 {
242 const fn div(self) -> u32 { 265 match ahb {
243 match self { 266 AHBPrescaler::DIV1 => 1,
244 AHBPrescaler::NotDivided => 1, 267 AHBPrescaler::DIV2 => 2,
245 AHBPrescaler::Div2 => 2, 268 AHBPrescaler::DIV4 => 4,
246 AHBPrescaler::Div4 => 4, 269 AHBPrescaler::DIV8 => 8,
247 AHBPrescaler::Div8 => 8, 270 AHBPrescaler::DIV16 => 16,
248 AHBPrescaler::Div16 => 16, 271 AHBPrescaler::DIV64 => 64,
249 AHBPrescaler::Div64 => 64, 272 AHBPrescaler::DIV128 => 128,
250 AHBPrescaler::Div128 => 128, 273 AHBPrescaler::DIV256 => 256,
251 AHBPrescaler::Div256 => 256, 274 AHBPrescaler::DIV512 => 512,
252 AHBPrescaler::Div512 => 512, 275 _ => unreachable!(),
253 }
254 } 276 }
255} 277}
256 278
257impl APBPrescaler { 279fn apb_div(apb: APBPrescaler) -> u32 {
258 const fn div(self) -> u32 { 280 match apb {
259 match self { 281 APBPrescaler::DIV1 => 1,
260 APBPrescaler::NotDivided => 1, 282 APBPrescaler::DIV2 => 2,
261 APBPrescaler::Div2 => 2, 283 APBPrescaler::DIV4 => 4,
262 APBPrescaler::Div4 => 4, 284 APBPrescaler::DIV8 => 8,
263 APBPrescaler::Div8 => 8, 285 APBPrescaler::DIV16 => 16,
264 APBPrescaler::Div16 => 16, 286 _ => unreachable!(),
265 }
266 }
267}
268
269impl Into<Ppre> for APBPrescaler {
270 fn into(self) -> Ppre {
271 match self {
272 APBPrescaler::NotDivided => Ppre::DIV1,
273 APBPrescaler::Div2 => Ppre::DIV2,
274 APBPrescaler::Div4 => Ppre::DIV4,
275 APBPrescaler::Div8 => Ppre::DIV8,
276 APBPrescaler::Div16 => Ppre::DIV16,
277 }
278 }
279}
280
281impl Into<Hpre> for AHBPrescaler {
282 fn into(self) -> Hpre {
283 match self {
284 AHBPrescaler::NotDivided => Hpre::DIV1,
285 AHBPrescaler::Div2 => Hpre::DIV2,
286 AHBPrescaler::Div4 => Hpre::DIV4,
287 AHBPrescaler::Div8 => Hpre::DIV8,
288 AHBPrescaler::Div16 => Hpre::DIV16,
289 AHBPrescaler::Div64 => Hpre::DIV64,
290 AHBPrescaler::Div128 => Hpre::DIV128,
291 AHBPrescaler::Div256 => Hpre::DIV256,
292 AHBPrescaler::Div512 => Hpre::DIV512,
293 }
294 } 287 }
295} 288}
296 289
@@ -327,6 +320,8 @@ pub struct Config {
327 pub pll: Option<Pll>, 320 pub pll: Option<Pll>,
328 /// Sets the clock source for the 48MHz clock used by the USB and RNG peripherals. 321 /// Sets the clock source for the 48MHz clock used by the USB and RNG peripherals.
329 pub clock_48mhz_src: Option<Clock48MhzSrc>, 322 pub clock_48mhz_src: Option<Clock48MhzSrc>,
323 pub adc12_clock_source: AdcClockSource,
324 pub adc345_clock_source: AdcClockSource,
330} 325}
331 326
332/// Configuration for the Clock Recovery System (CRS) used to trim the HSI48 oscillator. 327/// Configuration for the Clock Recovery System (CRS) used to trim the HSI48 oscillator.
@@ -340,12 +335,14 @@ impl Default for Config {
340 fn default() -> Config { 335 fn default() -> Config {
341 Config { 336 Config {
342 mux: ClockSrc::HSI16, 337 mux: ClockSrc::HSI16,
343 ahb_pre: AHBPrescaler::NotDivided, 338 ahb_pre: AHBPrescaler::DIV1,
344 apb1_pre: APBPrescaler::NotDivided, 339 apb1_pre: APBPrescaler::DIV1,
345 apb2_pre: APBPrescaler::NotDivided, 340 apb2_pre: APBPrescaler::DIV1,
346 low_power_run: false, 341 low_power_run: false,
347 pll: None, 342 pll: None,
348 clock_48mhz_src: None, 343 clock_48mhz_src: None,
344 adc12_clock_source: Default::default(),
345 adc345_clock_source: Default::default(),
349 } 346 }
350 } 347 }
351} 348}
@@ -485,22 +482,22 @@ pub(crate) unsafe fn init(config: Config) {
485 }); 482 });
486 483
487 let ahb_freq: u32 = match config.ahb_pre { 484 let ahb_freq: u32 = match config.ahb_pre {
488 AHBPrescaler::NotDivided => sys_clk, 485 AHBPrescaler::DIV1 => sys_clk,
489 pre => sys_clk / pre.div(), 486 pre => sys_clk / ahb_div(pre),
490 }; 487 };
491 488
492 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 489 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
493 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 490 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
494 pre => { 491 pre => {
495 let freq = ahb_freq / pre.div(); 492 let freq = ahb_freq / apb_div(pre);
496 (freq, freq * 2) 493 (freq, freq * 2)
497 } 494 }
498 }; 495 };
499 496
500 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 497 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
501 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 498 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
502 pre => { 499 pre => {
503 let freq = ahb_freq / pre.div(); 500 let freq = ahb_freq / apb_div(pre);
504 (freq, freq * 2) 501 (freq, freq * 2)
505 } 502 }
506 }; 503 };
@@ -549,6 +546,29 @@ pub(crate) unsafe fn init(config: Config) {
549 RCC.ccipr().modify(|w| w.set_clk48sel(source)); 546 RCC.ccipr().modify(|w| w.set_clk48sel(source));
550 } 547 }
551 548
549 RCC.ccipr()
550 .modify(|w| w.set_adc12sel(config.adc12_clock_source.adcsel()));
551 RCC.ccipr()
552 .modify(|w| w.set_adc345sel(config.adc345_clock_source.adcsel()));
553
554 let adc12_ck = match config.adc12_clock_source {
555 AdcClockSource::NoClk => None,
556 AdcClockSource::PllP => match &pll_freq {
557 Some(pll) => pll.pll_p,
558 None => None,
559 },
560 AdcClockSource::SysClk => Some(Hertz(sys_clk)),
561 };
562
563 let adc345_ck = match config.adc345_clock_source {
564 AdcClockSource::NoClk => None,
565 AdcClockSource::PllP => match &pll_freq {
566 Some(pll) => pll.pll_p,
567 None => None,
568 },
569 AdcClockSource::SysClk => Some(Hertz(sys_clk)),
570 };
571
552 if config.low_power_run { 572 if config.low_power_run {
553 assert!(sys_clk <= 2_000_000); 573 assert!(sys_clk <= 2_000_000);
554 PWR.cr1().modify(|w| w.set_lpr(true)); 574 PWR.cr1().modify(|w| w.set_lpr(true));
@@ -562,5 +582,7 @@ pub(crate) unsafe fn init(config: Config) {
562 apb1_tim: Hertz(apb1_tim_freq), 582 apb1_tim: Hertz(apb1_tim_freq),
563 apb2: Hertz(apb2_freq), 583 apb2: Hertz(apb2_freq),
564 apb2_tim: Hertz(apb2_tim_freq), 584 apb2_tim: Hertz(apb2_tim_freq),
585 adc: adc12_ck,
586 adc34: adc345_ck,
565 }); 587 });
566} 588}
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
new file mode 100644
index 000000000..43e8db22e
--- /dev/null
+++ b/embassy-stm32/src/rcc/h.rs
@@ -0,0 +1,772 @@
1use core::ops::RangeInclusive;
2
3use crate::pac;
4use crate::pac::pwr::vals::Vos;
5#[cfg(stm32h5)]
6pub use crate::pac::rcc::vals::Adcdacsel as AdcClockSource;
7#[cfg(stm32h7)]
8pub use crate::pac::rcc::vals::Adcsel as AdcClockSource;
9pub use crate::pac::rcc::vals::Ckpersel as PerClockSource;
10use crate::pac::rcc::vals::{Ckpersel, Hsidiv, Pllrge, Pllsrc, Pllvcosel, Sw, Timpre};
11use crate::pac::{FLASH, PWR, RCC};
12use crate::rcc::{set_freqs, Clocks};
13use crate::time::Hertz;
14
15/// HSI speed
16pub const HSI_FREQ: Hertz = Hertz(64_000_000);
17
18/// CSI speed
19pub const CSI_FREQ: Hertz = Hertz(4_000_000);
20
21/// HSI48 speed
22pub const HSI48_FREQ: Hertz = Hertz(48_000_000);
23
24/// LSI speed
25pub const LSI_FREQ: Hertz = Hertz(32_000);
26
27const VCO_RANGE: RangeInclusive<u32> = 150_000_000..=420_000_000;
28#[cfg(any(stm32h5, pwr_h7rm0455))]
29const VCO_WIDE_RANGE: RangeInclusive<u32> = 128_000_000..=560_000_000;
30#[cfg(pwr_h7rm0468)]
31const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=836_000_000;
32#[cfg(any(pwr_h7rm0399, pwr_h7rm0433))]
33const VCO_WIDE_RANGE: RangeInclusive<u32> = 192_000_000..=960_000_000;
34
35pub use super::bus::{AHBPrescaler, APBPrescaler};
36
37#[derive(Clone, Copy, Eq, PartialEq)]
38pub enum VoltageScale {
39 Scale0,
40 Scale1,
41 Scale2,
42 Scale3,
43}
44
45#[derive(Clone, Copy, Eq, PartialEq)]
46pub enum HseMode {
47 /// crystal/ceramic oscillator (HSEBYP=0)
48 Oscillator,
49 /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0)
50 Bypass,
51 /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1)
52 #[cfg(any(rcc_h5, rcc_h50))]
53 BypassDigital,
54}
55
56#[derive(Clone, Copy, Eq, PartialEq)]
57pub struct Hse {
58 /// HSE frequency.
59 pub freq: Hertz,
60 /// HSE mode.
61 pub mode: HseMode,
62}
63
64#[derive(Clone, Copy, Eq, PartialEq)]
65pub enum Hsi {
66 /// 64Mhz
67 Mhz64,
68 /// 32Mhz (divided by 2)
69 Mhz32,
70 /// 16Mhz (divided by 4)
71 Mhz16,
72 /// 8Mhz (divided by 8)
73 Mhz8,
74}
75
76#[derive(Clone, Copy, Eq, PartialEq)]
77pub enum Sysclk {
78 /// HSI selected as sysclk
79 HSI,
80 /// HSE selected as sysclk
81 HSE,
82 /// CSI selected as sysclk
83 CSI,
84 /// PLL1_P selected as sysclk
85 Pll1P,
86}
87
88#[derive(Clone, Copy, Eq, PartialEq)]
89pub enum PllSource {
90 Hsi,
91 Csi,
92 Hse,
93}
94
95#[derive(Clone, Copy)]
96pub struct Pll {
97 /// Source clock selection.
98 #[cfg(stm32h5)]
99 pub source: PllSource,
100
101 /// PLL pre-divider (DIVM). Must be between 1 and 63.
102 pub prediv: u8,
103
104 /// PLL multiplication factor. Must be between 4 and 512.
105 pub mul: u16,
106
107 /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
108 /// On PLL1, it must be even (in particular, it cannot be 1.)
109 pub divp: Option<u16>,
110 /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
111 pub divq: Option<u16>,
112 /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
113 pub divr: Option<u16>,
114}
115
116fn apb_div_tim(apb: &APBPrescaler, clk: Hertz, tim: TimerPrescaler) -> Hertz {
117 match (tim, apb) {
118 (TimerPrescaler::DefaultX2, APBPrescaler::DIV1) => clk,
119 (TimerPrescaler::DefaultX2, APBPrescaler::DIV2) => clk,
120 (TimerPrescaler::DefaultX2, APBPrescaler::DIV4) => clk / 2u32,
121 (TimerPrescaler::DefaultX2, APBPrescaler::DIV8) => clk / 4u32,
122 (TimerPrescaler::DefaultX2, APBPrescaler::DIV16) => clk / 8u32,
123
124 (TimerPrescaler::DefaultX4, APBPrescaler::DIV1) => clk,
125 (TimerPrescaler::DefaultX4, APBPrescaler::DIV2) => clk,
126 (TimerPrescaler::DefaultX4, APBPrescaler::DIV4) => clk,
127 (TimerPrescaler::DefaultX4, APBPrescaler::DIV8) => clk / 2u32,
128 (TimerPrescaler::DefaultX4, APBPrescaler::DIV16) => clk / 4u32,
129
130 _ => unreachable!(),
131 }
132}
133
134/// Timer prescaler
135#[derive(Clone, Copy, Eq, PartialEq)]
136pub enum TimerPrescaler {
137 /// The timers kernel clock is equal to hclk if PPREx corresponds to a
138 /// division by 1 or 2, else it is equal to 2*pclk
139 DefaultX2,
140
141 /// The timers kernel clock is equal to hclk if PPREx corresponds to a
142 /// division by 1, 2 or 4, else it is equal to 4*pclk
143 DefaultX4,
144}
145
146impl From<TimerPrescaler> for Timpre {
147 fn from(value: TimerPrescaler) -> Self {
148 match value {
149 TimerPrescaler::DefaultX2 => Timpre::DEFAULTX2,
150 TimerPrescaler::DefaultX4 => Timpre::DEFAULTX4,
151 }
152 }
153}
154
155/// Configuration of the core clocks
156#[non_exhaustive]
157pub struct Config {
158 pub hsi: Option<Hsi>,
159 pub hse: Option<Hse>,
160 pub csi: bool,
161 pub hsi48: bool,
162 pub sys: Sysclk,
163
164 #[cfg(stm32h7)]
165 pub pll_src: PllSource,
166
167 pub pll1: Option<Pll>,
168 pub pll2: Option<Pll>,
169 #[cfg(any(rcc_h5, stm32h7))]
170 pub pll3: Option<Pll>,
171
172 pub d1c_pre: AHBPrescaler,
173 pub ahb_pre: AHBPrescaler,
174 pub apb1_pre: APBPrescaler,
175 pub apb2_pre: APBPrescaler,
176 pub apb3_pre: APBPrescaler,
177 #[cfg(stm32h7)]
178 pub apb4_pre: APBPrescaler,
179
180 pub per_clock_source: PerClockSource,
181 pub adc_clock_source: AdcClockSource,
182 pub timer_prescaler: TimerPrescaler,
183 pub voltage_scale: VoltageScale,
184}
185
186impl Default for Config {
187 fn default() -> Self {
188 Self {
189 hsi: Some(Hsi::Mhz64),
190 hse: None,
191 csi: false,
192 hsi48: false,
193 sys: Sysclk::HSI,
194 #[cfg(stm32h7)]
195 pll_src: PllSource::Hsi,
196 pll1: None,
197 pll2: None,
198 #[cfg(any(rcc_h5, stm32h7))]
199 pll3: None,
200
201 d1c_pre: AHBPrescaler::DIV1,
202 ahb_pre: AHBPrescaler::DIV1,
203 apb1_pre: APBPrescaler::DIV1,
204 apb2_pre: APBPrescaler::DIV1,
205 apb3_pre: APBPrescaler::DIV1,
206 #[cfg(stm32h7)]
207 apb4_pre: APBPrescaler::DIV1,
208
209 per_clock_source: PerClockSource::HSI,
210 adc_clock_source: AdcClockSource::from_bits(0), // PLL2_P on H7, HCLK on H5
211 timer_prescaler: TimerPrescaler::DefaultX2,
212 voltage_scale: VoltageScale::Scale0,
213 }
214 }
215}
216
217pub(crate) unsafe fn init(config: Config) {
218 // NB. The lower bytes of CR3 can only be written once after
219 // POR, and must be written with a valid combination. Refer to
220 // RM0433 Rev 7 6.8.4. This is partially enforced by dropping
221 // `self` at the end of this method, but of course we cannot
222 // know what happened between the previous POR and here.
223 #[cfg(pwr_h7rm0433)]
224 PWR.cr3().modify(|w| {
225 w.set_scuen(true);
226 w.set_ldoen(true);
227 w.set_bypass(false);
228 });
229
230 #[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
231 PWR.cr3().modify(|w| {
232 // hardcode "Direct SPMS" for now, this is what works on nucleos with the
233 // default solderbridge configuration.
234 w.set_sden(true);
235 w.set_ldoen(false);
236 });
237
238 // Validate the supply configuration. If you are stuck here, it is
239 // because the voltages on your board do not match those specified
240 // in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset
241 // VOS = Scale 3, so check that the voltage on the VCAP pins =
242 // 1.0V.
243 #[cfg(any(pwr_h7rm0433, pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468))]
244 while !PWR.csr1().read().actvosrdy() {}
245
246 // Configure voltage scale.
247 #[cfg(any(pwr_h5, pwr_h50))]
248 {
249 PWR.voscr().modify(|w| {
250 w.set_vos(match config.voltage_scale {
251 VoltageScale::Scale0 => Vos::SCALE0,
252 VoltageScale::Scale1 => Vos::SCALE1,
253 VoltageScale::Scale2 => Vos::SCALE2,
254 VoltageScale::Scale3 => Vos::SCALE3,
255 })
256 });
257 while !PWR.vossr().read().vosrdy() {}
258 }
259
260 #[cfg(syscfg_h7)]
261 {
262 // in chips without the overdrive bit, we can go from any scale to any scale directly.
263 PWR.d3cr().modify(|w| {
264 w.set_vos(match config.voltage_scale {
265 VoltageScale::Scale0 => Vos::SCALE0,
266 VoltageScale::Scale1 => Vos::SCALE1,
267 VoltageScale::Scale2 => Vos::SCALE2,
268 VoltageScale::Scale3 => Vos::SCALE3,
269 })
270 });
271 while !PWR.d3cr().read().vosrdy() {}
272 }
273
274 #[cfg(syscfg_h7od)]
275 {
276 match config.voltage_scale {
277 VoltageScale::Scale0 => {
278 // to go to scale0, we must go to Scale1 first...
279 PWR.d3cr().modify(|w| w.set_vos(Vos::SCALE1));
280 while !PWR.d3cr().read().vosrdy() {}
281
282 // Then enable overdrive.
283 critical_section::with(|_| pac::SYSCFG.pwrcr().modify(|w| w.set_oden(1)));
284 while !PWR.d3cr().read().vosrdy() {}
285 }
286 _ => {
287 // for all other scales, we can go directly.
288 PWR.d3cr().modify(|w| {
289 w.set_vos(match config.voltage_scale {
290 VoltageScale::Scale0 => unreachable!(),
291 VoltageScale::Scale1 => Vos::SCALE1,
292 VoltageScale::Scale2 => Vos::SCALE2,
293 VoltageScale::Scale3 => Vos::SCALE3,
294 })
295 });
296 while !PWR.d3cr().read().vosrdy() {}
297 }
298 }
299 }
300
301 // Configure HSI
302 let hsi = match config.hsi {
303 None => {
304 RCC.cr().modify(|w| w.set_hsion(false));
305 None
306 }
307 Some(hsi) => {
308 let (freq, hsidiv) = match hsi {
309 Hsi::Mhz64 => (HSI_FREQ / 1u32, Hsidiv::DIV1),
310 Hsi::Mhz32 => (HSI_FREQ / 2u32, Hsidiv::DIV2),
311 Hsi::Mhz16 => (HSI_FREQ / 4u32, Hsidiv::DIV4),
312 Hsi::Mhz8 => (HSI_FREQ / 8u32, Hsidiv::DIV8),
313 };
314 RCC.cr().modify(|w| {
315 w.set_hsidiv(hsidiv);
316 w.set_hsion(true);
317 });
318 while !RCC.cr().read().hsirdy() {}
319 Some(freq)
320 }
321 };
322
323 // Configure HSE
324 let hse = match config.hse {
325 None => {
326 RCC.cr().modify(|w| w.set_hseon(false));
327 None
328 }
329 Some(hse) => {
330 RCC.cr().modify(|w| {
331 w.set_hsebyp(hse.mode != HseMode::Oscillator);
332 #[cfg(any(rcc_h5, rcc_h50))]
333 w.set_hseext(match hse.mode {
334 HseMode::Oscillator | HseMode::Bypass => pac::rcc::vals::Hseext::ANALOG,
335 HseMode::BypassDigital => pac::rcc::vals::Hseext::DIGITAL,
336 });
337 });
338 RCC.cr().modify(|w| w.set_hseon(true));
339 while !RCC.cr().read().hserdy() {}
340 Some(hse.freq)
341 }
342 };
343
344 // Configure HSI48.
345 RCC.cr().modify(|w| w.set_hsi48on(config.hsi48));
346 let _hsi48 = match config.hsi48 {
347 false => None,
348 true => {
349 while !RCC.cr().read().hsi48rdy() {}
350 Some(CSI_FREQ)
351 }
352 };
353
354 // Configure CSI.
355 RCC.cr().modify(|w| w.set_csion(config.csi));
356 let csi = match config.csi {
357 false => None,
358 true => {
359 while !RCC.cr().read().csirdy() {}
360 Some(CSI_FREQ)
361 }
362 };
363
364 // Configure PLLs.
365 let pll_input = PllInput {
366 csi,
367 hse,
368 hsi,
369 #[cfg(stm32h7)]
370 source: config.pll_src,
371 };
372 let pll1 = init_pll(0, config.pll1, &pll_input);
373 let pll2 = init_pll(1, config.pll2, &pll_input);
374 #[cfg(any(rcc_h5, stm32h7))]
375 let _pll3 = init_pll(2, config.pll3, &pll_input);
376
377 // Configure sysclk
378 let (sys, sw) = match config.sys {
379 Sysclk::HSI => (unwrap!(hsi), Sw::HSI),
380 Sysclk::HSE => (unwrap!(hse), Sw::HSE),
381 Sysclk::CSI => (unwrap!(csi), Sw::CSI),
382 Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1),
383 };
384
385 // Check limits.
386 #[cfg(stm32h5)]
387 let (hclk_max, pclk_max) = match config.voltage_scale {
388 VoltageScale::Scale0 => (Hertz(250_000_000), Hertz(250_000_000)),
389 VoltageScale::Scale1 => (Hertz(200_000_000), Hertz(200_000_000)),
390 VoltageScale::Scale2 => (Hertz(150_000_000), Hertz(150_000_000)),
391 VoltageScale::Scale3 => (Hertz(100_000_000), Hertz(100_000_000)),
392 };
393 #[cfg(stm32h7)]
394 let (d1cpre_clk_max, hclk_max, pclk_max) = match config.voltage_scale {
395 VoltageScale::Scale0 => (Hertz(480_000_000), Hertz(240_000_000), Hertz(120_000_000)),
396 VoltageScale::Scale1 => (Hertz(400_000_000), Hertz(200_000_000), Hertz(100_000_000)),
397 VoltageScale::Scale2 => (Hertz(300_000_000), Hertz(150_000_000), Hertz(75_000_000)),
398 VoltageScale::Scale3 => (Hertz(200_000_000), Hertz(100_000_000), Hertz(50_000_000)),
399 };
400
401 #[cfg(stm32h7)]
402 let hclk = {
403 let d1cpre_clk = sys / config.d1c_pre;
404 assert!(d1cpre_clk <= d1cpre_clk_max);
405 sys / config.ahb_pre
406 };
407 #[cfg(stm32h5)]
408 let hclk = sys / config.ahb_pre;
409 assert!(hclk <= hclk_max);
410
411 let apb1 = hclk / config.apb1_pre;
412 let apb1_tim = apb_div_tim(&config.apb1_pre, hclk, config.timer_prescaler);
413 assert!(apb1 <= pclk_max);
414 let apb2 = hclk / config.apb2_pre;
415 let apb2_tim = apb_div_tim(&config.apb2_pre, hclk, config.timer_prescaler);
416 assert!(apb2 <= pclk_max);
417 let apb3 = hclk / config.apb3_pre;
418 assert!(apb3 <= pclk_max);
419 #[cfg(stm32h7)]
420 let apb4 = hclk / config.apb4_pre;
421 #[cfg(stm32h7)]
422 assert!(apb4 <= pclk_max);
423
424 let _per_ck = match config.per_clock_source {
425 Ckpersel::HSI => hsi,
426 Ckpersel::CSI => csi,
427 Ckpersel::HSE => hse,
428 _ => unreachable!(),
429 };
430
431 #[cfg(stm32h7)]
432 let adc = match config.adc_clock_source {
433 AdcClockSource::PLL2_P => pll2.p,
434 AdcClockSource::PLL3_R => _pll3.r,
435 AdcClockSource::PER => _per_ck,
436 _ => unreachable!(),
437 };
438 #[cfg(stm32h5)]
439 let adc = match config.adc_clock_source {
440 AdcClockSource::HCLK => Some(hclk),
441 AdcClockSource::SYSCLK => Some(sys),
442 AdcClockSource::PLL2_R => pll2.r,
443 AdcClockSource::HSE => hse,
444 AdcClockSource::HSI_KER => hsi,
445 AdcClockSource::CSI_KER => csi,
446 _ => unreachable!(),
447 };
448
449 flash_setup(hclk, config.voltage_scale);
450
451 #[cfg(stm32h7)]
452 {
453 RCC.d1cfgr().modify(|w| {
454 w.set_d1cpre(config.d1c_pre);
455 w.set_d1ppre(config.apb3_pre);
456 w.set_hpre(config.ahb_pre);
457 });
458 // Ensure core prescaler value is valid before future lower core voltage
459 while RCC.d1cfgr().read().d1cpre() != config.d1c_pre {}
460
461 RCC.d2cfgr().modify(|w| {
462 w.set_d2ppre1(config.apb1_pre);
463 w.set_d2ppre2(config.apb2_pre);
464 });
465 RCC.d3cfgr().modify(|w| {
466 w.set_d3ppre(config.apb4_pre);
467 });
468
469 RCC.d1ccipr().modify(|w| {
470 w.set_ckpersel(config.per_clock_source);
471 });
472 RCC.d3ccipr().modify(|w| {
473 w.set_adcsel(config.adc_clock_source);
474 });
475 }
476 #[cfg(stm32h5)]
477 {
478 // Set hpre
479 RCC.cfgr2().modify(|w| w.set_hpre(config.ahb_pre));
480 while RCC.cfgr2().read().hpre() != config.ahb_pre {}
481
482 // set ppre
483 RCC.cfgr2().modify(|w| {
484 w.set_ppre1(config.apb1_pre);
485 w.set_ppre2(config.apb2_pre);
486 w.set_ppre3(config.apb3_pre);
487 });
488
489 RCC.ccipr5().modify(|w| {
490 w.set_ckpersel(config.per_clock_source);
491 w.set_adcdacsel(config.adc_clock_source)
492 });
493 }
494
495 RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into()));
496
497 RCC.cfgr().modify(|w| w.set_sw(sw));
498 while RCC.cfgr().read().sws() != sw {}
499
500 // IO compensation cell - Requires CSI clock and SYSCFG
501 #[cfg(stm32h7)] // TODO h5
502 if csi.is_some() {
503 // Enable the compensation cell, using back-bias voltage code
504 // provide by the cell.
505 critical_section::with(|_| {
506 pac::SYSCFG.cccsr().modify(|w| {
507 w.set_en(true);
508 w.set_cs(false);
509 w.set_hslv(false);
510 })
511 });
512 while !pac::SYSCFG.cccsr().read().ready() {}
513 }
514
515 set_freqs(Clocks {
516 sys,
517 ahb1: hclk,
518 ahb2: hclk,
519 ahb3: hclk,
520 ahb4: hclk,
521 apb1,
522 apb2,
523 apb3,
524 #[cfg(stm32h7)]
525 apb4,
526 apb1_tim,
527 apb2_tim,
528 adc: adc,
529 });
530}
531
532struct PllInput {
533 hsi: Option<Hertz>,
534 hse: Option<Hertz>,
535 csi: Option<Hertz>,
536 #[cfg(stm32h7)]
537 source: PllSource,
538}
539
540struct PllOutput {
541 p: Option<Hertz>,
542 #[allow(dead_code)]
543 q: Option<Hertz>,
544 #[allow(dead_code)]
545 r: Option<Hertz>,
546}
547
548fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
549 let Some(config) = config else {
550 // Stop PLL
551 RCC.cr().modify(|w| w.set_pllon(num, false));
552 while RCC.cr().read().pllrdy(num) {}
553
554 // "To save power when PLL1 is not used, the value of PLL1M must be set to 0.""
555 #[cfg(stm32h7)]
556 RCC.pllckselr().write(|w| w.set_divm(num, 0));
557 #[cfg(stm32h5)]
558 RCC.pllcfgr(num).write(|w| w.set_divm(0));
559
560 return PllOutput {
561 p: None,
562 q: None,
563 r: None,
564 };
565 };
566
567 assert!(1 <= config.prediv && config.prediv <= 63);
568 assert!(4 <= config.mul && config.mul <= 512);
569
570 #[cfg(stm32h5)]
571 let source = config.source;
572 #[cfg(stm32h7)]
573 let source = input.source;
574
575 let (in_clk, src) = match source {
576 PllSource::Hsi => (unwrap!(input.hsi), Pllsrc::HSI),
577 PllSource::Hse => (unwrap!(input.hse), Pllsrc::HSE),
578 PllSource::Csi => (unwrap!(input.csi), Pllsrc::CSI),
579 };
580
581 let ref_clk = in_clk / config.prediv as u32;
582
583 let ref_range = match ref_clk.0 {
584 ..=1_999_999 => Pllrge::RANGE1,
585 ..=3_999_999 => Pllrge::RANGE2,
586 ..=7_999_999 => Pllrge::RANGE4,
587 ..=16_000_000 => Pllrge::RANGE8,
588 x => panic!("pll ref_clk out of range: {} mhz", x),
589 };
590
591 // The smaller range (150 to 420 MHz) must
592 // be chosen when the reference clock frequency is lower than 2 MHz.
593 let wide_allowed = ref_range != Pllrge::RANGE1;
594
595 let vco_clk = ref_clk * config.mul;
596 let vco_range = if VCO_RANGE.contains(&vco_clk.0) {
597 Pllvcosel::MEDIUMVCO
598 } else if wide_allowed && VCO_WIDE_RANGE.contains(&vco_clk.0) {
599 Pllvcosel::WIDEVCO
600 } else {
601 panic!("pll vco_clk out of range: {} mhz", vco_clk.0)
602 };
603
604 let p = config.divp.map(|div| {
605 assert!(1 <= div && div <= 128);
606 if num == 0 {
607 // on PLL1, DIVP must be even.
608 assert!(div % 2 == 0);
609 }
610
611 vco_clk / div
612 });
613 let q = config.divq.map(|div| {
614 assert!(1 <= div && div <= 128);
615 vco_clk / div
616 });
617 let r = config.divr.map(|div| {
618 assert!(1 <= div && div <= 128);
619 vco_clk / div
620 });
621
622 #[cfg(stm32h5)]
623 RCC.pllcfgr(num).write(|w| {
624 w.set_pllsrc(src);
625 w.set_divm(config.prediv);
626 w.set_pllvcosel(vco_range);
627 w.set_pllrge(ref_range);
628 w.set_pllfracen(false);
629 w.set_pllpen(p.is_some());
630 w.set_pllqen(q.is_some());
631 w.set_pllren(r.is_some());
632 });
633
634 #[cfg(stm32h7)]
635 {
636 RCC.pllckselr().modify(|w| {
637 w.set_divm(num, config.prediv);
638 w.set_pllsrc(src);
639 });
640 RCC.pllcfgr().modify(|w| {
641 w.set_pllvcosel(num, vco_range);
642 w.set_pllrge(num, ref_range);
643 w.set_pllfracen(num, false);
644 w.set_divpen(num, p.is_some());
645 w.set_divqen(num, q.is_some());
646 w.set_divren(num, r.is_some());
647 });
648 }
649
650 RCC.plldivr(num).write(|w| {
651 w.set_plln(config.mul - 1);
652 w.set_pllp((config.divp.unwrap_or(1) - 1) as u8);
653 w.set_pllq((config.divq.unwrap_or(1) - 1) as u8);
654 w.set_pllr((config.divr.unwrap_or(1) - 1) as u8);
655 });
656
657 RCC.cr().modify(|w| w.set_pllon(num, true));
658 while !RCC.cr().read().pllrdy(num) {}
659
660 PllOutput { p, q, r }
661}
662
663fn flash_setup(clk: Hertz, vos: VoltageScale) {
664 // RM0481 Rev 1, table 37
665 // LATENCY WRHIGHFREQ VOS3 VOS2 VOS1 VOS0
666 // 0 0 0 to 20 MHz 0 to 30 MHz 0 to 34 MHz 0 to 42 MHz
667 // 1 0 20 to 40 MHz 30 to 60 MHz 34 to 68 MHz 42 to 84 MHz
668 // 2 1 40 to 60 MHz 60 to 90 MHz 68 to 102 MHz 84 to 126 MHz
669 // 3 1 60 to 80 MHz 90 to 120 MHz 102 to 136 MHz 126 to 168 MHz
670 // 4 2 80 to 100 MHz 120 to 150 MHz 136 to 170 MHz 168 to 210 MHz
671 // 5 2 170 to 200 MHz 210 to 250 MHz
672 #[cfg(stm32h5)]
673 let (latency, wrhighfreq) = match (vos, clk.0) {
674 (VoltageScale::Scale0, ..=42_000_000) => (0, 0),
675 (VoltageScale::Scale0, ..=84_000_000) => (1, 0),
676 (VoltageScale::Scale0, ..=126_000_000) => (2, 1),
677 (VoltageScale::Scale0, ..=168_000_000) => (3, 1),
678 (VoltageScale::Scale0, ..=210_000_000) => (4, 2),
679 (VoltageScale::Scale0, ..=250_000_000) => (5, 2),
680
681 (VoltageScale::Scale1, ..=34_000_000) => (0, 0),
682 (VoltageScale::Scale1, ..=68_000_000) => (1, 0),
683 (VoltageScale::Scale1, ..=102_000_000) => (2, 1),
684 (VoltageScale::Scale1, ..=136_000_000) => (3, 1),
685 (VoltageScale::Scale1, ..=170_000_000) => (4, 2),
686 (VoltageScale::Scale1, ..=200_000_000) => (5, 2),
687
688 (VoltageScale::Scale2, ..=30_000_000) => (0, 0),
689 (VoltageScale::Scale2, ..=60_000_000) => (1, 0),
690 (VoltageScale::Scale2, ..=90_000_000) => (2, 1),
691 (VoltageScale::Scale2, ..=120_000_000) => (3, 1),
692 (VoltageScale::Scale2, ..=150_000_000) => (4, 2),
693
694 (VoltageScale::Scale3, ..=20_000_000) => (0, 0),
695 (VoltageScale::Scale3, ..=40_000_000) => (1, 0),
696 (VoltageScale::Scale3, ..=60_000_000) => (2, 1),
697 (VoltageScale::Scale3, ..=80_000_000) => (3, 1),
698 (VoltageScale::Scale3, ..=100_000_000) => (4, 2),
699
700 _ => unreachable!(),
701 };
702
703 #[cfg(flash_h7)]
704 let (latency, wrhighfreq) = match (vos, clk.0) {
705 // VOS 0 range VCORE 1.26V - 1.40V
706 (VoltageScale::Scale0, ..=70_000_000) => (0, 0),
707 (VoltageScale::Scale0, ..=140_000_000) => (1, 1),
708 (VoltageScale::Scale0, ..=185_000_000) => (2, 1),
709 (VoltageScale::Scale0, ..=210_000_000) => (2, 2),
710 (VoltageScale::Scale0, ..=225_000_000) => (3, 2),
711 (VoltageScale::Scale0, ..=240_000_000) => (4, 2),
712 // VOS 1 range VCORE 1.15V - 1.26V
713 (VoltageScale::Scale1, ..=70_000_000) => (0, 0),
714 (VoltageScale::Scale1, ..=140_000_000) => (1, 1),
715 (VoltageScale::Scale1, ..=185_000_000) => (2, 1),
716 (VoltageScale::Scale1, ..=210_000_000) => (2, 2),
717 (VoltageScale::Scale1, ..=225_000_000) => (3, 2),
718 // VOS 2 range VCORE 1.05V - 1.15V
719 (VoltageScale::Scale2, ..=55_000_000) => (0, 0),
720 (VoltageScale::Scale2, ..=110_000_000) => (1, 1),
721 (VoltageScale::Scale2, ..=165_000_000) => (2, 1),
722 (VoltageScale::Scale2, ..=224_000_000) => (3, 2),
723 // VOS 3 range VCORE 0.95V - 1.05V
724 (VoltageScale::Scale3, ..=45_000_000) => (0, 0),
725 (VoltageScale::Scale3, ..=90_000_000) => (1, 1),
726 (VoltageScale::Scale3, ..=135_000_000) => (2, 1),
727 (VoltageScale::Scale3, ..=180_000_000) => (3, 2),
728 (VoltageScale::Scale3, ..=224_000_000) => (4, 2),
729 _ => unreachable!(),
730 };
731
732 // See RM0455 Rev 10 Table 16. FLASH recommended number of wait
733 // states and programming delay
734 #[cfg(flash_h7ab)]
735 let (latency, wrhighfreq) = match (vos, clk.0) {
736 // VOS 0 range VCORE 1.25V - 1.35V
737 (VoltageScale::Scale0, ..=42_000_000) => (0, 0),
738 (VoltageScale::Scale0, ..=84_000_000) => (1, 0),
739 (VoltageScale::Scale0, ..=126_000_000) => (2, 1),
740 (VoltageScale::Scale0, ..=168_000_000) => (3, 1),
741 (VoltageScale::Scale0, ..=210_000_000) => (4, 2),
742 (VoltageScale::Scale0, ..=252_000_000) => (5, 2),
743 (VoltageScale::Scale0, ..=280_000_000) => (6, 3),
744 // VOS 1 range VCORE 1.15V - 1.25V
745 (VoltageScale::Scale1, ..=38_000_000) => (0, 0),
746 (VoltageScale::Scale1, ..=76_000_000) => (1, 0),
747 (VoltageScale::Scale1, ..=114_000_000) => (2, 1),
748 (VoltageScale::Scale1, ..=152_000_000) => (3, 1),
749 (VoltageScale::Scale1, ..=190_000_000) => (4, 2),
750 (VoltageScale::Scale1, ..=225_000_000) => (5, 2),
751 // VOS 2 range VCORE 1.05V - 1.15V
752 (VoltageScale::Scale2, ..=34) => (0, 0),
753 (VoltageScale::Scale2, ..=68) => (1, 0),
754 (VoltageScale::Scale2, ..=102) => (2, 1),
755 (VoltageScale::Scale2, ..=136) => (3, 1),
756 (VoltageScale::Scale2, ..=160) => (4, 2),
757 // VOS 3 range VCORE 0.95V - 1.05V
758 (VoltageScale::Scale3, ..=22) => (0, 0),
759 (VoltageScale::Scale3, ..=44) => (1, 0),
760 (VoltageScale::Scale3, ..=66) => (2, 1),
761 (VoltageScale::Scale3, ..=88) => (3, 1),
762 _ => unreachable!(),
763 };
764
765 debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq);
766
767 FLASH.acr().write(|w| {
768 w.set_wrhighfreq(wrhighfreq);
769 w.set_latency(latency);
770 });
771 while FLASH.acr().read().latency() != latency {}
772}
diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs
deleted file mode 100644
index 2e72b1931..000000000
--- a/embassy-stm32/src/rcc/h5.rs
+++ /dev/null
@@ -1,511 +0,0 @@
1use core::marker::PhantomData;
2
3use stm32_metapac::rcc::vals::Timpre;
4
5use crate::pac::pwr::vals::Vos;
6use crate::pac::rcc::vals::{Hseext, Hsidiv, Mco1, Mco2, Pllrge, Pllsrc, Pllvcosel, Sw};
7use crate::pac::{FLASH, PWR, RCC};
8use crate::rcc::{set_freqs, Clocks};
9use crate::time::Hertz;
10use crate::{peripherals, Peripheral};
11
12/// HSI speed
13pub const HSI_FREQ: Hertz = Hertz(64_000_000);
14
15/// CSI speed
16pub const CSI_FREQ: Hertz = Hertz(4_000_000);
17
18/// HSI48 speed
19pub const HSI48_FREQ: Hertz = Hertz(48_000_000);
20
21/// LSI speed
22pub const LSI_FREQ: Hertz = Hertz(32_000);
23
24const VCO_MIN: u32 = 150_000_000;
25const VCO_MAX: u32 = 420_000_000;
26const VCO_WIDE_MIN: u32 = 128_000_000;
27const VCO_WIDE_MAX: u32 = 560_000_000;
28
29pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale};
30
31pub enum HseMode {
32 /// crystal/ceramic oscillator (HSEBYP=0)
33 Oscillator,
34 /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0)
35 BypassAnalog,
36 /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1)
37 BypassDigital,
38}
39
40pub struct Hse {
41 /// HSE frequency.
42 pub freq: Hertz,
43 /// HSE mode.
44 pub mode: HseMode,
45}
46
47pub enum Hsi {
48 /// 64Mhz
49 Mhz64,
50 /// 32Mhz (divided by 2)
51 Mhz32,
52 /// 16Mhz (divided by 4)
53 Mhz16,
54 /// 8Mhz (divided by 8)
55 Mhz8,
56}
57
58pub enum Sysclk {
59 /// HSI selected as sysclk
60 HSI,
61 /// HSE selected as sysclk
62 HSE,
63 /// CSI selected as sysclk
64 CSI,
65 /// PLL1_P selected as sysclk
66 Pll1P,
67}
68
69pub enum PllSource {
70 Hsi,
71 Csi,
72 Hse,
73}
74
75pub struct Pll {
76 /// Source clock selection.
77 pub source: PllSource,
78
79 /// PLL pre-divider (DIVM). Must be between 1 and 63.
80 pub prediv: u8,
81
82 /// PLL multiplication factor. Must be between 4 and 512.
83 pub mul: u16,
84
85 /// PLL P division factor. If None, PLL P output is disabled. Must be between 1 and 128.
86 /// On PLL1, it must be even (in particular, it cannot be 1.)
87 pub divp: Option<u16>,
88 /// PLL Q division factor. If None, PLL Q output is disabled. Must be between 1 and 128.
89 pub divq: Option<u16>,
90 /// PLL R division factor. If None, PLL R output is disabled. Must be between 1 and 128.
91 pub divr: Option<u16>,
92}
93
94impl APBPrescaler {
95 fn div_tim(&self, clk: Hertz, tim: TimerPrescaler) -> Hertz {
96 match (tim, self) {
97 // The timers kernel clock is equal to rcc_hclk1 if PPRE1 or PPRE2 corresponds to a
98 // division by 1 or 2, else it is equal to 2 x Frcc_pclk1 or 2 x Frcc_pclk2
99 (TimerPrescaler::DefaultX2, Self::NotDivided) => clk,
100 (TimerPrescaler::DefaultX2, Self::Div2) => clk,
101 (TimerPrescaler::DefaultX2, Self::Div4) => clk / 2u32,
102 (TimerPrescaler::DefaultX2, Self::Div8) => clk / 4u32,
103 (TimerPrescaler::DefaultX2, Self::Div16) => clk / 8u32,
104 // The timers kernel clock is equal to 2 x Frcc_pclk1 or 2 x Frcc_pclk2 if PPRE1 or PPRE2
105 // corresponds to a division by 1, 2 or 4, else it is equal to 4 x Frcc_pclk1 or 4 x Frcc_pclk2
106 // this makes NO SENSE and is different than in the H7. Mistake in the RM??
107 (TimerPrescaler::DefaultX4, Self::NotDivided) => clk * 2u32,
108 (TimerPrescaler::DefaultX4, Self::Div2) => clk,
109 (TimerPrescaler::DefaultX4, Self::Div4) => clk / 2u32,
110 (TimerPrescaler::DefaultX4, Self::Div8) => clk / 2u32,
111 (TimerPrescaler::DefaultX4, Self::Div16) => clk / 4u32,
112 }
113 }
114}
115
116/// APB prescaler
117#[derive(Clone, Copy)]
118pub enum TimerPrescaler {
119 DefaultX2,
120 DefaultX4,
121}
122
123impl From<TimerPrescaler> for Timpre {
124 fn from(value: TimerPrescaler) -> Self {
125 match value {
126 TimerPrescaler::DefaultX2 => Timpre::DEFAULTX2,
127 TimerPrescaler::DefaultX4 => Timpre::DEFAULTX4,
128 }
129 }
130}
131
132/// Configuration of the core clocks
133#[non_exhaustive]
134pub struct Config {
135 pub hsi: Option<Hsi>,
136 pub hse: Option<Hse>,
137 pub csi: bool,
138 pub hsi48: bool,
139 pub sys: Sysclk,
140
141 pub pll1: Option<Pll>,
142 pub pll2: Option<Pll>,
143 #[cfg(rcc_h5)]
144 pub pll3: Option<Pll>,
145
146 pub ahb_pre: AHBPrescaler,
147 pub apb1_pre: APBPrescaler,
148 pub apb2_pre: APBPrescaler,
149 pub apb3_pre: APBPrescaler,
150 pub timer_prescaler: TimerPrescaler,
151
152 pub voltage_scale: VoltageScale,
153}
154
155impl Default for Config {
156 fn default() -> Self {
157 Self {
158 hsi: Some(Hsi::Mhz64),
159 hse: None,
160 csi: false,
161 hsi48: false,
162 sys: Sysclk::HSI,
163 pll1: None,
164 pll2: None,
165 #[cfg(rcc_h5)]
166 pll3: None,
167
168 ahb_pre: AHBPrescaler::NotDivided,
169 apb1_pre: APBPrescaler::NotDivided,
170 apb2_pre: APBPrescaler::NotDivided,
171 apb3_pre: APBPrescaler::NotDivided,
172 timer_prescaler: TimerPrescaler::DefaultX2,
173
174 voltage_scale: VoltageScale::Scale3,
175 }
176 }
177}
178
179pub(crate) mod sealed {
180 pub trait McoInstance {
181 type Source;
182 unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8);
183 }
184}
185
186pub trait McoInstance: sealed::McoInstance + 'static {}
187
188pin_trait!(McoPin, McoInstance);
189
190macro_rules! impl_peri {
191 ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => {
192 impl sealed::McoInstance for peripherals::$peri {
193 type Source = $source;
194
195 unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8) {
196 RCC.cfgr().modify(|w| {
197 w.$set_source(source);
198 w.$set_prescaler(prescaler);
199 });
200 }
201 }
202
203 impl McoInstance for peripherals::$peri {}
204 };
205}
206
207impl_peri!(MCO1, Mco1, set_mco1, set_mco1pre);
208impl_peri!(MCO2, Mco2, set_mco2, set_mco2pre);
209
210pub struct Mco<'d, T: McoInstance> {
211 phantom: PhantomData<&'d mut T>,
212}
213
214impl<'d, T: McoInstance> Mco<'d, T> {
215 pub fn new(
216 _peri: impl Peripheral<P = T> + 'd,
217 _pin: impl Peripheral<P = impl McoPin<T>> + 'd,
218 _source: T::Source,
219 ) -> Self {
220 todo!();
221 }
222}
223
224pub(crate) unsafe fn init(config: Config) {
225 let (vos, max_clk) = match config.voltage_scale {
226 VoltageScale::Scale0 => (Vos::SCALE0, Hertz(250_000_000)),
227 VoltageScale::Scale1 => (Vos::SCALE1, Hertz(200_000_000)),
228 VoltageScale::Scale2 => (Vos::SCALE2, Hertz(150_000_000)),
229 VoltageScale::Scale3 => (Vos::SCALE3, Hertz(100_000_000)),
230 };
231
232 // Configure voltage scale.
233 PWR.voscr().modify(|w| w.set_vos(vos));
234 while !PWR.vossr().read().vosrdy() {}
235
236 // Configure HSI
237 let hsi = match config.hsi {
238 None => {
239 RCC.cr().modify(|w| w.set_hsion(false));
240 None
241 }
242 Some(hsi) => {
243 let (freq, hsidiv) = match hsi {
244 Hsi::Mhz64 => (HSI_FREQ / 1u32, Hsidiv::DIV1),
245 Hsi::Mhz32 => (HSI_FREQ / 2u32, Hsidiv::DIV2),
246 Hsi::Mhz16 => (HSI_FREQ / 4u32, Hsidiv::DIV4),
247 Hsi::Mhz8 => (HSI_FREQ / 8u32, Hsidiv::DIV8),
248 };
249 RCC.cr().modify(|w| {
250 w.set_hsidiv(hsidiv);
251 w.set_hsion(true);
252 });
253 while !RCC.cr().read().hsirdy() {}
254 Some(freq)
255 }
256 };
257
258 // Configure HSE
259 let hse = match config.hse {
260 None => {
261 RCC.cr().modify(|w| w.set_hseon(false));
262 None
263 }
264 Some(hse) => {
265 let (byp, ext) = match hse.mode {
266 HseMode::Oscillator => (false, Hseext::ANALOG),
267 HseMode::BypassAnalog => (true, Hseext::ANALOG),
268 HseMode::BypassDigital => (true, Hseext::DIGITAL),
269 };
270
271 RCC.cr().modify(|w| {
272 w.set_hsebyp(byp);
273 w.set_hseext(ext);
274 });
275 RCC.cr().modify(|w| w.set_hseon(true));
276 while !RCC.cr().read().hserdy() {}
277 Some(hse.freq)
278 }
279 };
280
281 // Configure HSI48.
282 RCC.cr().modify(|w| w.set_hsi48on(config.hsi48));
283 let _hsi48 = match config.hsi48 {
284 false => None,
285 true => {
286 while !RCC.cr().read().hsi48rdy() {}
287 Some(CSI_FREQ)
288 }
289 };
290
291 // Configure CSI.
292 RCC.cr().modify(|w| w.set_csion(config.csi));
293 let csi = match config.csi {
294 false => None,
295 true => {
296 while !RCC.cr().read().csirdy() {}
297 Some(CSI_FREQ)
298 }
299 };
300
301 // Configure PLLs.
302 let pll_input = PllInput { csi, hse, hsi };
303 let pll1 = init_pll(0, config.pll1, &pll_input);
304 let _pll2 = init_pll(1, config.pll2, &pll_input);
305 #[cfg(rcc_h5)]
306 let _pll3 = init_pll(2, config.pll3, &pll_input);
307
308 // Configure sysclk
309 let (sys, sw) = match config.sys {
310 Sysclk::HSI => (unwrap!(hsi), Sw::HSI),
311 Sysclk::HSE => (unwrap!(hse), Sw::HSE),
312 Sysclk::CSI => (unwrap!(csi), Sw::CSI),
313 Sysclk::Pll1P => (unwrap!(pll1.p), Sw::PLL1),
314 };
315 assert!(sys <= max_clk);
316
317 let hclk = sys / config.ahb_pre;
318
319 let apb1 = hclk / config.apb1_pre;
320 let apb1_tim = config.apb1_pre.div_tim(hclk, config.timer_prescaler);
321 let apb2 = hclk / config.apb2_pre;
322 let apb2_tim = config.apb2_pre.div_tim(hclk, config.timer_prescaler);
323 let apb3 = hclk / config.apb3_pre;
324
325 flash_setup(hclk, config.voltage_scale);
326
327 // Set hpre
328 let hpre = config.ahb_pre.into();
329 RCC.cfgr2().modify(|w| w.set_hpre(hpre));
330 while RCC.cfgr2().read().hpre() != hpre {}
331
332 // set ppre
333 RCC.cfgr2().modify(|w| {
334 w.set_ppre1(config.apb1_pre.into());
335 w.set_ppre2(config.apb2_pre.into());
336 w.set_ppre3(config.apb3_pre.into());
337 });
338
339 RCC.cfgr().modify(|w| w.set_timpre(config.timer_prescaler.into()));
340
341 RCC.cfgr().modify(|w| w.set_sw(sw));
342 while RCC.cfgr().read().sws() != sw {}
343
344 set_freqs(Clocks {
345 sys,
346 ahb1: hclk,
347 ahb2: hclk,
348 ahb3: hclk,
349 ahb4: hclk,
350 apb1,
351 apb2,
352 apb3,
353 apb1_tim,
354 apb2_tim,
355 adc: None,
356 });
357}
358
359struct PllInput {
360 hsi: Option<Hertz>,
361 hse: Option<Hertz>,
362 csi: Option<Hertz>,
363}
364
365struct PllOutput {
366 p: Option<Hertz>,
367 #[allow(dead_code)]
368 q: Option<Hertz>,
369 #[allow(dead_code)]
370 r: Option<Hertz>,
371}
372
373fn init_pll(num: usize, config: Option<Pll>, input: &PllInput) -> PllOutput {
374 let Some(config) = config else {
375 // Stop PLL
376 RCC.cr().modify(|w| w.set_pllon(num, false));
377 while RCC.cr().read().pllrdy(num) {}
378
379 // "To save power when PLL1 is not used, the value of PLL1M must be set to 0.""
380 RCC.pllcfgr(num).write(|w| {
381 w.set_divm(0);
382 });
383
384 return PllOutput {
385 p: None,
386 q: None,
387 r: None,
388 };
389 };
390
391 assert!(1 <= config.prediv && config.prediv <= 63);
392 assert!(4 <= config.mul && config.mul <= 512);
393
394 let (in_clk, src) = match config.source {
395 PllSource::Hsi => (unwrap!(input.hsi), Pllsrc::HSI),
396 PllSource::Hse => (unwrap!(input.hse), Pllsrc::HSE),
397 PllSource::Csi => (unwrap!(input.csi), Pllsrc::CSI),
398 };
399
400 let ref_clk = in_clk / config.prediv as u32;
401
402 let ref_range = match ref_clk.0 {
403 ..=1_999_999 => Pllrge::RANGE1,
404 ..=3_999_999 => Pllrge::RANGE2,
405 ..=7_999_999 => Pllrge::RANGE4,
406 ..=16_000_000 => Pllrge::RANGE8,
407 x => panic!("pll ref_clk out of range: {} mhz", x),
408 };
409
410 // The smaller range (150 to 420 MHz) must
411 // be chosen when the reference clock frequency is lower than 2 MHz.
412 let wide_allowed = ref_range != Pllrge::RANGE1;
413
414 let vco_clk = ref_clk * config.mul;
415 let vco_range = match vco_clk.0 {
416 VCO_MIN..=VCO_MAX => Pllvcosel::MEDIUMVCO,
417 VCO_WIDE_MIN..=VCO_WIDE_MAX if wide_allowed => Pllvcosel::WIDEVCO,
418 x => panic!("pll vco_clk out of range: {} mhz", x),
419 };
420
421 let p = config.divp.map(|div| {
422 assert!(1 <= div && div <= 128);
423 if num == 0 {
424 // on PLL1, DIVP must be even.
425 assert!(div % 2 == 0);
426 }
427
428 vco_clk / div
429 });
430 let q = config.divq.map(|div| {
431 assert!(1 <= div && div <= 128);
432 vco_clk / div
433 });
434 let r = config.divr.map(|div| {
435 assert!(1 <= div && div <= 128);
436 vco_clk / div
437 });
438
439 RCC.pllcfgr(num).write(|w| {
440 w.set_pllsrc(src);
441 w.set_divm(config.prediv);
442 w.set_pllvcosel(vco_range);
443 w.set_pllrge(ref_range);
444 w.set_pllfracen(false);
445 w.set_pllpen(p.is_some());
446 w.set_pllqen(q.is_some());
447 w.set_pllren(r.is_some());
448 });
449 RCC.plldivr(num).write(|w| {
450 w.set_plln(config.mul - 1);
451 w.set_pllp((config.divp.unwrap_or(1) - 1) as u8);
452 w.set_pllq((config.divq.unwrap_or(1) - 1) as u8);
453 w.set_pllr((config.divr.unwrap_or(1) - 1) as u8);
454 });
455
456 RCC.cr().modify(|w| w.set_pllon(num, true));
457 while !RCC.cr().read().pllrdy(num) {}
458
459 PllOutput { p, q, r }
460}
461
462fn flash_setup(clk: Hertz, vos: VoltageScale) {
463 // RM0481 Rev 1, table 37
464 // LATENCY WRHIGHFREQ VOS3 VOS2 VOS1 VOS0
465 // 0 0 0 to 20 MHz 0 to 30 MHz 0 to 34 MHz 0 to 42 MHz
466 // 1 0 20 to 40 MHz 30 to 60 MHz 34 to 68 MHz 42 to 84 MHz
467 // 2 1 40 to 60 MHz 60 to 90 MHz 68 to 102 MHz 84 to 126 MHz
468 // 3 1 60 to 80 MHz 90 to 120 MHz 102 to 136 MHz 126 to 168 MHz
469 // 4 2 80 to 100 MHz 120 to 150 MHz 136 to 170 MHz 168 to 210 MHz
470 // 5 2 170 to 200 MHz 210 to 250 MHz
471
472 // See RM0433 Rev 7 Table 17. FLASH recommended number of wait
473 // states and programming delay
474 let (latency, wrhighfreq) = match (vos, clk.0) {
475 (VoltageScale::Scale0, ..=42_000_000) => (0, 0),
476 (VoltageScale::Scale0, ..=84_000_000) => (1, 0),
477 (VoltageScale::Scale0, ..=126_000_000) => (2, 1),
478 (VoltageScale::Scale0, ..=168_000_000) => (3, 1),
479 (VoltageScale::Scale0, ..=210_000_000) => (4, 2),
480 (VoltageScale::Scale0, ..=250_000_000) => (5, 2),
481
482 (VoltageScale::Scale1, ..=34_000_000) => (0, 0),
483 (VoltageScale::Scale1, ..=68_000_000) => (1, 0),
484 (VoltageScale::Scale1, ..=102_000_000) => (2, 1),
485 (VoltageScale::Scale1, ..=136_000_000) => (3, 1),
486 (VoltageScale::Scale1, ..=170_000_000) => (4, 2),
487 (VoltageScale::Scale1, ..=200_000_000) => (5, 2),
488
489 (VoltageScale::Scale2, ..=30_000_000) => (0, 0),
490 (VoltageScale::Scale2, ..=60_000_000) => (1, 0),
491 (VoltageScale::Scale2, ..=90_000_000) => (2, 1),
492 (VoltageScale::Scale2, ..=120_000_000) => (3, 1),
493 (VoltageScale::Scale2, ..=150_000_000) => (4, 2),
494
495 (VoltageScale::Scale3, ..=20_000_000) => (0, 0),
496 (VoltageScale::Scale3, ..=40_000_000) => (1, 0),
497 (VoltageScale::Scale3, ..=60_000_000) => (2, 1),
498 (VoltageScale::Scale3, ..=80_000_000) => (3, 1),
499 (VoltageScale::Scale3, ..=100_000_000) => (4, 2),
500
501 _ => unreachable!(),
502 };
503
504 defmt::debug!("flash: latency={} wrhighfreq={}", latency, wrhighfreq);
505
506 FLASH.acr().write(|w| {
507 w.set_wrhighfreq(wrhighfreq);
508 w.set_latency(latency);
509 });
510 while FLASH.acr().read().latency() != latency {}
511}
diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs
deleted file mode 100644
index 7fb4fb95b..000000000
--- a/embassy-stm32/src/rcc/h7.rs
+++ /dev/null
@@ -1,879 +0,0 @@
1use core::marker::PhantomData;
2
3use embassy_hal_internal::into_ref;
4pub use pll::PllConfig;
5use stm32_metapac::rcc::vals::{Mco1, Mco2};
6
7use crate::gpio::sealed::AFType;
8use crate::gpio::Speed;
9use crate::pac::rcc::vals::{Adcsel, Ckpersel, Dppre, Hpre, Hsidiv, Pllsrc, Sw, Timpre};
10use crate::pac::{PWR, RCC, SYSCFG};
11use crate::rcc::{set_freqs, Clocks};
12use crate::time::Hertz;
13use crate::{peripherals, Peripheral};
14
15/// HSI speed
16pub const HSI_FREQ: Hertz = Hertz(64_000_000);
17
18/// CSI speed
19pub const CSI_FREQ: Hertz = Hertz(4_000_000);
20
21/// HSI48 speed
22pub const HSI48_FREQ: Hertz = Hertz(48_000_000);
23
24/// LSI speed
25pub const LSI_FREQ: Hertz = Hertz(32_000);
26
27pub use super::common::VoltageScale;
28
29#[derive(Clone, Copy)]
30pub enum AdcClockSource {
31 Pll2PCk,
32 Pll3RCk,
33 PerCk,
34}
35
36impl AdcClockSource {
37 pub fn adcsel(&self) -> Adcsel {
38 match self {
39 AdcClockSource::Pll2PCk => Adcsel::PLL2_P,
40 AdcClockSource::Pll3RCk => Adcsel::PLL3_R,
41 AdcClockSource::PerCk => Adcsel::PER,
42 }
43 }
44}
45
46impl Default for AdcClockSource {
47 fn default() -> Self {
48 Self::Pll2PCk
49 }
50}
51
52/// Core clock frequencies
53#[derive(Clone, Copy)]
54pub struct CoreClocks {
55 pub hclk: Hertz,
56 pub pclk1: Hertz,
57 pub pclk2: Hertz,
58 pub pclk3: Hertz,
59 pub pclk4: Hertz,
60 pub ppre1: u8,
61 pub ppre2: u8,
62 pub ppre3: u8,
63 pub ppre4: u8,
64 pub csi_ck: Option<Hertz>,
65 pub hsi_ck: Option<Hertz>,
66 pub hsi48_ck: Option<Hertz>,
67 pub lsi_ck: Option<Hertz>,
68 pub per_ck: Option<Hertz>,
69 pub hse_ck: Option<Hertz>,
70 pub pll1_p_ck: Option<Hertz>,
71 pub pll1_q_ck: Option<Hertz>,
72 pub pll1_r_ck: Option<Hertz>,
73 pub pll2_p_ck: Option<Hertz>,
74 pub pll2_q_ck: Option<Hertz>,
75 pub pll2_r_ck: Option<Hertz>,
76 pub pll3_p_ck: Option<Hertz>,
77 pub pll3_q_ck: Option<Hertz>,
78 pub pll3_r_ck: Option<Hertz>,
79 pub timx_ker_ck: Option<Hertz>,
80 pub timy_ker_ck: Option<Hertz>,
81 pub adc_ker_ck: Option<Hertz>,
82 pub sys_ck: Hertz,
83 pub c_ck: Hertz,
84}
85
86/// Configuration of the core clocks
87#[non_exhaustive]
88#[derive(Default)]
89pub struct Config {
90 pub hse: Option<Hertz>,
91 pub bypass_hse: bool,
92 pub sys_ck: Option<Hertz>,
93 pub per_ck: Option<Hertz>,
94 pub hclk: Option<Hertz>,
95 pub pclk1: Option<Hertz>,
96 pub pclk2: Option<Hertz>,
97 pub pclk3: Option<Hertz>,
98 pub pclk4: Option<Hertz>,
99 pub pll1: PllConfig,
100 pub pll2: PllConfig,
101 pub pll3: PllConfig,
102 pub adc_clock_source: AdcClockSource,
103}
104
105/// Setup traceclk
106/// Returns a pll1_r_ck
107fn traceclk_setup(config: &mut Config, sys_use_pll1_p: bool) {
108 let pll1_r_ck = match (sys_use_pll1_p, config.pll1.r_ck) {
109 // pll1_p_ck selected as system clock but pll1_r_ck not
110 // set. The traceclk mux is synchronous with the system
111 // clock mux, but has pll1_r_ck as an input. In order to
112 // keep traceclk running, we force a pll1_r_ck.
113 (true, None) => Some(Hertz(unwrap!(config.pll1.p_ck).0 / 2)),
114
115 // Either pll1 not selected as system clock, free choice
116 // of pll1_r_ck. Or pll1 is selected, assume user has set
117 // a suitable pll1_r_ck frequency.
118 _ => config.pll1.r_ck,
119 };
120 config.pll1.r_ck = pll1_r_ck;
121}
122
123/// Divider calculator for pclk 1 - 4
124///
125/// Returns real pclk, bits, ppre and the timer kernel clock
126fn ppre_calculate(
127 requested_pclk: u32,
128 hclk: u32,
129 max_pclk: u32,
130 tim_pre: Option<Timpre>,
131) -> (u32, u8, u8, Option<u32>) {
132 let (bits, ppre) = match (hclk + requested_pclk - 1) / requested_pclk {
133 0 => panic!(),
134 1 => (0b000, 1),
135 2 => (0b100, 2),
136 3..=5 => (0b101, 4),
137 6..=11 => (0b110, 8),
138 _ => (0b111, 16),
139 };
140 let real_pclk = hclk / u32::from(ppre);
141 assert!(real_pclk <= max_pclk);
142
143 let tim_ker_clk = if let Some(tim_pre) = tim_pre {
144 let clk = match (bits, tim_pre) {
145 (0b101, Timpre::DEFAULTX2) => hclk / 2,
146 (0b110, Timpre::DEFAULTX4) => hclk / 2,
147 (0b110, Timpre::DEFAULTX2) => hclk / 4,
148 (0b111, Timpre::DEFAULTX4) => hclk / 4,
149 (0b111, Timpre::DEFAULTX2) => hclk / 8,
150 _ => hclk,
151 };
152 Some(clk)
153 } else {
154 None
155 };
156 (real_pclk, bits, ppre, tim_ker_clk)
157}
158
159/// Setup sys_ck
160/// Returns sys_ck frequency, and a pll1_p_ck
161fn sys_ck_setup(config: &mut Config, srcclk: Hertz) -> (Hertz, bool) {
162 // Compare available with wanted clocks
163 let sys_ck = config.sys_ck.unwrap_or(srcclk);
164
165 if sys_ck != srcclk {
166 // The requested system clock is not the immediately available
167 // HSE/HSI clock. Perhaps there are other ways of obtaining
168 // the requested system clock (such as `HSIDIV`) but we will
169 // ignore those for now.
170 //
171 // Therefore we must use pll1_p_ck
172 let pll1_p_ck = match config.pll1.p_ck {
173 Some(p_ck) => {
174 assert!(
175 p_ck == sys_ck,
176 "Error: Cannot set pll1_p_ck independently as it must be used to generate sys_ck"
177 );
178 Some(p_ck)
179 }
180 None => Some(sys_ck),
181 };
182 config.pll1.p_ck = pll1_p_ck;
183
184 (sys_ck, true)
185 } else {
186 // sys_ck is derived directly from a source clock
187 // (HSE/HSI). pll1_p_ck can be as requested
188 (sys_ck, false)
189 }
190}
191
192fn flash_setup(rcc_aclk: u32, vos: VoltageScale) {
193 use crate::pac::FLASH;
194
195 // ACLK in MHz, round down and subtract 1 from integers. eg.
196 // 61_999_999 -> 61MHz
197 // 62_000_000 -> 61MHz
198 // 62_000_001 -> 62MHz
199 let rcc_aclk_mhz = (rcc_aclk - 1) / 1_000_000;
200
201 // See RM0433 Rev 7 Table 17. FLASH recommended number of wait
202 // states and programming delay
203 #[cfg(flash_h7)]
204 let (wait_states, progr_delay) = match vos {
205 // VOS 0 range VCORE 1.26V - 1.40V
206 VoltageScale::Scale0 => match rcc_aclk_mhz {
207 0..=69 => (0, 0),
208 70..=139 => (1, 1),
209 140..=184 => (2, 1),
210 185..=209 => (2, 2),
211 210..=224 => (3, 2),
212 225..=239 => (4, 2),
213 _ => (7, 3),
214 },
215 // VOS 1 range VCORE 1.15V - 1.26V
216 VoltageScale::Scale1 => match rcc_aclk_mhz {
217 0..=69 => (0, 0),
218 70..=139 => (1, 1),
219 140..=184 => (2, 1),
220 185..=209 => (2, 2),
221 210..=224 => (3, 2),
222 _ => (7, 3),
223 },
224 // VOS 2 range VCORE 1.05V - 1.15V
225 VoltageScale::Scale2 => match rcc_aclk_mhz {
226 0..=54 => (0, 0),
227 55..=109 => (1, 1),
228 110..=164 => (2, 1),
229 165..=224 => (3, 2),
230 _ => (7, 3),
231 },
232 // VOS 3 range VCORE 0.95V - 1.05V
233 VoltageScale::Scale3 => match rcc_aclk_mhz {
234 0..=44 => (0, 0),
235 45..=89 => (1, 1),
236 90..=134 => (2, 1),
237 135..=179 => (3, 2),
238 180..=224 => (4, 2),
239 _ => (7, 3),
240 },
241 };
242
243 // See RM0455 Rev 10 Table 16. FLASH recommended number of wait
244 // states and programming delay
245 #[cfg(flash_h7ab)]
246 let (wait_states, progr_delay) = match vos {
247 // VOS 0 range VCORE 1.25V - 1.35V
248 VoltageScale::Scale0 => match rcc_aclk_mhz {
249 0..=42 => (0, 0),
250 43..=84 => (1, 0),
251 85..=126 => (2, 1),
252 127..=168 => (3, 1),
253 169..=210 => (4, 2),
254 211..=252 => (5, 2),
255 253..=280 => (6, 3),
256 _ => (7, 3),
257 },
258 // VOS 1 range VCORE 1.15V - 1.25V
259 VoltageScale::Scale1 => match rcc_aclk_mhz {
260 0..=38 => (0, 0),
261 39..=76 => (1, 0),
262 77..=114 => (2, 1),
263 115..=152 => (3, 1),
264 153..=190 => (4, 2),
265 191..=225 => (5, 2),
266 _ => (7, 3),
267 },
268 // VOS 2 range VCORE 1.05V - 1.15V
269 VoltageScale::Scale2 => match rcc_aclk_mhz {
270 0..=34 => (0, 0),
271 35..=68 => (1, 0),
272 69..=102 => (2, 1),
273 103..=136 => (3, 1),
274 137..=160 => (4, 2),
275 _ => (7, 3),
276 },
277 // VOS 3 range VCORE 0.95V - 1.05V
278 VoltageScale::Scale3 => match rcc_aclk_mhz {
279 0..=22 => (0, 0),
280 23..=44 => (1, 0),
281 45..=66 => (2, 1),
282 67..=88 => (3, 1),
283 _ => (7, 3),
284 },
285 };
286
287 FLASH.acr().write(|w| {
288 w.set_wrhighfreq(progr_delay);
289 w.set_latency(wait_states)
290 });
291 while FLASH.acr().read().latency() != wait_states {}
292}
293
294pub enum McoClock {
295 Disabled,
296 Bypassed,
297 Divided(u8),
298}
299
300impl McoClock {
301 fn into_raw(&self) -> u8 {
302 match self {
303 McoClock::Disabled => 0,
304 McoClock::Bypassed => 1,
305 McoClock::Divided(divisor) => {
306 if *divisor > 15 {
307 panic!("Mco divisor must be less than 15. Refer to the reference manual for more information.")
308 }
309 *divisor
310 }
311 }
312 }
313}
314
315#[derive(Copy, Clone)]
316pub enum Mco1Source {
317 Hsi,
318 Lse,
319 Hse,
320 Pll1Q,
321 Hsi48,
322}
323
324impl Default for Mco1Source {
325 fn default() -> Self {
326 Self::Hsi
327 }
328}
329
330pub trait McoSource {
331 type Raw;
332
333 fn into_raw(&self) -> Self::Raw;
334}
335
336impl McoSource for Mco1Source {
337 type Raw = Mco1;
338 fn into_raw(&self) -> Self::Raw {
339 match self {
340 Mco1Source::Hsi => Mco1::HSI,
341 Mco1Source::Lse => Mco1::LSE,
342 Mco1Source::Hse => Mco1::HSE,
343 Mco1Source::Pll1Q => Mco1::PLL1_Q,
344 Mco1Source::Hsi48 => Mco1::HSI48,
345 }
346 }
347}
348
349#[derive(Copy, Clone)]
350pub enum Mco2Source {
351 SysClk,
352 Pll2Q,
353 Hse,
354 Pll1Q,
355 Csi,
356 Lsi,
357}
358
359impl Default for Mco2Source {
360 fn default() -> Self {
361 Self::SysClk
362 }
363}
364
365impl McoSource for Mco2Source {
366 type Raw = Mco2;
367 fn into_raw(&self) -> Self::Raw {
368 match self {
369 Mco2Source::SysClk => Mco2::SYSCLK,
370 Mco2Source::Pll2Q => Mco2::PLL2_P,
371 Mco2Source::Hse => Mco2::HSE,
372 Mco2Source::Pll1Q => Mco2::PLL1_P,
373 Mco2Source::Csi => Mco2::CSI,
374 Mco2Source::Lsi => Mco2::LSI,
375 }
376 }
377}
378
379pub(crate) mod sealed {
380 pub trait McoInstance {
381 type Source;
382 unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8);
383 }
384}
385
386pub trait McoInstance: sealed::McoInstance + 'static {}
387
388pin_trait!(McoPin, McoInstance);
389
390macro_rules! impl_peri {
391 ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => {
392 impl sealed::McoInstance for peripherals::$peri {
393 type Source = $source;
394
395 unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8) {
396 RCC.cfgr().modify(|w| {
397 w.$set_source(source);
398 w.$set_prescaler(prescaler);
399 });
400 }
401 }
402
403 impl McoInstance for peripherals::$peri {}
404 };
405}
406
407impl_peri!(MCO1, Mco1, set_mco1, set_mco1pre);
408impl_peri!(MCO2, Mco2, set_mco2, set_mco2pre);
409
410pub struct Mco<'d, T: McoInstance> {
411 phantom: PhantomData<&'d mut T>,
412}
413
414impl<'d, T: McoInstance> Mco<'d, T> {
415 pub fn new(
416 _peri: impl Peripheral<P = T> + 'd,
417 pin: impl Peripheral<P = impl McoPin<T>> + 'd,
418 source: impl McoSource<Raw = T::Source>,
419 prescaler: McoClock,
420 ) -> Self {
421 into_ref!(pin);
422
423 critical_section::with(|_| unsafe {
424 T::apply_clock_settings(source.into_raw(), prescaler.into_raw());
425 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
426 pin.set_speed(Speed::VeryHigh);
427 });
428
429 Self { phantom: PhantomData }
430 }
431}
432
433pub(crate) unsafe fn init(mut config: Config) {
434 // TODO make configurable?
435 let enable_overdrive = false;
436
437 // NB. The lower bytes of CR3 can only be written once after
438 // POR, and must be written with a valid combination. Refer to
439 // RM0433 Rev 7 6.8.4. This is partially enforced by dropping
440 // `self` at the end of this method, but of course we cannot
441 // know what happened between the previous POR and here.
442 #[cfg(pwr_h7)]
443 PWR.cr3().modify(|w| {
444 w.set_scuen(true);
445 w.set_ldoen(true);
446 w.set_bypass(false);
447 });
448
449 #[cfg(pwr_h7smps)]
450 PWR.cr3().modify(|w| {
451 // hardcode "Direct SPMS" for now, this is what works on nucleos with the
452 // default solderbridge configuration.
453 w.set_sden(true);
454 w.set_ldoen(false);
455 });
456
457 // Validate the supply configuration. If you are stuck here, it is
458 // because the voltages on your board do not match those specified
459 // in the D3CR.VOS and CR3.SDLEVEL fields. By default after reset
460 // VOS = Scale 3, so check that the voltage on the VCAP pins =
461 // 1.0V.
462 while !PWR.csr1().read().actvosrdy() {}
463
464 // Go to Scale 1
465 PWR.d3cr().modify(|w| w.set_vos(0b11));
466 while !PWR.d3cr().read().vosrdy() {}
467
468 let pwr_vos = if !enable_overdrive {
469 VoltageScale::Scale1
470 } else {
471 critical_section::with(|_| {
472 RCC.apb4enr().modify(|w| w.set_syscfgen(true));
473
474 SYSCFG.pwrcr().modify(|w| w.set_oden(1));
475 });
476 while !PWR.d3cr().read().vosrdy() {}
477 VoltageScale::Scale0
478 };
479
480 // Freeze the core clocks, returning a Core Clocks Distribution
481 // and Reset (CCDR) structure. The actual frequency of the clocks
482 // configured is returned in the `clocks` member of the CCDR
483 // structure.
484 //
485 // Note that `freeze` will never result in a clock _faster_ than
486 // that specified. It may result in a clock that is a factor of [1,
487 // 2) slower.
488 //
489 // `syscfg` is required to enable the I/O compensation cell.
490 //
491 // # Panics
492 //
493 // If a clock specification cannot be achieved within the
494 // hardware specification then this function will panic. This
495 // function may also panic if a clock specification can be
496 // achieved, but the mechanism for doing so is not yet
497 // implemented here.
498
499 let srcclk = config.hse.unwrap_or(HSI_FREQ); // Available clocks
500 let (sys_ck, sys_use_pll1_p) = sys_ck_setup(&mut config, srcclk);
501
502 // Configure traceclk from PLL if needed
503 traceclk_setup(&mut config, sys_use_pll1_p);
504
505 let (pll1_p_ck, pll1_q_ck, pll1_r_ck) = pll::pll_setup(srcclk.0, &config.pll1, 0);
506 let (pll2_p_ck, pll2_q_ck, pll2_r_ck) = pll::pll_setup(srcclk.0, &config.pll2, 1);
507 let (pll3_p_ck, pll3_q_ck, pll3_r_ck) = pll::pll_setup(srcclk.0, &config.pll3, 2);
508
509 let sys_ck = if sys_use_pll1_p {
510 Hertz(unwrap!(pll1_p_ck)) // Must have been set by sys_ck_setup
511 } else {
512 sys_ck
513 };
514
515 // This routine does not support HSIDIV != 1. To
516 // do so it would need to ensure all PLLxON bits are clear
517 // before changing the value of HSIDIV
518 let cr = RCC.cr().read();
519 assert!(cr.hsion());
520 assert!(cr.hsidiv() == Hsidiv::DIV1);
521
522 RCC.csr().modify(|w| w.set_lsion(true));
523 while !RCC.csr().read().lsirdy() {}
524
525 // per_ck from HSI by default
526 let (per_ck, ckpersel) = match (config.per_ck == config.hse, config.per_ck) {
527 (true, Some(hse)) => (hse, Ckpersel::HSE), // HSE
528 (_, Some(CSI_FREQ)) => (CSI_FREQ, Ckpersel::CSI), // CSI
529 _ => (HSI_FREQ, Ckpersel::HSI), // HSI
530 };
531
532 // D1 Core Prescaler
533 // Set to 1
534 let d1cpre_bits = 0;
535 let d1cpre_div = 1;
536 let sys_d1cpre_ck = sys_ck.0 / d1cpre_div;
537
538 // Refer to part datasheet "General operating conditions"
539 // table for (rev V). We do not assert checks for earlier
540 // revisions which may have lower limits.
541 let (sys_d1cpre_ck_max, rcc_hclk_max, pclk_max) = match pwr_vos {
542 VoltageScale::Scale0 => (480_000_000, 240_000_000, 120_000_000),
543 VoltageScale::Scale1 => (400_000_000, 200_000_000, 100_000_000),
544 VoltageScale::Scale2 => (300_000_000, 150_000_000, 75_000_000),
545 _ => (200_000_000, 100_000_000, 50_000_000),
546 };
547 assert!(sys_d1cpre_ck <= sys_d1cpre_ck_max);
548
549 let rcc_hclk = config.hclk.map(|v| v.0).unwrap_or(sys_d1cpre_ck / 2);
550 assert!(rcc_hclk <= rcc_hclk_max);
551
552 // Estimate divisor
553 let (hpre_bits, hpre_div) = match (sys_d1cpre_ck + rcc_hclk - 1) / rcc_hclk {
554 0 => panic!(),
555 1 => (Hpre::DIV1, 1),
556 2 => (Hpre::DIV2, 2),
557 3..=5 => (Hpre::DIV4, 4),
558 6..=11 => (Hpre::DIV8, 8),
559 12..=39 => (Hpre::DIV16, 16),
560 40..=95 => (Hpre::DIV64, 64),
561 96..=191 => (Hpre::DIV128, 128),
562 192..=383 => (Hpre::DIV256, 256),
563 _ => (Hpre::DIV512, 512),
564 };
565 // Calculate real AXI and AHB clock
566 let rcc_hclk = sys_d1cpre_ck / hpre_div;
567 assert!(rcc_hclk <= rcc_hclk_max);
568 let rcc_aclk = rcc_hclk; // AXI clock is always equal to AHB clock on H7
569 // Timer prescaler selection
570 let timpre = Timpre::DEFAULTX2;
571
572 let requested_pclk1 = config.pclk1.map(|v| v.0).unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
573 let (rcc_pclk1, ppre1_bits, ppre1, rcc_timerx_ker_ck) =
574 ppre_calculate(requested_pclk1, rcc_hclk, pclk_max, Some(timpre));
575
576 let requested_pclk2 = config.pclk2.map(|v| v.0).unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
577 let (rcc_pclk2, ppre2_bits, ppre2, rcc_timery_ker_ck) =
578 ppre_calculate(requested_pclk2, rcc_hclk, pclk_max, Some(timpre));
579
580 let requested_pclk3 = config.pclk3.map(|v| v.0).unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
581 let (rcc_pclk3, ppre3_bits, ppre3, _) = ppre_calculate(requested_pclk3, rcc_hclk, pclk_max, None);
582
583 let requested_pclk4 = config.pclk4.map(|v| v.0).unwrap_or_else(|| pclk_max.min(rcc_hclk / 2));
584 let (rcc_pclk4, ppre4_bits, ppre4, _) = ppre_calculate(requested_pclk4, rcc_hclk, pclk_max, None);
585
586 // Start switching clocks -------------------
587
588 // Ensure CSI is on and stable
589 RCC.cr().modify(|w| w.set_csion(true));
590 while !RCC.cr().read().csirdy() {}
591
592 // Ensure HSI48 is on and stable
593 RCC.cr().modify(|w| w.set_hsi48on(true));
594 while !RCC.cr().read().hsi48on() {}
595
596 // XXX: support MCO ?
597
598 let hse_ck = match config.hse {
599 Some(hse) => {
600 // Ensure HSE is on and stable
601 RCC.cr().modify(|w| {
602 w.set_hseon(true);
603 w.set_hsebyp(config.bypass_hse);
604 });
605 while !RCC.cr().read().hserdy() {}
606 Some(hse)
607 }
608 None => None,
609 };
610
611 let pllsrc = if config.hse.is_some() { Pllsrc::HSE } else { Pllsrc::HSI };
612 RCC.pllckselr().modify(|w| w.set_pllsrc(pllsrc));
613
614 let enable_pll = |pll| {
615 RCC.cr().modify(|w| w.set_pllon(pll, true));
616 while !RCC.cr().read().pllrdy(pll) {}
617 };
618
619 if pll1_p_ck.is_some() {
620 enable_pll(0);
621 }
622
623 if pll2_p_ck.is_some() {
624 enable_pll(1);
625 }
626
627 if pll3_p_ck.is_some() {
628 enable_pll(2);
629 }
630
631 // Core Prescaler / AHB Prescaler / APB3 Prescaler
632 RCC.d1cfgr().modify(|w| {
633 w.set_d1cpre(Hpre::from_bits(d1cpre_bits));
634 w.set_d1ppre(Dppre::from_bits(ppre3_bits));
635 w.set_hpre(hpre_bits)
636 });
637 // Ensure core prescaler value is valid before future lower
638 // core voltage
639 while RCC.d1cfgr().read().d1cpre().to_bits() != d1cpre_bits {}
640
641 flash_setup(rcc_aclk, pwr_vos);
642
643 // APB1 / APB2 Prescaler
644 RCC.d2cfgr().modify(|w| {
645 w.set_d2ppre1(Dppre::from_bits(ppre1_bits));
646 w.set_d2ppre2(Dppre::from_bits(ppre2_bits));
647 });
648
649 // APB4 Prescaler
650 RCC.d3cfgr().modify(|w| w.set_d3ppre(Dppre::from_bits(ppre4_bits)));
651
652 // Peripheral Clock (per_ck)
653 RCC.d1ccipr().modify(|w| w.set_ckpersel(ckpersel));
654
655 // ADC clock MUX
656 RCC.d3ccipr().modify(|w| w.set_adcsel(config.adc_clock_source.adcsel()));
657
658 let adc_ker_ck = match config.adc_clock_source {
659 AdcClockSource::Pll2PCk => pll2_p_ck.map(Hertz),
660 AdcClockSource::Pll3RCk => pll3_r_ck.map(Hertz),
661 AdcClockSource::PerCk => Some(per_ck),
662 };
663
664 // Set timer clocks prescaler setting
665 RCC.cfgr().modify(|w| w.set_timpre(timpre));
666
667 // Select system clock source
668 let sw = match (sys_use_pll1_p, config.hse.is_some()) {
669 (true, _) => Sw::PLL1,
670 (false, true) => Sw::HSE,
671 _ => Sw::HSI,
672 };
673 RCC.cfgr().modify(|w| w.set_sw(sw));
674 while RCC.cfgr().read().sws().to_bits() != sw.to_bits() {}
675
676 // IO compensation cell - Requires CSI clock and SYSCFG
677 assert!(RCC.cr().read().csirdy());
678 RCC.apb4enr().modify(|w| w.set_syscfgen(true));
679
680 // Enable the compensation cell, using back-bias voltage code
681 // provide by the cell.
682 critical_section::with(|_| {
683 SYSCFG.cccsr().modify(|w| {
684 w.set_en(true);
685 w.set_cs(false);
686 w.set_hslv(false);
687 })
688 });
689 while !SYSCFG.cccsr().read().ready() {}
690
691 let core_clocks = CoreClocks {
692 hclk: Hertz(rcc_hclk),
693 pclk1: Hertz(rcc_pclk1),
694 pclk2: Hertz(rcc_pclk2),
695 pclk3: Hertz(rcc_pclk3),
696 pclk4: Hertz(rcc_pclk4),
697 ppre1,
698 ppre2,
699 ppre3,
700 ppre4,
701 csi_ck: Some(CSI_FREQ),
702 hsi_ck: Some(HSI_FREQ),
703 hsi48_ck: Some(HSI48_FREQ),
704 lsi_ck: Some(LSI_FREQ),
705 per_ck: Some(per_ck),
706 hse_ck,
707 pll1_p_ck: pll1_p_ck.map(Hertz),
708 pll1_q_ck: pll1_q_ck.map(Hertz),
709 pll1_r_ck: pll1_r_ck.map(Hertz),
710 pll2_p_ck: pll2_p_ck.map(Hertz),
711 pll2_q_ck: pll2_q_ck.map(Hertz),
712 pll2_r_ck: pll2_r_ck.map(Hertz),
713 pll3_p_ck: pll3_p_ck.map(Hertz),
714 pll3_q_ck: pll3_q_ck.map(Hertz),
715 pll3_r_ck: pll3_r_ck.map(Hertz),
716 timx_ker_ck: rcc_timerx_ker_ck.map(Hertz),
717 timy_ker_ck: rcc_timery_ker_ck.map(Hertz),
718 adc_ker_ck,
719 sys_ck,
720 c_ck: Hertz(sys_d1cpre_ck),
721 };
722
723 set_freqs(Clocks {
724 sys: core_clocks.c_ck,
725 ahb1: core_clocks.hclk,
726 ahb2: core_clocks.hclk,
727 ahb3: core_clocks.hclk,
728 ahb4: core_clocks.hclk,
729 apb1: core_clocks.pclk1,
730 apb2: core_clocks.pclk2,
731 apb4: core_clocks.pclk4,
732 apb1_tim: core_clocks.timx_ker_ck.unwrap_or(core_clocks.pclk1),
733 apb2_tim: core_clocks.timy_ker_ck.unwrap_or(core_clocks.pclk2),
734 adc: core_clocks.adc_ker_ck,
735 });
736}
737
738mod pll {
739 use super::{Hertz, RCC};
740
741 const VCO_MIN: u32 = 150_000_000;
742 const VCO_MAX: u32 = 420_000_000;
743
744 #[derive(Default)]
745 pub struct PllConfig {
746 pub p_ck: Option<Hertz>,
747 pub q_ck: Option<Hertz>,
748 pub r_ck: Option<Hertz>,
749 }
750
751 pub(super) struct PllConfigResults {
752 pub ref_x_ck: u32,
753 pub pll_x_m: u32,
754 pub pll_x_p: u32,
755 pub vco_ck_target: u32,
756 }
757
758 fn vco_output_divider_setup(output: u32, plln: usize) -> (u32, u32) {
759 let pll_x_p = if plln == 0 {
760 if output > VCO_MAX / 2 {
761 1
762 } else {
763 ((VCO_MAX / output) | 1) - 1 // Must be even or unity
764 }
765 } else {
766 // Specific to PLL2/3, will subtract 1 later
767 if output > VCO_MAX / 2 {
768 1
769 } else {
770 VCO_MAX / output
771 }
772 };
773
774 let vco_ck = output * pll_x_p;
775
776 assert!(pll_x_p < 128);
777 assert!(vco_ck >= VCO_MIN);
778 assert!(vco_ck <= VCO_MAX);
779
780 (vco_ck, pll_x_p)
781 }
782
783 /// # Safety
784 ///
785 /// Must have exclusive access to the RCC register block
786 fn vco_setup(pll_src: u32, requested_output: u32, plln: usize) -> PllConfigResults {
787 use crate::pac::rcc::vals::{Pllrge, Pllvcosel};
788
789 let (vco_ck_target, pll_x_p) = vco_output_divider_setup(requested_output, plln);
790
791 // Input divisor, resulting in a reference clock in the range
792 // 1 to 2 MHz. Choose the highest reference clock (lowest m)
793 let pll_x_m = (pll_src + 1_999_999) / 2_000_000;
794 assert!(pll_x_m < 64);
795
796 // Calculate resulting reference clock
797 let ref_x_ck = pll_src / pll_x_m;
798 assert!((1_000_000..=2_000_000).contains(&ref_x_ck));
799
800 RCC.pllcfgr().modify(|w| {
801 w.set_pllvcosel(plln, Pllvcosel::MEDIUMVCO);
802 w.set_pllrge(plln, Pllrge::RANGE1);
803 });
804 PllConfigResults {
805 ref_x_ck,
806 pll_x_m,
807 pll_x_p,
808 vco_ck_target,
809 }
810 }
811
812 /// # Safety
813 ///
814 /// Must have exclusive access to the RCC register block
815 pub(super) fn pll_setup(pll_src: u32, config: &PllConfig, plln: usize) -> (Option<u32>, Option<u32>, Option<u32>) {
816 use crate::pac::rcc::vals::Divp;
817
818 match config.p_ck {
819 Some(requested_output) => {
820 let config_results = vco_setup(pll_src, requested_output.0, plln);
821 let PllConfigResults {
822 ref_x_ck,
823 pll_x_m,
824 pll_x_p,
825 vco_ck_target,
826 } = config_results;
827
828 RCC.pllckselr().modify(|w| w.set_divm(plln, pll_x_m as u8));
829
830 // Feedback divider. Integer only
831 let pll_x_n = vco_ck_target / ref_x_ck;
832 assert!(pll_x_n >= 4);
833 assert!(pll_x_n <= 512);
834 RCC.plldivr(plln).modify(|w| w.set_divn1((pll_x_n - 1) as u16));
835
836 // No FRACN
837 RCC.pllcfgr().modify(|w| w.set_pllfracen(plln, false));
838 let vco_ck = ref_x_ck * pll_x_n;
839
840 RCC.plldivr(plln)
841 .modify(|w| w.set_divp1(Divp::from_bits((pll_x_p - 1) as u8)));
842 RCC.pllcfgr().modify(|w| w.set_divpen(plln, true));
843
844 // Calulate additional output dividers
845 let q_ck = match config.q_ck {
846 Some(Hertz(ck)) if ck > 0 => {
847 let div = (vco_ck + ck - 1) / ck;
848 RCC.plldivr(plln).modify(|w| w.set_divq1((div - 1) as u8));
849 RCC.pllcfgr().modify(|w| w.set_divqen(plln, true));
850 Some(vco_ck / div)
851 }
852 _ => None,
853 };
854 let r_ck = match config.r_ck {
855 Some(Hertz(ck)) if ck > 0 => {
856 let div = (vco_ck + ck - 1) / ck;
857 RCC.plldivr(plln).modify(|w| w.set_divr1((div - 1) as u8));
858 RCC.pllcfgr().modify(|w| w.set_divren(plln, true));
859 Some(vco_ck / div)
860 }
861 _ => None,
862 };
863
864 (Some(vco_ck / pll_x_p), q_ck, r_ck)
865 }
866 None => {
867 assert!(
868 config.q_ck.is_none(),
869 "Must set PLL P clock for Q clock to take effect!"
870 );
871 assert!(
872 config.r_ck.is_none(),
873 "Must set PLL P clock for R clock to take effect!"
874 );
875 (None, None, None)
876 }
877 }
878 }
879}
diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs
index 46b58ca7c..7358be31b 100644
--- a/embassy-stm32/src/rcc/l0.rs
+++ b/embassy-stm32/src/rcc/l0.rs
@@ -1,8 +1,11 @@
1pub use super::common::{AHBPrescaler, APBPrescaler}; 1use super::bd::BackupDomain;
2pub use super::bus::{AHBPrescaler, APBPrescaler};
3use super::RtcClockSource;
4pub use crate::pac::pwr::vals::Vos as VoltageScale;
2use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; 5use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
3use crate::pac::RCC;
4#[cfg(crs)] 6#[cfg(crs)]
5use crate::pac::{crs, CRS, SYSCFG}; 7use crate::pac::{crs, CRS, SYSCFG};
8use crate::pac::{FLASH, PWR, RCC};
6use crate::rcc::{set_freqs, Clocks}; 9use crate::rcc::{set_freqs, Clocks};
7use crate::time::Hertz; 10use crate::time::Hertz;
8 11
@@ -135,6 +138,10 @@ pub struct Config {
135 pub apb2_pre: APBPrescaler, 138 pub apb2_pre: APBPrescaler,
136 #[cfg(crs)] 139 #[cfg(crs)]
137 pub enable_hsi48: bool, 140 pub enable_hsi48: bool,
141 pub rtc: Option<RtcClockSource>,
142 pub lse: Option<Hertz>,
143 pub lsi: bool,
144 pub voltage_scale: VoltageScale,
138} 145}
139 146
140impl Default for Config { 147impl Default for Config {
@@ -142,16 +149,25 @@ impl Default for Config {
142 fn default() -> Config { 149 fn default() -> Config {
143 Config { 150 Config {
144 mux: ClockSrc::MSI(MSIRange::default()), 151 mux: ClockSrc::MSI(MSIRange::default()),
145 ahb_pre: AHBPrescaler::NotDivided, 152 ahb_pre: AHBPrescaler::DIV1,
146 apb1_pre: APBPrescaler::NotDivided, 153 apb1_pre: APBPrescaler::DIV1,
147 apb2_pre: APBPrescaler::NotDivided, 154 apb2_pre: APBPrescaler::DIV1,
148 #[cfg(crs)] 155 #[cfg(crs)]
149 enable_hsi48: false, 156 enable_hsi48: false,
157 rtc: None,
158 lse: None,
159 lsi: false,
160 voltage_scale: VoltageScale::RANGE1,
150 } 161 }
151 } 162 }
152} 163}
153 164
154pub(crate) unsafe fn init(config: Config) { 165pub(crate) unsafe fn init(config: Config) {
166 // Set voltage scale
167 while PWR.csr().read().vosf() {}
168 PWR.cr().write(|w| w.set_vos(config.voltage_scale));
169 while PWR.csr().read().vosf() {}
170
155 let (sys_clk, sw) = match config.mux { 171 let (sys_clk, sw) = match config.mux {
156 ClockSrc::MSI(range) => { 172 ClockSrc::MSI(range) => {
157 // Set MSI range 173 // Set MSI range
@@ -231,6 +247,28 @@ pub(crate) unsafe fn init(config: Config) {
231 } 247 }
232 }; 248 };
233 249
250 BackupDomain::configure_ls(
251 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
252 config.lsi,
253 config.lse.map(|_| Default::default()),
254 );
255
256 let wait_states = match config.voltage_scale {
257 VoltageScale::RANGE1 => match sys_clk {
258 ..=16_000_000 => 0,
259 _ => 1,
260 },
261 VoltageScale::RANGE2 => match sys_clk {
262 ..=8_000_000 => 0,
263 _ => 1,
264 },
265 VoltageScale::RANGE3 => 0,
266 _ => unreachable!(),
267 };
268 FLASH.acr().modify(|w| {
269 w.set_latency(wait_states != 0);
270 });
271
234 RCC.cfgr().modify(|w| { 272 RCC.cfgr().modify(|w| {
235 w.set_sw(sw); 273 w.set_sw(sw);
236 w.set_hpre(config.ahb_pre.into()); 274 w.set_hpre(config.ahb_pre.into());
@@ -239,7 +277,7 @@ pub(crate) unsafe fn init(config: Config) {
239 }); 277 });
240 278
241 let ahb_freq: u32 = match config.ahb_pre { 279 let ahb_freq: u32 = match config.ahb_pre {
242 AHBPrescaler::NotDivided => sys_clk, 280 AHBPrescaler::DIV1 => sys_clk,
243 pre => { 281 pre => {
244 let pre: Hpre = pre.into(); 282 let pre: Hpre = pre.into();
245 let pre = 1 << (pre.to_bits() as u32 - 7); 283 let pre = 1 << (pre.to_bits() as u32 - 7);
@@ -248,7 +286,7 @@ pub(crate) unsafe fn init(config: Config) {
248 }; 286 };
249 287
250 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 288 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
251 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 289 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
252 pre => { 290 pre => {
253 let pre: Ppre = pre.into(); 291 let pre: Ppre = pre.into();
254 let pre: u8 = 1 << (pre.to_bits() - 3); 292 let pre: u8 = 1 << (pre.to_bits() - 3);
@@ -258,7 +296,7 @@ pub(crate) unsafe fn init(config: Config) {
258 }; 296 };
259 297
260 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 298 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
261 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 299 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
262 pre => { 300 pre => {
263 let pre: Ppre = pre.into(); 301 let pre: Ppre = pre.into();
264 let pre: u8 = 1 << (pre.to_bits() - 3); 302 let pre: u8 = 1 << (pre.to_bits() - 3);
@@ -269,13 +307,6 @@ pub(crate) unsafe fn init(config: Config) {
269 307
270 #[cfg(crs)] 308 #[cfg(crs)]
271 if config.enable_hsi48 { 309 if config.enable_hsi48 {
272 // Reset SYSCFG peripheral
273 RCC.apb2rstr().modify(|w| w.set_syscfgrst(true));
274 RCC.apb2rstr().modify(|w| w.set_syscfgrst(false));
275
276 // Enable SYSCFG peripheral
277 RCC.apb2enr().modify(|w| w.set_syscfgen(true));
278
279 // Reset CRS peripheral 310 // Reset CRS peripheral
280 RCC.apb1rstr().modify(|w| w.set_crsrst(true)); 311 RCC.apb1rstr().modify(|w| w.set_crsrst(true));
281 RCC.apb1rstr().modify(|w| w.set_crsrst(false)); 312 RCC.apb1rstr().modify(|w| w.set_crsrst(false));
diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs
index bdfc5b87a..90524fb37 100644
--- a/embassy-stm32/src/rcc/l1.rs
+++ b/embassy-stm32/src/rcc/l1.rs
@@ -1,4 +1,4 @@
1pub use super::common::{AHBPrescaler, APBPrescaler}; 1pub use super::bus::{AHBPrescaler, APBPrescaler};
2use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; 2use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw};
3use crate::pac::{FLASH, RCC}; 3use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks}; 4use crate::rcc::{set_freqs, Clocks};
@@ -138,9 +138,9 @@ impl Default for Config {
138 fn default() -> Config { 138 fn default() -> Config {
139 Config { 139 Config {
140 mux: ClockSrc::MSI(MSIRange::default()), 140 mux: ClockSrc::MSI(MSIRange::default()),
141 ahb_pre: AHBPrescaler::NotDivided, 141 ahb_pre: AHBPrescaler::DIV1,
142 apb1_pre: APBPrescaler::NotDivided, 142 apb1_pre: APBPrescaler::DIV1,
143 apb2_pre: APBPrescaler::NotDivided, 143 apb2_pre: APBPrescaler::DIV1,
144 } 144 }
145 } 145 }
146} 146}
@@ -240,7 +240,7 @@ pub(crate) unsafe fn init(config: Config) {
240 }); 240 });
241 241
242 let ahb_freq: u32 = match config.ahb_pre { 242 let ahb_freq: u32 = match config.ahb_pre {
243 AHBPrescaler::NotDivided => sys_clk, 243 AHBPrescaler::DIV1 => sys_clk,
244 pre => { 244 pre => {
245 let pre: Hpre = pre.into(); 245 let pre: Hpre = pre.into();
246 let pre = 1 << (pre.to_bits() as u32 - 7); 246 let pre = 1 << (pre.to_bits() as u32 - 7);
@@ -249,7 +249,7 @@ pub(crate) unsafe fn init(config: Config) {
249 }; 249 };
250 250
251 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 251 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
252 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 252 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
253 pre => { 253 pre => {
254 let pre: Ppre = pre.into(); 254 let pre: Ppre = pre.into();
255 let pre: u8 = 1 << (pre.to_bits() - 3); 255 let pre: u8 = 1 << (pre.to_bits() - 3);
@@ -259,7 +259,7 @@ pub(crate) unsafe fn init(config: Config) {
259 }; 259 };
260 260
261 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 261 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
262 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 262 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
263 pre => { 263 pre => {
264 let pre: Ppre = pre.into(); 264 let pre: Ppre = pre.into();
265 let pre: u8 = 1 << (pre.to_bits() - 3); 265 let pre: u8 = 1 << (pre.to_bits() - 3);
diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs
index b34b8caab..6f1f7458c 100644
--- a/embassy-stm32/src/rcc/l4.rs
+++ b/embassy-stm32/src/rcc/l4.rs
@@ -2,15 +2,15 @@ use core::marker::PhantomData;
2 2
3use embassy_hal_internal::into_ref; 3use embassy_hal_internal::into_ref;
4use stm32_metapac::rcc::regs::Cfgr; 4use stm32_metapac::rcc::regs::Cfgr;
5use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel}; 5use stm32_metapac::rcc::vals::{Mcopre, Mcosel};
6 6
7pub use super::common::{AHBPrescaler, APBPrescaler}; 7pub use super::bus::{AHBPrescaler, APBPrescaler};
8use crate::gpio::sealed::AFType; 8use crate::gpio::sealed::AFType;
9use crate::gpio::Speed; 9use crate::gpio::Speed;
10use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; 10use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
11use crate::pac::{FLASH, PWR, RCC}; 11use crate::pac::{FLASH, RCC};
12use crate::rcc::bd::{BackupDomain, RtcClockSource};
12use crate::rcc::{set_freqs, Clocks}; 13use crate::rcc::{set_freqs, Clocks};
13use crate::rtc::{Rtc, RtcClockSource as RCS};
14use crate::time::Hertz; 14use crate::time::Hertz;
15use crate::{peripherals, Peripheral}; 15use crate::{peripherals, Peripheral};
16 16
@@ -241,6 +241,8 @@ pub struct Config {
241 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] 241 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
242 pub hsi48: bool, 242 pub hsi48: bool,
243 pub rtc_mux: RtcClockSource, 243 pub rtc_mux: RtcClockSource,
244 pub lse: Option<Hertz>,
245 pub lsi: bool,
244} 246}
245 247
246impl Default for Config { 248impl Default for Config {
@@ -248,22 +250,19 @@ impl Default for Config {
248 fn default() -> Config { 250 fn default() -> Config {
249 Config { 251 Config {
250 mux: ClockSrc::MSI(MSIRange::Range6), 252 mux: ClockSrc::MSI(MSIRange::Range6),
251 ahb_pre: AHBPrescaler::NotDivided, 253 ahb_pre: AHBPrescaler::DIV1,
252 apb1_pre: APBPrescaler::NotDivided, 254 apb1_pre: APBPrescaler::DIV1,
253 apb2_pre: APBPrescaler::NotDivided, 255 apb2_pre: APBPrescaler::DIV1,
254 pllsai1: None, 256 pllsai1: None,
255 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))] 257 #[cfg(not(any(stm32l471, stm32l475, stm32l476, stm32l486)))]
256 hsi48: false, 258 hsi48: false,
257 rtc_mux: RtcClockSource::LSI32, 259 rtc_mux: RtcClockSource::LSI,
260 lsi: true,
261 lse: None,
258 } 262 }
259 } 263 }
260} 264}
261 265
262pub enum RtcClockSource {
263 LSE32,
264 LSI32,
265}
266
267pub enum McoClock { 266pub enum McoClock {
268 DIV1, 267 DIV1,
269 DIV2, 268 DIV2,
@@ -410,37 +409,7 @@ pub(crate) unsafe fn init(config: Config) {
410 while RCC.cfgr().read().sws() != Sw::MSI {} 409 while RCC.cfgr().read().sws() != Sw::MSI {}
411 } 410 }
412 411
413 RCC.apb1enr1().modify(|w| w.set_pwren(true)); 412 BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default()));
414
415 match config.rtc_mux {
416 RtcClockSource::LSE32 => {
417 // 1. Unlock the backup domain
418 PWR.cr1().modify(|w| w.set_dbp(true));
419
420 // 2. Setup the LSE
421 RCC.bdcr().modify(|w| {
422 // Enable LSE
423 w.set_lseon(true);
424 // Max drive strength
425 // TODO: should probably be settable
426 w.set_lsedrv(Lsedrv::HIGH);
427 });
428
429 // Wait until LSE is running
430 while !RCC.bdcr().read().lserdy() {}
431
432 Rtc::set_clock_source(RCS::LSE);
433 }
434 RtcClockSource::LSI32 => {
435 // Turn on the internal 32 kHz LSI oscillator
436 RCC.csr().modify(|w| w.set_lsion(true));
437
438 // Wait until LSI is running
439 while !RCC.csr().read().lsirdy() {}
440
441 Rtc::set_clock_source(RCS::LSI);
442 }
443 }
444 413
445 let (sys_clk, sw) = match config.mux { 414 let (sys_clk, sw) = match config.mux {
446 ClockSrc::MSI(range) => { 415 ClockSrc::MSI(range) => {
@@ -451,7 +420,7 @@ pub(crate) unsafe fn init(config: Config) {
451 w.set_msirgsel(true); 420 w.set_msirgsel(true);
452 w.set_msion(true); 421 w.set_msion(true);
453 422
454 if let RtcClockSource::LSE32 = config.rtc_mux { 423 if let RtcClockSource::LSE = config.rtc_mux {
455 // If LSE is enabled, enable calibration of MSI 424 // If LSE is enabled, enable calibration of MSI
456 w.set_msipllen(true); 425 w.set_msipllen(true);
457 } else { 426 } else {
@@ -609,7 +578,7 @@ pub(crate) unsafe fn init(config: Config) {
609 }); 578 });
610 579
611 let ahb_freq: u32 = match config.ahb_pre { 580 let ahb_freq: u32 = match config.ahb_pre {
612 AHBPrescaler::NotDivided => sys_clk, 581 AHBPrescaler::DIV1 => sys_clk,
613 pre => { 582 pre => {
614 let pre: Hpre = pre.into(); 583 let pre: Hpre = pre.into();
615 let pre = 1 << (pre.to_bits() as u32 - 7); 584 let pre = 1 << (pre.to_bits() as u32 - 7);
@@ -618,7 +587,7 @@ pub(crate) unsafe fn init(config: Config) {
618 }; 587 };
619 588
620 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 589 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
621 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 590 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
622 pre => { 591 pre => {
623 let pre: Ppre = pre.into(); 592 let pre: Ppre = pre.into();
624 let pre: u8 = 1 << (pre.to_bits() - 3); 593 let pre: u8 = 1 << (pre.to_bits() - 3);
@@ -628,7 +597,7 @@ pub(crate) unsafe fn init(config: Config) {
628 }; 597 };
629 598
630 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 599 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
631 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 600 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
632 pre => { 601 pre => {
633 let pre: Ppre = pre.into(); 602 let pre: Ppre = pre.into();
634 let pre: u8 = 1 << (pre.to_bits() - 3); 603 let pre: u8 = 1 << (pre.to_bits() - 3);
@@ -637,8 +606,6 @@ pub(crate) unsafe fn init(config: Config) {
637 } 606 }
638 }; 607 };
639 608
640 RCC.apb1enr1().modify(|w| w.set_pwren(true));
641
642 set_freqs(Clocks { 609 set_freqs(Clocks {
643 sys: Hertz(sys_clk), 610 sys: Hertz(sys_clk),
644 ahb1: Hertz(ahb_freq), 611 ahb1: Hertz(ahb_freq),
diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs
index a85e14889..652bdcb7b 100644
--- a/embassy-stm32/src/rcc/l5.rs
+++ b/embassy-stm32/src/rcc/l5.rs
@@ -1,6 +1,6 @@
1use stm32_metapac::PWR; 1use stm32_metapac::PWR;
2 2
3pub use super::common::{AHBPrescaler, APBPrescaler}; 3pub use super::bus::{AHBPrescaler, APBPrescaler};
4use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; 4use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw};
5use crate::pac::{FLASH, RCC}; 5use crate::pac::{FLASH, RCC};
6use crate::rcc::{set_freqs, Clocks}; 6use crate::rcc::{set_freqs, Clocks};
@@ -238,9 +238,9 @@ impl Default for Config {
238 fn default() -> Config { 238 fn default() -> Config {
239 Config { 239 Config {
240 mux: ClockSrc::MSI(MSIRange::Range6), 240 mux: ClockSrc::MSI(MSIRange::Range6),
241 ahb_pre: AHBPrescaler::NotDivided, 241 ahb_pre: AHBPrescaler::DIV1,
242 apb1_pre: APBPrescaler::NotDivided, 242 apb1_pre: APBPrescaler::DIV1,
243 apb2_pre: APBPrescaler::NotDivided, 243 apb2_pre: APBPrescaler::DIV1,
244 pllsai1: None, 244 pllsai1: None,
245 hsi48: false, 245 hsi48: false,
246 } 246 }
@@ -317,11 +317,6 @@ pub(crate) unsafe fn init(config: Config) {
317 317
318 let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div(); 318 let freq = (src_freq / prediv.to_div() * mul.to_mul()) / div.to_div();
319 319
320 #[cfg(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx))]
321 assert!(freq <= 120_000_000);
322 #[cfg(not(any(stm32l4px, stm32l4qx, stm32l4rx, stm32l4sx)))]
323 assert!(freq <= 80_000_000);
324
325 RCC.pllcfgr().write(move |w| { 320 RCC.pllcfgr().write(move |w| {
326 w.set_plln(mul.into()); 321 w.set_plln(mul.into());
327 w.set_pllm(prediv.into()); 322 w.set_pllm(prediv.into());
@@ -407,7 +402,7 @@ pub(crate) unsafe fn init(config: Config) {
407 }); 402 });
408 403
409 let ahb_freq: u32 = match config.ahb_pre { 404 let ahb_freq: u32 = match config.ahb_pre {
410 AHBPrescaler::NotDivided => sys_clk, 405 AHBPrescaler::DIV1 => sys_clk,
411 pre => { 406 pre => {
412 let pre: Hpre = pre.into(); 407 let pre: Hpre = pre.into();
413 let pre = 1 << (pre.to_bits() as u32 - 7); 408 let pre = 1 << (pre.to_bits() as u32 - 7);
@@ -416,7 +411,7 @@ pub(crate) unsafe fn init(config: Config) {
416 }; 411 };
417 412
418 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 413 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
419 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 414 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
420 pre => { 415 pre => {
421 let pre: Ppre = pre.into(); 416 let pre: Ppre = pre.into();
422 let pre: u8 = 1 << (pre.to_bits() - 3); 417 let pre: u8 = 1 << (pre.to_bits() - 3);
@@ -426,7 +421,7 @@ pub(crate) unsafe fn init(config: Config) {
426 }; 421 };
427 422
428 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 423 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
429 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 424 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
430 pre => { 425 pre => {
431 let pre: Ppre = pre.into(); 426 let pre: Ppre = pre.into();
432 let pre: u8 = 1 << (pre.to_bits() - 3); 427 let pre: u8 = 1 << (pre.to_bits() - 3);
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs
new file mode 100644
index 000000000..2453ed821
--- /dev/null
+++ b/embassy-stm32/src/rcc/mco.rs
@@ -0,0 +1,71 @@
1use core::marker::PhantomData;
2
3use embassy_hal_internal::into_ref;
4
5use crate::gpio::sealed::AFType;
6use crate::gpio::Speed;
7pub use crate::pac::rcc::vals::{Mco1 as Mco1Source, Mco2 as Mco2Source};
8use crate::pac::RCC;
9use crate::{peripherals, Peripheral};
10
11pub(crate) mod sealed {
12 pub trait McoInstance {
13 type Source;
14 unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8);
15 }
16}
17
18pub trait McoInstance: sealed::McoInstance + 'static {}
19
20pin_trait!(McoPin, McoInstance);
21
22macro_rules! impl_peri {
23 ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => {
24 impl sealed::McoInstance for peripherals::$peri {
25 type Source = $source;
26
27 unsafe fn apply_clock_settings(source: Self::Source, prescaler: u8) {
28 RCC.cfgr().modify(|w| {
29 w.$set_source(source);
30 w.$set_prescaler(prescaler);
31 });
32 }
33 }
34
35 impl McoInstance for peripherals::$peri {}
36 };
37}
38
39impl_peri!(MCO1, Mco1Source, set_mco1, set_mco1pre);
40impl_peri!(MCO2, Mco2Source, set_mco2, set_mco2pre);
41
42pub struct Mco<'d, T: McoInstance> {
43 phantom: PhantomData<&'d mut T>,
44}
45
46impl<'d, T: McoInstance> Mco<'d, T> {
47 /// Create a new MCO instance.
48 ///
49 /// `prescaler` must be between 1 and 15.
50 pub fn new(
51 _peri: impl Peripheral<P = T> + 'd,
52 pin: impl Peripheral<P = impl McoPin<T>> + 'd,
53 source: T::Source,
54 prescaler: u8,
55 ) -> Self {
56 into_ref!(pin);
57
58 assert!(
59 1 <= prescaler && prescaler <= 15,
60 "Mco prescaler must be between 1 and 15. Refer to the reference manual for more information."
61 );
62
63 critical_section::with(|_| unsafe {
64 T::apply_clock_settings(source, prescaler);
65 pin.set_as_af(pin.af_num(), AFType::OutputPushPull);
66 pin.set_speed(Speed::VeryHigh);
67 });
68
69 Self { phantom: PhantomData }
70 }
71}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 3c75923e5..9ccf2ac4f 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -1,11 +1,17 @@
1#![macro_use] 1#![macro_use]
2 2
3pub mod common;
4
5use core::mem::MaybeUninit; 3use core::mem::MaybeUninit;
6 4
5pub use crate::rcc::bd::RtcClockSource;
7use crate::time::Hertz; 6use crate::time::Hertz;
8 7
8pub(crate) mod bd;
9mod bus;
10#[cfg(any(stm32h5, stm32h7))]
11mod mco;
12#[cfg(any(stm32h5, stm32h7))]
13pub use mco::*;
14
9#[cfg_attr(rcc_f0, path = "f0.rs")] 15#[cfg_attr(rcc_f0, path = "f0.rs")]
10#[cfg_attr(any(rcc_f1, rcc_f100, rcc_f1cl), path = "f1.rs")] 16#[cfg_attr(any(rcc_f1, rcc_f100, rcc_f1cl), path = "f1.rs")]
11#[cfg_attr(rcc_f2, path = "f2.rs")] 17#[cfg_attr(rcc_f2, path = "f2.rs")]
@@ -15,20 +21,30 @@ use crate::time::Hertz;
15#[cfg_attr(rcc_c0, path = "c0.rs")] 21#[cfg_attr(rcc_c0, path = "c0.rs")]
16#[cfg_attr(rcc_g0, path = "g0.rs")] 22#[cfg_attr(rcc_g0, path = "g0.rs")]
17#[cfg_attr(rcc_g4, path = "g4.rs")] 23#[cfg_attr(rcc_g4, path = "g4.rs")]
18#[cfg_attr(any(rcc_h7, rcc_h7ab), path = "h7.rs")] 24#[cfg_attr(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab), path = "h.rs")]
19#[cfg_attr(rcc_l0, path = "l0.rs")] 25#[cfg_attr(rcc_l0, path = "l0.rs")]
20#[cfg_attr(rcc_l1, path = "l1.rs")] 26#[cfg_attr(rcc_l1, path = "l1.rs")]
21#[cfg_attr(rcc_l4, path = "l4.rs")] 27#[cfg_attr(rcc_l4, path = "l4.rs")]
22#[cfg_attr(rcc_l5, path = "l5.rs")] 28#[cfg_attr(rcc_l5, path = "l5.rs")]
23#[cfg_attr(rcc_u5, path = "u5.rs")] 29#[cfg_attr(rcc_u5, path = "u5.rs")]
24#[cfg_attr(rcc_wb, path = "wb.rs")] 30#[cfg_attr(rcc_wb, path = "wb.rs")]
31#[cfg_attr(rcc_wba, path = "wba.rs")]
25#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")] 32#[cfg_attr(any(rcc_wl5, rcc_wle), path = "wl.rs")]
26#[cfg_attr(any(rcc_h5, rcc_h50), path = "h5.rs")]
27mod _version; 33mod _version;
28pub use _version::*; 34pub use _version::*;
29#[cfg(feature = "low-power")] 35#[cfg(feature = "low-power")]
30use atomic_polyfill::{AtomicU32, Ordering}; 36use atomic_polyfill::{AtomicU32, Ordering};
31 37
38// Model Clock Configuration
39//
40// pub struct Clocks {
41// hse: Option<Hertz>,
42// hsi: bool,
43// lse: Option<Hertz>,
44// lsi: bool,
45// rtc: RtcSource,
46// }
47
32#[derive(Clone, Copy, Debug)] 48#[derive(Clone, Copy, Debug)]
33#[cfg_attr(feature = "defmt", derive(defmt::Format))] 49#[cfg_attr(feature = "defmt", derive(defmt::Format))]
34pub struct Clocks { 50pub struct Clocks {
@@ -41,16 +57,18 @@ pub struct Clocks {
41 pub apb2: Hertz, 57 pub apb2: Hertz,
42 #[cfg(not(any(rcc_c0, rcc_g0)))] 58 #[cfg(not(any(rcc_c0, rcc_g0)))]
43 pub apb2_tim: Hertz, 59 pub apb2_tim: Hertz,
44 #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_u5))] 60 #[cfg(any(rcc_wl5, rcc_wle, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_u5))]
45 pub apb3: Hertz, 61 pub apb3: Hertz,
46 #[cfg(any(rcc_h7, rcc_h7ab))] 62 #[cfg(any(rcc_h7, rcc_h7ab))]
47 pub apb4: Hertz, 63 pub apb4: Hertz,
64 #[cfg(any(rcc_wba))]
65 pub apb7: Hertz,
48 66
49 // AHB 67 // AHB
50 pub ahb1: Hertz, 68 pub ahb1: Hertz,
51 #[cfg(any( 69 #[cfg(any(
52 rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb, 70 rcc_l4, rcc_l5, rcc_f2, rcc_f4, rcc_f410, rcc_f7, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_g4, rcc_u5, rcc_wb,
53 rcc_wl5, rcc_wle 71 rcc_wba, rcc_wl5, rcc_wle
54 ))] 72 ))]
55 pub ahb2: Hertz, 73 pub ahb2: Hertz,
56 #[cfg(any( 74 #[cfg(any(
@@ -58,7 +76,7 @@ pub struct Clocks {
58 rcc_wle 76 rcc_wle
59 ))] 77 ))]
60 pub ahb3: Hertz, 78 pub ahb3: Hertz,
61 #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))] 79 #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_wba))]
62 pub ahb4: Hertz, 80 pub ahb4: Hertz,
63 81
64 #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))] 82 #[cfg(any(rcc_f2, rcc_f4, rcc_f410, rcc_f7))]
@@ -70,15 +88,22 @@ pub struct Clocks {
70 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] 88 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
71 pub pllsai: Option<Hertz>, 89 pub pllsai: Option<Hertz>,
72 90
73 #[cfg(stm32f1)] 91 #[cfg(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_f3, rcc_g4))]
74 pub adc: Hertz,
75
76 #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))]
77 pub adc: Option<Hertz>, 92 pub adc: Option<Hertz>,
78 93
79 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] 94 #[cfg(any(rcc_f3, rcc_g4))]
80 /// Set only if the lsi or lse is configured 95 pub adc34: Option<Hertz>,
96
97 #[cfg(stm32f334)]
98 pub hrtim: Option<Hertz>,
99
100 #[cfg(any(rcc_wb, rcc_f4, rcc_f410, rcc_f7))]
101 /// Set only if the lsi or lse is configured, indicates stop is supported
81 pub rtc: Option<Hertz>, 102 pub rtc: Option<Hertz>,
103
104 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
105 /// Set if the hse is configured, indicates stop is not supported
106 pub rtc_hse: Option<Hertz>,
82} 107}
83 108
84#[cfg(feature = "low-power")] 109#[cfg(feature = "low-power")]
@@ -86,6 +111,8 @@ static CLOCK_REFCOUNT: AtomicU32 = AtomicU32::new(0);
86 111
87#[cfg(feature = "low-power")] 112#[cfg(feature = "low-power")]
88pub fn low_power_ready() -> bool { 113pub fn low_power_ready() -> bool {
114 trace!("clock refcount: {}", CLOCK_REFCOUNT.load(Ordering::SeqCst));
115
89 CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0 116 CLOCK_REFCOUNT.load(Ordering::SeqCst) == 0
90} 117}
91 118
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index b5feeb0c4..d9a531285 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -1,6 +1,6 @@
1use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw}; 1use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw};
2 2
3pub use super::common::{AHBPrescaler, APBPrescaler}; 3pub use super::bus::{AHBPrescaler, APBPrescaler};
4use crate::pac::{FLASH, RCC}; 4use crate::pac::{FLASH, RCC};
5use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
6use crate::time::Hertz; 6use crate::time::Hertz;
@@ -11,7 +11,7 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000);
11/// LSI speed 11/// LSI speed
12pub const LSI_FREQ: Hertz = Hertz(32_000); 12pub const LSI_FREQ: Hertz = Hertz(32_000);
13 13
14pub use super::common::VoltageScale; 14pub use crate::pac::pwr::vals::Vos as VoltageScale;
15 15
16#[derive(Copy, Clone)] 16#[derive(Copy, Clone)]
17pub enum ClockSrc { 17pub enum ClockSrc {
@@ -119,53 +119,13 @@ impl Into<Pllm> for PllM {
119 } 119 }
120} 120}
121 121
122impl Into<u8> for AHBPrescaler {
123 fn into(self) -> u8 {
124 match self {
125 AHBPrescaler::NotDivided => 1,
126 AHBPrescaler::Div2 => 0x08,
127 AHBPrescaler::Div4 => 0x09,
128 AHBPrescaler::Div8 => 0x0a,
129 AHBPrescaler::Div16 => 0x0b,
130 AHBPrescaler::Div64 => 0x0c,
131 AHBPrescaler::Div128 => 0x0d,
132 AHBPrescaler::Div256 => 0x0e,
133 AHBPrescaler::Div512 => 0x0f,
134 }
135 }
136}
137
138impl Default for AHBPrescaler {
139 fn default() -> Self {
140 AHBPrescaler::NotDivided
141 }
142}
143
144impl Default for APBPrescaler {
145 fn default() -> Self {
146 APBPrescaler::NotDivided
147 }
148}
149
150impl Into<u8> for APBPrescaler {
151 fn into(self) -> u8 {
152 match self {
153 APBPrescaler::NotDivided => 1,
154 APBPrescaler::Div2 => 0x04,
155 APBPrescaler::Div4 => 0x05,
156 APBPrescaler::Div8 => 0x06,
157 APBPrescaler::Div16 => 0x07,
158 }
159 }
160}
161
162impl Into<Sw> for ClockSrc { 122impl Into<Sw> for ClockSrc {
163 fn into(self) -> Sw { 123 fn into(self) -> Sw {
164 match self { 124 match self {
165 ClockSrc::MSI(..) => Sw::MSIS, 125 ClockSrc::MSI(..) => Sw::MSIS,
166 ClockSrc::HSE(..) => Sw::HSE, 126 ClockSrc::HSE(..) => Sw::HSE,
167 ClockSrc::HSI16 => Sw::HSI16, 127 ClockSrc::HSI16 => Sw::HSI16,
168 ClockSrc::PLL1R(..) => Sw::PLL1R, 128 ClockSrc::PLL1R(..) => Sw::PLL1_R,
169 } 129 }
170 } 130 }
171} 131}
@@ -239,10 +199,10 @@ impl Default for Config {
239 fn default() -> Self { 199 fn default() -> Self {
240 Self { 200 Self {
241 mux: ClockSrc::MSI(MSIRange::default()), 201 mux: ClockSrc::MSI(MSIRange::default()),
242 ahb_pre: Default::default(), 202 ahb_pre: AHBPrescaler::DIV1,
243 apb1_pre: Default::default(), 203 apb1_pre: APBPrescaler::DIV1,
244 apb2_pre: Default::default(), 204 apb2_pre: APBPrescaler::DIV1,
245 apb3_pre: Default::default(), 205 apb3_pre: APBPrescaler::DIV1,
246 hsi48: false, 206 hsi48: false,
247 } 207 }
248 } 208 }
@@ -326,12 +286,12 @@ pub(crate) unsafe fn init(config: Config) {
326 } 286 }
327 287
328 // TODO make configurable 288 // TODO make configurable
329 let power_vos = VoltageScale::Scale3; 289 let power_vos = VoltageScale::RANGE3;
330 290
331 // states and programming delay 291 // states and programming delay
332 let wait_states = match power_vos { 292 let wait_states = match power_vos {
333 // VOS 0 range VCORE 1.26V - 1.40V 293 // VOS 1 range VCORE 1.26V - 1.40V
334 VoltageScale::Scale0 => { 294 VoltageScale::RANGE1 => {
335 if sys_clk < 32_000_000 { 295 if sys_clk < 32_000_000 {
336 0 296 0
337 } else if sys_clk < 64_000_000 { 297 } else if sys_clk < 64_000_000 {
@@ -344,8 +304,8 @@ pub(crate) unsafe fn init(config: Config) {
344 4 304 4
345 } 305 }
346 } 306 }
347 // VOS 1 range VCORE 1.15V - 1.26V 307 // VOS 2 range VCORE 1.15V - 1.26V
348 VoltageScale::Scale1 => { 308 VoltageScale::RANGE2 => {
349 if sys_clk < 30_000_000 { 309 if sys_clk < 30_000_000 {
350 0 310 0
351 } else if sys_clk < 60_000_000 { 311 } else if sys_clk < 60_000_000 {
@@ -356,8 +316,8 @@ pub(crate) unsafe fn init(config: Config) {
356 3 316 3
357 } 317 }
358 } 318 }
359 // VOS 2 range VCORE 1.05V - 1.15V 319 // VOS 3 range VCORE 1.05V - 1.15V
360 VoltageScale::Scale2 => { 320 VoltageScale::RANGE3 => {
361 if sys_clk < 24_000_000 { 321 if sys_clk < 24_000_000 {
362 0 322 0
363 } else if sys_clk < 48_000_000 { 323 } else if sys_clk < 48_000_000 {
@@ -366,8 +326,8 @@ pub(crate) unsafe fn init(config: Config) {
366 2 326 2
367 } 327 }
368 } 328 }
369 // VOS 3 range VCORE 0.95V - 1.05V 329 // VOS 4 range VCORE 0.95V - 1.05V
370 VoltageScale::Scale3 => { 330 VoltageScale::RANGE4 => {
371 if sys_clk < 12_000_000 { 331 if sys_clk < 12_000_000 {
372 0 332 0
373 } else { 333 } else {
@@ -395,7 +355,7 @@ pub(crate) unsafe fn init(config: Config) {
395 }); 355 });
396 356
397 let ahb_freq: u32 = match config.ahb_pre { 357 let ahb_freq: u32 = match config.ahb_pre {
398 AHBPrescaler::NotDivided => sys_clk, 358 AHBPrescaler::DIV1 => sys_clk,
399 pre => { 359 pre => {
400 let pre: u8 = pre.into(); 360 let pre: u8 = pre.into();
401 let pre = 1 << (pre as u32 - 7); 361 let pre = 1 << (pre as u32 - 7);
@@ -404,7 +364,7 @@ pub(crate) unsafe fn init(config: Config) {
404 }; 364 };
405 365
406 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 366 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
407 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 367 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
408 pre => { 368 pre => {
409 let pre: u8 = pre.into(); 369 let pre: u8 = pre.into();
410 let pre: u8 = 1 << (pre - 3); 370 let pre: u8 = 1 << (pre - 3);
@@ -414,7 +374,7 @@ pub(crate) unsafe fn init(config: Config) {
414 }; 374 };
415 375
416 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 376 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
417 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 377 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
418 pre => { 378 pre => {
419 let pre: u8 = pre.into(); 379 let pre: u8 = pre.into();
420 let pre: u8 = 1 << (pre - 3); 380 let pre: u8 = 1 << (pre - 3);
@@ -424,7 +384,7 @@ pub(crate) unsafe fn init(config: Config) {
424 }; 384 };
425 385
426 let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre { 386 let (apb3_freq, _apb3_tim_freq) = match config.apb3_pre {
427 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 387 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
428 pre => { 388 pre => {
429 let pre: u8 = pre.into(); 389 let pre: u8 = pre.into();
430 let pre: u8 = 1 << (pre - 3); 390 let pre: u8 = 1 << (pre - 3);
diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs
index ae708b37f..ee45a342b 100644
--- a/embassy-stm32/src/rcc/wb.rs
+++ b/embassy-stm32/src/rcc/wb.rs
@@ -1,6 +1,6 @@
1pub use super::common::{AHBPrescaler, APBPrescaler}; 1pub use super::bus::{AHBPrescaler, APBPrescaler};
2use crate::rcc::bd::{BackupDomain, RtcClockSource};
2use crate::rcc::Clocks; 3use crate::rcc::Clocks;
3use crate::rtc::{Rtc, RtcClockSource};
4use crate::time::{khz, mhz, Hertz}; 4use crate::time::{khz, mhz, Hertz};
5 5
6/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 6/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
@@ -108,6 +108,7 @@ pub struct Pll {
108pub struct Config { 108pub struct Config {
109 pub hse: Option<Hse>, 109 pub hse: Option<Hse>,
110 pub lse: Option<Hertz>, 110 pub lse: Option<Hertz>,
111 pub lsi: bool,
111 pub sys: Sysclk, 112 pub sys: Sysclk,
112 pub mux: Option<PllMux>, 113 pub mux: Option<PllMux>,
113 pub pll48: Option<Pll48Source>, 114 pub pll48: Option<Pll48Source>,
@@ -135,7 +136,8 @@ pub const WPAN_DEFAULT: Config = Config {
135 prediv: 2, 136 prediv: 2,
136 }), 137 }),
137 pll48: None, 138 pll48: None,
138 rtc: None, 139 rtc: Some(RtcClockSource::LSE),
140 lsi: false,
139 141
140 pll: Some(Pll { 142 pll: Some(Pll {
141 mul: 12, 143 mul: 12,
@@ -145,11 +147,11 @@ pub const WPAN_DEFAULT: Config = Config {
145 }), 147 }),
146 pllsai: None, 148 pllsai: None,
147 149
148 ahb1_pre: AHBPrescaler::NotDivided, 150 ahb1_pre: AHBPrescaler::DIV1,
149 ahb2_pre: AHBPrescaler::Div2, 151 ahb2_pre: AHBPrescaler::DIV2,
150 ahb3_pre: AHBPrescaler::NotDivided, 152 ahb3_pre: AHBPrescaler::DIV1,
151 apb1_pre: APBPrescaler::NotDivided, 153 apb1_pre: APBPrescaler::DIV1,
152 apb2_pre: APBPrescaler::NotDivided, 154 apb2_pre: APBPrescaler::DIV1,
153}; 155};
154 156
155impl Default for Config { 157impl Default for Config {
@@ -164,12 +166,13 @@ impl Default for Config {
164 pll: None, 166 pll: None,
165 pllsai: None, 167 pllsai: None,
166 rtc: None, 168 rtc: None,
169 lsi: false,
167 170
168 ahb1_pre: AHBPrescaler::NotDivided, 171 ahb1_pre: AHBPrescaler::DIV1,
169 ahb2_pre: AHBPrescaler::NotDivided, 172 ahb2_pre: AHBPrescaler::DIV1,
170 ahb3_pre: AHBPrescaler::NotDivided, 173 ahb3_pre: AHBPrescaler::DIV1,
171 apb1_pre: APBPrescaler::NotDivided, 174 apb1_pre: APBPrescaler::DIV1,
172 apb2_pre: APBPrescaler::NotDivided, 175 apb2_pre: APBPrescaler::DIV1,
173 } 176 }
174 } 177 }
175} 178}
@@ -209,7 +212,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
209 }; 212 };
210 213
211 let ahb1_clk = match config.ahb1_pre { 214 let ahb1_clk = match config.ahb1_pre {
212 AHBPrescaler::NotDivided => sys_clk, 215 AHBPrescaler::DIV1 => sys_clk,
213 pre => { 216 pre => {
214 let pre: u8 = pre.into(); 217 let pre: u8 = pre.into();
215 let pre = 1u32 << (pre as u32 - 7); 218 let pre = 1u32 << (pre as u32 - 7);
@@ -218,7 +221,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
218 }; 221 };
219 222
220 let ahb2_clk = match config.ahb2_pre { 223 let ahb2_clk = match config.ahb2_pre {
221 AHBPrescaler::NotDivided => sys_clk, 224 AHBPrescaler::DIV1 => sys_clk,
222 pre => { 225 pre => {
223 let pre: u8 = pre.into(); 226 let pre: u8 = pre.into();
224 let pre = 1u32 << (pre as u32 - 7); 227 let pre = 1u32 << (pre as u32 - 7);
@@ -227,7 +230,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
227 }; 230 };
228 231
229 let ahb3_clk = match config.ahb3_pre { 232 let ahb3_clk = match config.ahb3_pre {
230 AHBPrescaler::NotDivided => sys_clk, 233 AHBPrescaler::DIV1 => sys_clk,
231 pre => { 234 pre => {
232 let pre: u8 = pre.into(); 235 let pre: u8 = pre.into();
233 let pre = 1u32 << (pre as u32 - 7); 236 let pre = 1u32 << (pre as u32 - 7);
@@ -236,7 +239,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
236 }; 239 };
237 240
238 let (apb1_clk, apb1_tim_clk) = match config.apb1_pre { 241 let (apb1_clk, apb1_tim_clk) = match config.apb1_pre {
239 APBPrescaler::NotDivided => (ahb1_clk, ahb1_clk), 242 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
240 pre => { 243 pre => {
241 let pre: u8 = pre.into(); 244 let pre: u8 = pre.into();
242 let pre: u8 = 1 << (pre - 3); 245 let pre: u8 = 1 << (pre - 3);
@@ -246,7 +249,7 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
246 }; 249 };
247 250
248 let (apb2_clk, apb2_tim_clk) = match config.apb2_pre { 251 let (apb2_clk, apb2_tim_clk) = match config.apb2_pre {
249 APBPrescaler::NotDivided => (ahb1_clk, ahb1_clk), 252 APBPrescaler::DIV1 => (ahb1_clk, ahb1_clk),
250 pre => { 253 pre => {
251 let pre: u8 = pre.into(); 254 let pre: u8 = pre.into();
252 let pre: u8 = 1 << (pre - 3); 255 let pre: u8 = 1 << (pre - 3);
@@ -271,11 +274,11 @@ pub(crate) fn compute_clocks(config: &Config) -> Clocks {
271 apb1_tim: apb1_tim_clk, 274 apb1_tim: apb1_tim_clk,
272 apb2_tim: apb2_tim_clk, 275 apb2_tim: apb2_tim_clk,
273 rtc: rtc_clk, 276 rtc: rtc_clk,
277 rtc_hse: None,
274 } 278 }
275} 279}
276 280
277pub(crate) fn configure_clocks(config: &Config) { 281pub(crate) fn configure_clocks(config: &Config) {
278 let pwr = crate::pac::PWR;
279 let rcc = crate::pac::RCC; 282 let rcc = crate::pac::RCC;
280 283
281 let needs_hsi = if let Some(pll_mux) = &config.mux { 284 let needs_hsi = if let Some(pll_mux) = &config.mux {
@@ -292,29 +295,13 @@ pub(crate) fn configure_clocks(config: &Config) {
292 while !rcc.cr().read().hsirdy() {} 295 while !rcc.cr().read().hsirdy() {}
293 } 296 }
294 297
295 let needs_lsi = if let Some(rtc_mux) = &config.rtc { 298 rcc.cfgr().modify(|w| w.set_stopwuck(true));
296 *rtc_mux == RtcClockSource::LSI
297 } else {
298 false
299 };
300
301 if needs_lsi {
302 rcc.csr().modify(|w| w.set_lsi1on(true));
303
304 while !rcc.csr().read().lsi1rdy() {}
305 }
306 299
307 match &config.lse { 300 BackupDomain::configure_ls(
308 Some(_) => { 301 config.rtc.unwrap_or(RtcClockSource::NOCLOCK),
309 rcc.cfgr().modify(|w| w.set_stopwuck(true)); 302 config.lsi,
310 303 config.lse.map(|_| Default::default()),
311 pwr.cr1().modify(|w| w.set_dbp(true)); 304 );
312 pwr.cr1().modify(|w| w.set_dbp(true));
313
314 rcc.bdcr().modify(|w| w.set_lseon(true));
315 }
316 _ => {}
317 }
318 305
319 match &config.hse { 306 match &config.hse {
320 Some(hse) => { 307 Some(hse) => {
@@ -374,6 +361,4 @@ pub(crate) fn configure_clocks(config: &Config) {
374 w.set_c2hpre(config.ahb2_pre.into()); 361 w.set_c2hpre(config.ahb2_pre.into());
375 w.set_shdhpre(config.ahb3_pre.into()); 362 w.set_shdhpre(config.ahb3_pre.into());
376 }); 363 });
377
378 config.rtc.map(|clock_source| Rtc::set_clock_source(clock_source));
379} 364}
diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs
new file mode 100644
index 000000000..c5d7ab62f
--- /dev/null
+++ b/embassy-stm32/src/rcc/wba.rs
@@ -0,0 +1,154 @@
1use stm32_metapac::rcc::vals::{Pllsrc, Sw};
2
3use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz;
6
7/// HSI speed
8pub const HSI_FREQ: Hertz = Hertz(16_000_000);
9
10/// LSI speed
11pub const LSI_FREQ: Hertz = Hertz(32_000);
12
13pub use crate::pac::pwr::vals::Vos as VoltageScale;
14pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler};
15
16#[derive(Copy, Clone)]
17pub enum ClockSrc {
18 HSE(Hertz),
19 HSI16,
20}
21
22#[derive(Clone, Copy, Debug)]
23pub enum PllSrc {
24 HSE(Hertz),
25 HSI16,
26}
27
28impl Into<Pllsrc> for PllSrc {
29 fn into(self) -> Pllsrc {
30 match self {
31 PllSrc::HSE(..) => Pllsrc::HSE32,
32 PllSrc::HSI16 => Pllsrc::HSI16,
33 }
34 }
35}
36
37impl Into<Sw> for ClockSrc {
38 fn into(self) -> Sw {
39 match self {
40 ClockSrc::HSE(..) => Sw::HSE32,
41 ClockSrc::HSI16 => Sw::HSI16,
42 }
43 }
44}
45
46#[derive(Copy, Clone)]
47pub struct Config {
48 pub mux: ClockSrc,
49 pub ahb_pre: AHBPrescaler,
50 pub apb1_pre: APBPrescaler,
51 pub apb2_pre: APBPrescaler,
52 pub apb7_pre: APBPrescaler,
53}
54
55impl Default for Config {
56 fn default() -> Self {
57 Self {
58 mux: ClockSrc::HSI16,
59 ahb_pre: AHBPrescaler::DIV1,
60 apb1_pre: APBPrescaler::DIV1,
61 apb2_pre: APBPrescaler::DIV1,
62 apb7_pre: APBPrescaler::DIV1,
63 }
64 }
65}
66
67pub(crate) unsafe fn init(config: Config) {
68 let sys_clk = match config.mux {
69 ClockSrc::HSE(freq) => {
70 RCC.cr().write(|w| w.set_hseon(true));
71 while !RCC.cr().read().hserdy() {}
72
73 freq
74 }
75 ClockSrc::HSI16 => {
76 RCC.cr().write(|w| w.set_hsion(true));
77 while !RCC.cr().read().hsirdy() {}
78
79 HSI_FREQ
80 }
81 };
82
83 // TODO make configurable
84 let power_vos = VoltageScale::RANGE1;
85
86 // states and programming delay
87 let wait_states = match power_vos {
88 VoltageScale::RANGE1 => match sys_clk.0 {
89 ..=32_000_000 => 0,
90 ..=64_000_000 => 1,
91 ..=96_000_000 => 2,
92 ..=100_000_000 => 3,
93 _ => 4,
94 },
95 VoltageScale::RANGE2 => match sys_clk.0 {
96 ..=8_000_000 => 0,
97 ..=16_000_000 => 1,
98 _ => 2,
99 },
100 };
101
102 FLASH.acr().modify(|w| {
103 w.set_latency(wait_states);
104 });
105
106 RCC.cfgr1().modify(|w| {
107 w.set_sw(config.mux.into());
108 });
109
110 RCC.cfgr2().modify(|w| {
111 w.set_hpre(config.ahb_pre.into());
112 w.set_ppre1(config.apb1_pre.into());
113 w.set_ppre2(config.apb2_pre.into());
114 });
115
116 RCC.cfgr3().modify(|w| {
117 w.set_ppre7(config.apb7_pre.into());
118 });
119
120 let ahb_freq = sys_clk / config.ahb_pre;
121 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
122 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
123 pre => {
124 let freq = ahb_freq / pre;
125 (freq, freq * 2u32)
126 }
127 };
128 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
129 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
130 pre => {
131 let freq = ahb_freq / pre;
132 (freq, freq * 2u32)
133 }
134 };
135 let (apb7_freq, _apb7_tim_freq) = match config.apb7_pre {
136 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
137 pre => {
138 let freq = ahb_freq / pre;
139 (freq, freq * 2u32)
140 }
141 };
142
143 set_freqs(Clocks {
144 sys: sys_clk,
145 ahb1: ahb_freq,
146 ahb2: ahb_freq,
147 ahb4: ahb_freq,
148 apb1: apb1_freq,
149 apb2: apb2_freq,
150 apb7: apb7_freq,
151 apb1_tim: apb1_tim_freq,
152 apb2_tim: apb2_tim_freq,
153 });
154}
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs
index f1dd2bd7e..6643d278a 100644
--- a/embassy-stm32/src/rcc/wl.rs
+++ b/embassy-stm32/src/rcc/wl.rs
@@ -1,8 +1,9 @@
1pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale}; 1pub use super::bus::{AHBPrescaler, APBPrescaler};
2use crate::pac::pwr::vals::Dbp; 2pub use crate::pac::pwr::vals::Vos as VoltageScale;
3use crate::pac::{FLASH, PWR, RCC}; 3use crate::pac::rcc::vals::Adcsel;
4use crate::pac::{FLASH, RCC};
5use crate::rcc::bd::{BackupDomain, RtcClockSource};
4use crate::rcc::{set_freqs, Clocks}; 6use crate::rcc::{set_freqs, Clocks};
5use crate::rtc::{Rtc, RtcClockSource as RCS};
6use crate::time::Hertz; 7use crate::time::Hertz;
7 8
8/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC, 9/// Most of clock setup is copied from stm32l0xx-hal, and adopted to the generated PAC,
@@ -75,9 +76,9 @@ impl MSIRange {
75 76
76 fn vos(&self) -> VoltageScale { 77 fn vos(&self) -> VoltageScale {
77 if self > &MSIRange::Range8 { 78 if self > &MSIRange::Range8 {
78 VoltageScale::Scale0 79 VoltageScale::RANGE1
79 } else { 80 } else {
80 VoltageScale::Scale1 81 VoltageScale::RANGE2
81 } 82 }
82 } 83 }
83} 84}
@@ -107,6 +108,29 @@ impl Into<u8> for MSIRange {
107 } 108 }
108} 109}
109 110
111#[derive(Clone, Copy)]
112pub enum AdcClockSource {
113 HSI16,
114 PLLPCLK,
115 SYSCLK,
116}
117
118impl AdcClockSource {
119 pub fn adcsel(&self) -> Adcsel {
120 match self {
121 AdcClockSource::HSI16 => Adcsel::HSI16,
122 AdcClockSource::PLLPCLK => Adcsel::PLLPCLK,
123 AdcClockSource::SYSCLK => Adcsel::SYSCLK,
124 }
125 }
126}
127
128impl Default for AdcClockSource {
129 fn default() -> Self {
130 Self::HSI16
131 }
132}
133
110/// Clocks configutation 134/// Clocks configutation
111pub struct Config { 135pub struct Config {
112 pub mux: ClockSrc, 136 pub mux: ClockSrc,
@@ -114,9 +138,10 @@ pub struct Config {
114 pub shd_ahb_pre: AHBPrescaler, 138 pub shd_ahb_pre: AHBPrescaler,
115 pub apb1_pre: APBPrescaler, 139 pub apb1_pre: APBPrescaler,
116 pub apb2_pre: APBPrescaler, 140 pub apb2_pre: APBPrescaler,
117 pub enable_lsi: bool,
118 pub enable_rtc_apb: bool,
119 pub rtc_mux: RtcClockSource, 141 pub rtc_mux: RtcClockSource,
142 pub lse: Option<Hertz>,
143 pub lsi: bool,
144 pub adc_clock_source: AdcClockSource,
120} 145}
121 146
122impl Default for Config { 147impl Default for Config {
@@ -124,22 +149,18 @@ impl Default for Config {
124 fn default() -> Config { 149 fn default() -> Config {
125 Config { 150 Config {
126 mux: ClockSrc::MSI(MSIRange::default()), 151 mux: ClockSrc::MSI(MSIRange::default()),
127 ahb_pre: AHBPrescaler::NotDivided, 152 ahb_pre: AHBPrescaler::DIV1,
128 shd_ahb_pre: AHBPrescaler::NotDivided, 153 shd_ahb_pre: AHBPrescaler::DIV1,
129 apb1_pre: APBPrescaler::NotDivided, 154 apb1_pre: APBPrescaler::DIV1,
130 apb2_pre: APBPrescaler::NotDivided, 155 apb2_pre: APBPrescaler::DIV1,
131 enable_lsi: false, 156 rtc_mux: RtcClockSource::LSI,
132 enable_rtc_apb: false, 157 lsi: true,
133 rtc_mux: RtcClockSource::LSI32, 158 lse: None,
159 adc_clock_source: AdcClockSource::default(),
134 } 160 }
135 } 161 }
136} 162}
137 163
138pub enum RtcClockSource {
139 LSE32,
140 LSI32,
141}
142
143#[repr(u8)] 164#[repr(u8)]
144pub enum Lsedrv { 165pub enum Lsedrv {
145 Low = 0, 166 Low = 0,
@@ -150,13 +171,13 @@ pub enum Lsedrv {
150 171
151pub(crate) unsafe fn init(config: Config) { 172pub(crate) unsafe fn init(config: Config) {
152 let (sys_clk, sw, vos) = match config.mux { 173 let (sys_clk, sw, vos) = match config.mux {
153 ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Scale1), 174 ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::RANGE2),
154 ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::Scale0), 175 ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::RANGE1),
155 ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()), 176 ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()),
156 }; 177 };
157 178
158 let ahb_freq: u32 = match config.ahb_pre { 179 let ahb_freq: u32 = match config.ahb_pre {
159 AHBPrescaler::NotDivided => sys_clk, 180 AHBPrescaler::DIV1 => sys_clk,
160 pre => { 181 pre => {
161 let pre: u8 = pre.into(); 182 let pre: u8 = pre.into();
162 let pre = 1 << (pre as u32 - 7); 183 let pre = 1 << (pre as u32 - 7);
@@ -165,7 +186,7 @@ pub(crate) unsafe fn init(config: Config) {
165 }; 186 };
166 187
167 let shd_ahb_freq: u32 = match config.shd_ahb_pre { 188 let shd_ahb_freq: u32 = match config.shd_ahb_pre {
168 AHBPrescaler::NotDivided => sys_clk, 189 AHBPrescaler::DIV1 => sys_clk,
169 pre => { 190 pre => {
170 let pre: u8 = pre.into(); 191 let pre: u8 = pre.into();
171 let pre = 1 << (pre as u32 - 7); 192 let pre = 1 << (pre as u32 - 7);
@@ -174,7 +195,7 @@ pub(crate) unsafe fn init(config: Config) {
174 }; 195 };
175 196
176 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre { 197 let (apb1_freq, apb1_tim_freq) = match config.apb1_pre {
177 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 198 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
178 pre => { 199 pre => {
179 let pre: u8 = pre.into(); 200 let pre: u8 = pre.into();
180 let pre: u8 = 1 << (pre - 3); 201 let pre: u8 = 1 << (pre - 3);
@@ -184,7 +205,7 @@ pub(crate) unsafe fn init(config: Config) {
184 }; 205 };
185 206
186 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre { 207 let (apb2_freq, apb2_tim_freq) = match config.apb2_pre {
187 APBPrescaler::NotDivided => (ahb_freq, ahb_freq), 208 APBPrescaler::DIV1 => (ahb_freq, ahb_freq),
188 pre => { 209 pre => {
189 let pre: u8 = pre.into(); 210 let pre: u8 = pre.into();
190 let pre: u8 = 1 << (pre - 3); 211 let pre: u8 = 1 << (pre - 3);
@@ -196,16 +217,17 @@ pub(crate) unsafe fn init(config: Config) {
196 // Adjust flash latency 217 // Adjust flash latency
197 let flash_clk_src_freq: u32 = shd_ahb_freq; 218 let flash_clk_src_freq: u32 = shd_ahb_freq;
198 let ws = match vos { 219 let ws = match vos {
199 VoltageScale::Scale0 => match flash_clk_src_freq { 220 VoltageScale::RANGE1 => match flash_clk_src_freq {
200 0..=18_000_000 => 0b000, 221 0..=18_000_000 => 0b000,
201 18_000_001..=36_000_000 => 0b001, 222 18_000_001..=36_000_000 => 0b001,
202 _ => 0b010, 223 _ => 0b010,
203 }, 224 },
204 VoltageScale::Scale1 => match flash_clk_src_freq { 225 VoltageScale::RANGE2 => match flash_clk_src_freq {
205 0..=6_000_000 => 0b000, 226 0..=6_000_000 => 0b000,
206 6_000_001..=12_000_000 => 0b001, 227 6_000_001..=12_000_000 => 0b001,
207 _ => 0b010, 228 _ => 0b010,
208 }, 229 },
230 _ => unreachable!(),
209 }; 231 };
210 232
211 FLASH.acr().modify(|w| { 233 FLASH.acr().modify(|w| {
@@ -214,35 +236,8 @@ pub(crate) unsafe fn init(config: Config) {
214 236
215 while FLASH.acr().read().latency() != ws {} 237 while FLASH.acr().read().latency() != ws {}
216 238
217 match config.rtc_mux { 239 // Enables the LSI if configured
218 RtcClockSource::LSE32 => { 240 BackupDomain::configure_ls(config.rtc_mux, config.lsi, config.lse.map(|_| Default::default()));
219 // 1. Unlock the backup domain
220 PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED));
221
222 // 2. Setup the LSE
223 RCC.bdcr().modify(|w| {
224 // Enable LSE
225 w.set_lseon(true);
226 // Max drive strength
227 // TODO: should probably be settable
228 w.set_lsedrv(Lsedrv::High as u8); //---// PAM - should not be commented
229 });
230
231 // Wait until LSE is running
232 while !RCC.bdcr().read().lserdy() {}
233
234 Rtc::set_clock_source(RCS::LSE);
235 }
236 RtcClockSource::LSI32 => {
237 // Turn on the internal 32 kHz LSI oscillator
238 RCC.csr().modify(|w| w.set_lsion(true));
239
240 // Wait until LSI is running
241 while !RCC.csr().read().lsirdy() {}
242
243 Rtc::set_clock_source(RCS::LSI);
244 }
245 }
246 241
247 match config.mux { 242 match config.mux {
248 ClockSrc::HSI16 => { 243 ClockSrc::HSI16 => {
@@ -266,7 +261,7 @@ pub(crate) unsafe fn init(config: Config) {
266 w.set_msirange(range.into()); 261 w.set_msirange(range.into());
267 w.set_msion(true); 262 w.set_msion(true);
268 263
269 if let RtcClockSource::LSE32 = config.rtc_mux { 264 if let RtcClockSource::LSE = config.rtc_mux {
270 // If LSE is enabled, enable calibration of MSI 265 // If LSE is enabled, enable calibration of MSI
271 w.set_msipllen(true); 266 w.set_msipllen(true);
272 } else { 267 } else {
@@ -277,16 +272,8 @@ pub(crate) unsafe fn init(config: Config) {
277 } 272 }
278 } 273 }
279 274
280 if config.enable_rtc_apb {
281 // enable peripheral clock for communication
282 crate::pac::RCC.apb1enr1().modify(|w| w.set_rtcapben(true));
283
284 // read to allow the pwr clock to enable
285 crate::pac::PWR.cr1().read();
286 }
287
288 RCC.extcfgr().modify(|w| { 275 RCC.extcfgr().modify(|w| {
289 if config.shd_ahb_pre == AHBPrescaler::NotDivided { 276 if config.shd_ahb_pre == AHBPrescaler::DIV1 {
290 w.set_shdhpre(0); 277 w.set_shdhpre(0);
291 } else { 278 } else {
292 w.set_shdhpre(config.shd_ahb_pre.into()); 279 w.set_shdhpre(config.shd_ahb_pre.into());
@@ -295,24 +282,15 @@ pub(crate) unsafe fn init(config: Config) {
295 282
296 RCC.cfgr().modify(|w| { 283 RCC.cfgr().modify(|w| {
297 w.set_sw(sw.into()); 284 w.set_sw(sw.into());
298 if config.ahb_pre == AHBPrescaler::NotDivided { 285 w.set_hpre(config.ahb_pre);
299 w.set_hpre(0);
300 } else {
301 w.set_hpre(config.ahb_pre.into());
302 }
303 w.set_ppre1(config.apb1_pre.into()); 286 w.set_ppre1(config.apb1_pre.into());
304 w.set_ppre2(config.apb2_pre.into()); 287 w.set_ppre2(config.apb2_pre.into());
305 }); 288 });
306 289
307 // TODO: switch voltage range 290 // ADC clock MUX
291 RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source.adcsel()));
308 292
309 if config.enable_lsi { 293 // TODO: switch voltage range
310 let csr = RCC.csr().read();
311 if !csr.lsion() {
312 RCC.csr().modify(|w| w.set_lsion(true));
313 while !RCC.csr().read().lsirdy() {}
314 }
315 }
316 294
317 set_freqs(Clocks { 295 set_freqs(Clocks {
318 sys: Hertz(sys_clk), 296 sys: Hertz(sys_clk),
diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs
index 30816e436..0979dce8c 100644
--- a/embassy-stm32/src/rng.rs
+++ b/embassy-stm32/src/rng.rs
@@ -119,7 +119,31 @@ impl<'d, T: Instance> Rng<'d, T> {
119 119
120 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { 120 pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
121 for chunk in dest.chunks_mut(4) { 121 for chunk in dest.chunks_mut(4) {
122 let bits = T::regs().sr().read(); 122 let mut bits = T::regs().sr().read();
123 if !bits.seis() && !bits.ceis() && !bits.drdy() {
124 // wait for interrupt
125 poll_fn(|cx| {
126 // quick check to avoid registration if already done.
127 let bits = T::regs().sr().read();
128 if bits.drdy() || bits.seis() || bits.ceis() {
129 return Poll::Ready(());
130 }
131 RNG_WAKER.register(cx.waker());
132 T::regs().cr().modify(|reg| reg.set_ie(true));
133 // Need to check condition **after** `register` to avoid a race
134 // condition that would result in lost notifications.
135 let bits = T::regs().sr().read();
136 if bits.drdy() || bits.seis() || bits.ceis() {
137 Poll::Ready(())
138 } else {
139 Poll::Pending
140 }
141 })
142 .await;
143
144 // Re-read the status register after wait.
145 bits = T::regs().sr().read()
146 }
123 if bits.seis() { 147 if bits.seis() {
124 // in case of noise-source or seed error we try to recover here 148 // in case of noise-source or seed error we try to recover here
125 // but we must not use the data in DR and we return an error 149 // but we must not use the data in DR and we return an error
@@ -143,26 +167,6 @@ impl<'d, T: Instance> Rng<'d, T> {
143 for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) { 167 for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) {
144 *dest = *src 168 *dest = *src
145 } 169 }
146 } else {
147 // wait for interrupt
148 poll_fn(|cx| {
149 // quick check to avoid registration if already done.
150 let bits = T::regs().sr().read();
151 if bits.drdy() || bits.seis() || bits.ceis() {
152 return Poll::Ready(());
153 }
154 RNG_WAKER.register(cx.waker());
155 T::regs().cr().modify(|reg| reg.set_ie(true));
156 // Need to check condition **after** `register` to avoid a race
157 // condition that would result in lost notifications.
158 let bits = T::regs().sr().read();
159 if bits.drdy() || bits.seis() || bits.ceis() {
160 Poll::Ready(())
161 } else {
162 Poll::Pending
163 }
164 })
165 .await;
166 } 170 }
167 } 171 }
168 172
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs
index a9c48d88d..3efe9be5d 100644
--- a/embassy-stm32/src/rtc/datetime.rs
+++ b/embassy-stm32/src/rtc/datetime.rs
@@ -89,7 +89,7 @@ pub enum DayOfWeek {
89#[cfg(feature = "chrono")] 89#[cfg(feature = "chrono")]
90impl From<chrono::Weekday> for DayOfWeek { 90impl From<chrono::Weekday> for DayOfWeek {
91 fn from(weekday: Weekday) -> Self { 91 fn from(weekday: Weekday) -> Self {
92 day_of_week_from_u8(weekday.number_from_monday() as u8).unwrap() 92 day_of_week_from_u8(weekday.num_days_from_monday() as u8).unwrap()
93 } 93 }
94} 94}
95 95
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index a6102077a..73b78f253 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -1,7 +1,17 @@
1//! RTC peripheral abstraction 1//! RTC peripheral abstraction
2mod datetime; 2mod datetime;
3 3
4#[cfg(feature = "low-power")]
5use core::cell::Cell;
6
7#[cfg(feature = "low-power")]
8use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9#[cfg(feature = "low-power")]
10use embassy_sync::blocking_mutex::Mutex;
11
4pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; 12pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
13pub use crate::rcc::RtcClockSource;
14use crate::time::Hertz;
5 15
6/// refer to AN4759 to compare features of RTC2 and RTC3 16/// refer to AN4759 to compare features of RTC2 and RTC3
7#[cfg_attr(any(rtc_v1), path = "v1.rs")] 17#[cfg_attr(any(rtc_v1), path = "v1.rs")]
@@ -30,60 +40,99 @@ pub enum RtcError {
30 NotRunning, 40 NotRunning,
31} 41}
32 42
33/// RTC Abstraction 43#[cfg(feature = "low-power")]
34pub struct Rtc { 44/// Represents an instant in time that can be substracted to compute a duration
35 rtc_config: RtcConfig, 45struct RtcInstant {
46 second: u8,
47 subsecond: u16,
36} 48}
37 49
38#[derive(Copy, Clone, Debug, PartialEq)] 50#[cfg(all(feature = "low-power", feature = "defmt"))]
39#[repr(u8)] 51impl defmt::Format for RtcInstant {
40pub enum RtcClockSource { 52 fn format(&self, fmt: defmt::Formatter) {
41 /// 00: No clock 53 defmt::write!(
42 NoClock = 0b00, 54 fmt,
43 /// 01: LSE oscillator clock used as RTC clock 55 "{}:{}",
44 LSE = 0b01, 56 self.second,
45 /// 10: LSI oscillator clock used as RTC clock 57 RTC::regs().prer().read().prediv_s() - self.subsecond,
46 LSI = 0b10, 58 )
47 /// 11: HSE oscillator clock divided by 32 used as RTC clock 59 }
48 HSE = 0b11, 60}
61
62#[cfg(feature = "low-power")]
63impl core::ops::Sub for RtcInstant {
64 type Output = embassy_time::Duration;
65
66 fn sub(self, rhs: Self) -> Self::Output {
67 use embassy_time::{Duration, TICK_HZ};
68
69 let second = if self.second < rhs.second {
70 self.second + 60
71 } else {
72 self.second
73 };
74
75 let psc = RTC::regs().prer().read().prediv_s() as u32;
76
77 let self_ticks = second as u32 * (psc + 1) + (psc - self.subsecond as u32);
78 let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32);
79 let rtc_ticks = self_ticks - other_ticks;
80
81 Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / (psc + 1)) as u64)
82 }
83}
84
85pub struct RtcTimeProvider {
86 _private: (),
87}
88
89impl RtcTimeProvider {
90 /// Return the current datetime.
91 ///
92 /// # Errors
93 ///
94 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
95 pub fn now(&self) -> Result<DateTime, RtcError> {
96 let r = RTC::regs();
97 let tr = r.tr().read();
98 let second = bcd2_to_byte((tr.st(), tr.su()));
99 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
100 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
101 // Reading either RTC_SSR or RTC_TR locks the values in the higher-order
102 // calendar shadow registers until RTC_DR is read.
103 let dr = r.dr().read();
104
105 let weekday = dr.wdu();
106 let day = bcd2_to_byte((dr.dt(), dr.du()));
107 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
108 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
109
110 self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
111 }
112}
113
114/// RTC Abstraction
115pub struct Rtc {
116 #[cfg(feature = "low-power")]
117 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<RtcInstant>>>,
118 #[cfg(not(feature = "low-power"))]
119 _private: (),
49} 120}
50 121
122#[non_exhaustive]
51#[derive(Copy, Clone, PartialEq)] 123#[derive(Copy, Clone, PartialEq)]
52pub struct RtcConfig { 124pub struct RtcConfig {
53 /// Asynchronous prescaler factor 125 /// The subsecond counter frequency; default is 256
54 /// This is the asynchronous division factor: 126 ///
55 /// ck_apre frequency = RTCCLK frequency/(PREDIV_A+1) 127 /// A high counter frequency may impact stop power consumption
56 /// ck_apre drives the subsecond register 128 pub frequency: Hertz,
57 async_prescaler: u8,
58 /// Synchronous prescaler factor
59 /// This is the synchronous division factor:
60 /// ck_spre frequency = ck_apre frequency/(PREDIV_S+1)
61 /// ck_spre must be 1Hz
62 sync_prescaler: u16,
63} 129}
64 130
65impl Default for RtcConfig { 131impl Default for RtcConfig {
66 /// LSI with prescalers assuming 32.768 kHz. 132 /// LSI with prescalers assuming 32.768 kHz.
67 /// Raw sub-seconds in 1/256. 133 /// Raw sub-seconds in 1/256.
68 fn default() -> Self { 134 fn default() -> Self {
69 RtcConfig { 135 RtcConfig { frequency: Hertz(256) }
70 async_prescaler: 127,
71 sync_prescaler: 255,
72 }
73 }
74}
75
76impl RtcConfig {
77 /// Set the asynchronous prescaler of RTC config
78 pub fn async_prescaler(mut self, prescaler: u8) -> Self {
79 self.async_prescaler = prescaler;
80 self
81 }
82
83 /// Set the synchronous prescaler of RTC config
84 pub fn sync_prescaler(mut self, prescaler: u16) -> Self {
85 self.sync_prescaler = prescaler;
86 self
87 } 136 }
88} 137}
89 138
@@ -106,16 +155,44 @@ impl Default for RtcCalibrationCyclePeriod {
106 155
107impl Rtc { 156impl Rtc {
108 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { 157 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
109 RTC::enable_peripheral_clk(); 158 #[cfg(any(rcc_wle, rcc_wl5, rcc_g4, rcc_g0, rtc_v2l4, rtc_v2wb))]
159 <RTC as crate::rcc::sealed::RccPeripheral>::enable();
160
161 let mut this = Self {
162 #[cfg(feature = "low-power")]
163 stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)),
164 #[cfg(not(feature = "low-power"))]
165 _private: (),
166 };
167
168 let frequency = Self::frequency();
169 let async_psc = ((frequency.0 / rtc_config.frequency.0) - 1) as u8;
170 let sync_psc = (rtc_config.frequency.0 - 1) as u16;
110 171
111 let mut rtc_struct = Self { rtc_config }; 172 this.configure(async_psc, sync_psc);
112 173
113 Self::enable(); 174 this
175 }
176
177 fn frequency() -> Hertz {
178 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
179 let freqs = unsafe { crate::rcc::get_freqs() };
180
181 // Load the clock frequency from the rcc mod, if supported
182 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
183 match freqs.rtc {
184 Some(hertz) => hertz,
185 None => freqs.rtc_hse.unwrap(),
186 }
114 187
115 rtc_struct.configure(rtc_config); 188 // Assume the default value, if not supported
116 rtc_struct.rtc_config = rtc_config; 189 #[cfg(not(any(rcc_wb, rcc_f4, rcc_f410)))]
190 Hertz(32_768)
191 }
117 192
118 rtc_struct 193 /// Acquire a [`RtcTimeProvider`] instance.
194 pub const fn time_provider(&self) -> RtcTimeProvider {
195 RtcTimeProvider { _private: () }
119 } 196 }
120 197
121 /// Set the datetime to a new value. 198 /// Set the datetime to a new value.
@@ -130,27 +207,27 @@ impl Rtc {
130 Ok(()) 207 Ok(())
131 } 208 }
132 209
210 #[cfg(feature = "low-power")]
211 /// Return the current instant.
212 fn instant(&self) -> RtcInstant {
213 let r = RTC::regs();
214 let tr = r.tr().read();
215 let subsecond = r.ssr().read().ss();
216 let second = bcd2_to_byte((tr.st(), tr.su()));
217
218 // Unlock the registers
219 r.dr().read();
220
221 RtcInstant { second, subsecond }
222 }
223
133 /// Return the current datetime. 224 /// Return the current datetime.
134 /// 225 ///
135 /// # Errors 226 /// # Errors
136 /// 227 ///
137 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. 228 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
138 pub fn now(&self) -> Result<DateTime, RtcError> { 229 pub fn now(&self) -> Result<DateTime, RtcError> {
139 let r = RTC::regs(); 230 self.time_provider().now()
140 let tr = r.tr().read();
141 let second = bcd2_to_byte((tr.st(), tr.su()));
142 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
143 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
144 // Reading either RTC_SSR or RTC_TR locks the values in the higher-order
145 // calendar shadow registers until RTC_DR is read.
146 let dr = r.dr().read();
147
148 let weekday = dr.wdu();
149 let day = bcd2_to_byte((dr.dt(), dr.du()));
150 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
151 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
152
153 self::datetime::datetime(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
154 } 231 }
155 232
156 /// Check if daylight savings time is active. 233 /// Check if daylight savings time is active.
@@ -166,10 +243,6 @@ impl Rtc {
166 }) 243 })
167 } 244 }
168 245
169 pub fn get_config(&self) -> RtcConfig {
170 self.rtc_config
171 }
172
173 pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT; 246 pub const BACKUP_REGISTER_COUNT: usize = RTC::BACKUP_REGISTER_COUNT;
174 247
175 /// Read content of the backup register. 248 /// Read content of the backup register.
@@ -215,12 +288,16 @@ pub(crate) mod sealed {
215 pub trait Instance { 288 pub trait Instance {
216 const BACKUP_REGISTER_COUNT: usize; 289 const BACKUP_REGISTER_COUNT: usize;
217 290
291 #[cfg(feature = "low-power")]
292 const EXTI_WAKEUP_LINE: usize;
293
294 #[cfg(feature = "low-power")]
295 type WakeupInterrupt: crate::interrupt::typelevel::Interrupt;
296
218 fn regs() -> Rtc { 297 fn regs() -> Rtc {
219 crate::pac::RTC 298 crate::pac::RTC
220 } 299 }
221 300
222 fn enable_peripheral_clk() {}
223
224 /// Read content of the backup register. 301 /// Read content of the backup register.
225 /// 302 ///
226 /// The registers retain their values during wakes from standby mode or system resets. They also 303 /// The registers retain their values during wakes from standby mode or system resets. They also
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index bcb127ecb..4608d3114 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -1,77 +1,21 @@
1use stm32_metapac::rtc::vals::{Init, Osel, Pol}; 1use stm32_metapac::rtc::vals::{Init, Osel, Pol};
2 2
3use super::{sealed, RtcClockSource, RtcConfig}; 3use super::sealed;
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC; 5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance; 6use crate::rtc::sealed::Instance;
7 7
8#[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
9pub struct RtcInstant {
10 ssr: u16,
11 st: u8,
12}
13
14#[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
15impl RtcInstant {
16 pub fn now() -> Self {
17 // TODO: read value twice
18 use crate::rtc::bcd2_to_byte;
19
20 let tr = RTC::regs().tr().read();
21 let tr2 = RTC::regs().tr().read();
22 let ssr = RTC::regs().ssr().read().ss();
23 let ssr2 = RTC::regs().ssr().read().ss();
24
25 let st = bcd2_to_byte((tr.st(), tr.su()));
26 let st2 = bcd2_to_byte((tr2.st(), tr2.su()));
27
28 assert!(st == st2);
29 assert!(ssr == ssr2);
30
31 let _ = RTC::regs().dr().read();
32
33 trace!("ssr: {}", ssr);
34 trace!("st: {}", st);
35
36 Self { ssr, st }
37 }
38}
39
40#[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
41impl core::ops::Sub for RtcInstant {
42 type Output = embassy_time::Duration;
43
44 fn sub(self, rhs: Self) -> Self::Output {
45 use embassy_time::{Duration, TICK_HZ};
46
47 let st = if self.st < rhs.st { self.st + 60 } else { self.st };
48
49 // TODO: read prescaler
50
51 let self_ticks = st as u32 * 256 + (255 - self.ssr as u32);
52 let other_ticks = rhs.st as u32 * 256 + (255 - rhs.ssr as u32);
53 let rtc_ticks = self_ticks - other_ticks;
54
55 trace!("self, other, rtc ticks: {}, {}, {}", self_ticks, other_ticks, rtc_ticks);
56
57 Duration::from_ticks(
58 ((((st as u32 * 256 + (255u32 - self.ssr as u32)) - (rhs.st as u32 * 256 + (255u32 - rhs.ssr as u32)))
59 * TICK_HZ as u32) as u32
60 / 256u32) as u64,
61 )
62 }
63}
64
65#[allow(dead_code)] 8#[allow(dead_code)]
9#[repr(u8)]
66#[derive(Clone, Copy, Debug)] 10#[derive(Clone, Copy, Debug)]
67pub(crate) enum WakeupPrescaler { 11pub(crate) enum WakeupPrescaler {
68 Div2, 12 Div2 = 2,
69 Div4, 13 Div4 = 4,
70 Div8, 14 Div8 = 8,
71 Div16, 15 Div16 = 16,
72} 16}
73 17
74#[cfg(any(stm32wb, stm32f4))] 18#[cfg(any(stm32wb, stm32f4, stm32l0))]
75impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { 19impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
76 fn from(val: WakeupPrescaler) -> Self { 20 fn from(val: WakeupPrescaler) -> Self {
77 use crate::pac::rtc::vals::Wucksel; 21 use crate::pac::rtc::vals::Wucksel;
@@ -85,7 +29,7 @@ impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel {
85 } 29 }
86} 30}
87 31
88#[cfg(any(stm32wb, stm32f4))] 32#[cfg(any(stm32wb, stm32f4, stm32l0))]
89impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { 33impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
90 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { 34 fn from(val: crate::pac::rtc::vals::Wucksel) -> Self {
91 use crate::pac::rtc::vals::Wucksel; 35 use crate::pac::rtc::vals::Wucksel;
@@ -100,17 +44,6 @@ impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler {
100 } 44 }
101} 45}
102 46
103impl From<WakeupPrescaler> for u32 {
104 fn from(val: WakeupPrescaler) -> Self {
105 match val {
106 WakeupPrescaler::Div2 => 2,
107 WakeupPrescaler::Div4 => 4,
108 WakeupPrescaler::Div8 => 8,
109 WakeupPrescaler::Div16 => 16,
110 }
111 }
112}
113
114#[allow(dead_code)] 47#[allow(dead_code)]
115impl WakeupPrescaler { 48impl WakeupPrescaler {
116 pub fn compute_min(val: u32) -> Self { 49 pub fn compute_min(val: u32) -> Self {
@@ -121,158 +54,100 @@ impl WakeupPrescaler {
121 WakeupPrescaler::Div16, 54 WakeupPrescaler::Div16,
122 ] 55 ]
123 .iter() 56 .iter()
124 .skip_while(|psc| <WakeupPrescaler as Into<u32>>::into(**psc) <= val) 57 .skip_while(|psc| **psc as u32 <= val)
125 .next() 58 .next()
126 .unwrap_or(&WakeupPrescaler::Div16) 59 .unwrap_or(&WakeupPrescaler::Div16)
127 } 60 }
128} 61}
129 62
130impl super::Rtc { 63impl super::Rtc {
131 fn unlock_registers() { 64 #[cfg(feature = "low-power")]
132 #[cfg(any(rtc_v2f2, rtc_v2f3, rtc_v2l1))] 65 /// start the wakeup alarm and wtih a duration that is as close to but less than
133 let cr = crate::pac::PWR.cr(); 66 /// the requested duration, and record the instant the wakeup alarm was started
134 #[cfg(any(rtc_v2f4, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] 67 pub(crate) fn start_wakeup_alarm(
135 let cr = crate::pac::PWR.cr1(); 68 &self,
136 69 requested_duration: embassy_time::Duration,
137 // TODO: Missing from PAC for l0 and f0? 70 cs: critical_section::CriticalSection,
138 #[cfg(not(any(rtc_v2f0, rtc_v2l0)))] 71 ) {
139 {
140 if !cr.read().dbp() {
141 cr.modify(|w| w.set_dbp(true));
142 while !cr.read().dbp() {}
143 }
144 }
145 }
146
147 #[allow(dead_code)]
148 #[cfg(all(feature = "time", any(stm32wb, stm32f4)))]
149 /// start the wakeup alarm and return the actual duration of the alarm
150 /// the actual duration will be the closest value possible that is less
151 /// than the requested duration.
152 ///
153 /// note: this api is exposed for testing purposes until low power is implemented.
154 /// it is not intended to be public
155 pub(crate) fn start_wakeup_alarm(&self, requested_duration: embassy_time::Duration) -> RtcInstant {
156 use embassy_time::{Duration, TICK_HZ}; 72 use embassy_time::{Duration, TICK_HZ};
157 73
158 use crate::rcc::get_freqs; 74 // Panic if the rcc mod knows we're not using low-power rtc
75 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
76 unsafe { crate::rcc::get_freqs() }.rtc.unwrap();
159 77
160 let rtc_hz = unsafe { get_freqs() }.rtc.unwrap().0 as u64; 78 let requested_duration = requested_duration.as_ticks().clamp(0, u32::MAX as u64);
161 79 let rtc_hz = Self::frequency().0 as u64;
162 let rtc_ticks = requested_duration.as_ticks() * rtc_hz / TICK_HZ; 80 let rtc_ticks = requested_duration * rtc_hz / TICK_HZ;
163 let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32); 81 let prescaler = WakeupPrescaler::compute_min((rtc_ticks / u16::MAX as u64) as u32);
164 82
165 // adjust the rtc ticks to the prescaler 83 // adjust the rtc ticks to the prescaler and subtract one rtc tick
166 let rtc_ticks = rtc_ticks / (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64); 84 let rtc_ticks = rtc_ticks / prescaler as u64;
167 let rtc_ticks = if rtc_ticks >= u16::MAX as u64 { 85 let rtc_ticks = rtc_ticks.clamp(0, (u16::MAX - 1) as u64).saturating_sub(1) as u16;
168 u16::MAX - 1
169 } else {
170 rtc_ticks as u16
171 };
172
173 let duration = Duration::from_ticks(
174 rtc_ticks as u64 * TICK_HZ * (<WakeupPrescaler as Into<u32>>::into(prescaler) as u64) / rtc_hz,
175 );
176
177 trace!("set wakeup timer for {} ms", duration.as_millis());
178 86
179 self.write(false, |regs| { 87 self.write(false, |regs| {
180 regs.cr().modify(|w| w.set_wutie(true));
181
182 regs.cr().modify(|w| w.set_wute(false)); 88 regs.cr().modify(|w| w.set_wute(false));
183 regs.isr().modify(|w| w.set_wutf(false)); 89 regs.isr().modify(|w| w.set_wutf(false));
184 while !regs.isr().read().wutwf() {} 90 while !regs.isr().read().wutwf() {}
185 91
186 regs.cr().modify(|w| w.set_wucksel(prescaler.into())); 92 regs.cr().modify(|w| w.set_wucksel(prescaler.into()));
93 regs.wutr().write(|w| w.set_wut(rtc_ticks));
187 regs.cr().modify(|w| w.set_wute(true)); 94 regs.cr().modify(|w| w.set_wute(true));
95 regs.cr().modify(|w| w.set_wutie(true));
188 }); 96 });
189 97
190 RtcInstant::now() 98 trace!(
99 "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}",
100 Duration::from_ticks(rtc_ticks as u64 * TICK_HZ * prescaler as u64 / rtc_hz).as_millis(),
101 prescaler as u32,
102 rtc_ticks,
103 self.instant(),
104 );
105
106 assert!(self.stop_time.borrow(cs).replace(Some(self.instant())).is_none())
191 } 107 }
192 108
193 #[allow(dead_code)] 109 #[cfg(feature = "low-power")]
194 #[cfg(all(feature = "time", any(stm32wb, stm32f4)))] 110 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
195 /// stop the wakeup alarm and return the time remaining 111 /// was called, otherwise none
196 /// 112 pub(crate) fn stop_wakeup_alarm(&self, cs: critical_section::CriticalSection) -> Option<embassy_time::Duration> {
197 /// note: this api is exposed for testing purposes until low power is implemented. 113 use crate::interrupt::typelevel::Interrupt;
198 /// it is not intended to be public 114
199 pub(crate) fn stop_wakeup_alarm(&self) -> RtcInstant { 115 trace!("rtc: stop wakeup alarm at {}", self.instant());
200 trace!("disable wakeup timer...");
201 116
202 self.write(false, |regs| { 117 self.write(false, |regs| {
118 regs.cr().modify(|w| w.set_wutie(false));
203 regs.cr().modify(|w| w.set_wute(false)); 119 regs.cr().modify(|w| w.set_wute(false));
204 regs.isr().modify(|w| w.set_wutf(false)); 120 regs.isr().modify(|w| w.set_wutf(false));
205 });
206
207 RtcInstant::now()
208 }
209
210 #[allow(dead_code)]
211 pub(crate) fn set_clock_source(clock_source: RtcClockSource) {
212 #[cfg(not(rtc_v2wb))]
213 use stm32_metapac::rcc::vals::Rtcsel;
214 121
215 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 122 crate::pac::EXTI
216 let cr = crate::pac::RCC.bdcr(); 123 .pr(0)
217 #[cfg(any(rtc_v2l0, rtc_v2l1))] 124 .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
218 let cr = crate::pac::RCC.csr();
219 125
220 Self::unlock_registers(); 126 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
221
222 cr.modify(|w| {
223 // Select RTC source
224 #[cfg(not(rtc_v2wb))]
225 w.set_rtcsel(Rtcsel::from_bits(clock_source as u8));
226 #[cfg(rtc_v2wb)]
227 w.set_rtcsel(clock_source as u8);
228 }); 127 });
229 }
230 128
231 pub(super) fn enable() { 129 if let Some(stop_time) = self.stop_time.borrow(cs).take() {
232 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] 130 Some(self.instant() - stop_time)
233 let reg = crate::pac::RCC.bdcr().read(); 131 } else {
234 #[cfg(any(rtc_v2l0, rtc_v2l1))] 132 None
235 let reg = crate::pac::RCC.csr().read(); 133 }
236 134 }
237 #[cfg(any(rtc_v2h7, rtc_v2l4, rtc_v2wb))]
238 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
239
240 if !reg.rtcen() {
241 Self::unlock_registers();
242
243 #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))]
244 crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true));
245 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
246 let cr = crate::pac::RCC.bdcr();
247 #[cfg(any(rtc_v2l0, rtc_v2l1))]
248 let cr = crate::pac::RCC.csr();
249
250 cr.modify(|w| {
251 // Reset
252 #[cfg(not(any(rtc_v2l0, rtc_v2l1)))]
253 w.set_bdrst(false);
254
255 w.set_rtcen(true);
256 w.set_rtcsel(reg.rtcsel());
257 135
258 // Restore bcdr 136 #[cfg(feature = "low-power")]
259 #[cfg(any(rtc_v2l4, rtc_v2wb))] 137 pub(crate) fn enable_wakeup_line(&self) {
260 w.set_lscosel(reg.lscosel()); 138 use crate::interrupt::typelevel::Interrupt;
261 #[cfg(any(rtc_v2l4, rtc_v2wb))] 139 use crate::pac::EXTI;
262 w.set_lscoen(reg.lscoen());
263 140
264 w.set_lseon(reg.lseon()); 141 <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
142 unsafe { <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::enable() };
265 143
266 #[cfg(any(rtc_v2f0, rtc_v2f7, rtc_v2h7, rtc_v2l4, rtc_v2wb))] 144 EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
267 w.set_lsedrv(reg.lsedrv()); 145 EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true));
268 w.set_lsebyp(reg.lsebyp());
269 });
270 }
271 } 146 }
272 147
273 /// Applies the RTC config 148 /// Applies the RTC config
274 /// It this changes the RTC clock source the time will be reset 149 /// It this changes the RTC clock source the time will be reset
275 pub(super) fn configure(&mut self, rtc_config: RtcConfig) { 150 pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
276 self.write(true, |rtc| { 151 self.write(true, |rtc| {
277 rtc.cr().modify(|w| { 152 rtc.cr().modify(|w| {
278 #[cfg(rtc_v2f2)] 153 #[cfg(rtc_v2f2)]
@@ -284,8 +159,8 @@ impl super::Rtc {
284 }); 159 });
285 160
286 rtc.prer().modify(|w| { 161 rtc.prer().modify(|w| {
287 w.set_prediv_s(rtc_config.sync_prescaler); 162 w.set_prediv_s(sync_psc);
288 w.set_prediv_a(rtc_config.async_prescaler); 163 w.set_prediv_a(async_psc);
289 }); 164 });
290 }); 165 });
291 } 166 }
@@ -390,21 +265,17 @@ impl super::Rtc {
390impl sealed::Instance for crate::peripherals::RTC { 265impl sealed::Instance for crate::peripherals::RTC {
391 const BACKUP_REGISTER_COUNT: usize = 20; 266 const BACKUP_REGISTER_COUNT: usize = 20;
392 267
393 fn enable_peripheral_clk() { 268 #[cfg(all(feature = "low-power", stm32f4))]
394 #[cfg(any(rtc_v2l4, rtc_v2wb))] 269 const EXTI_WAKEUP_LINE: usize = 22;
395 {
396 // enable peripheral clock for communication
397 crate::pac::RCC.apb1enr1().modify(|w| w.set_rtcapben(true));
398 270
399 // read to allow the pwr clock to enable 271 #[cfg(all(feature = "low-power", stm32l0))]
400 crate::pac::PWR.cr1().read(); 272 const EXTI_WAKEUP_LINE: usize = 20;
401 } 273
402 #[cfg(any(rtc_v2f2))] 274 #[cfg(all(feature = "low-power", stm32f4))]
403 { 275 type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP;
404 crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true)); 276
405 crate::pac::PWR.cr().read(); 277 #[cfg(all(feature = "low-power", stm32l0))]
406 } 278 type WakeupInterrupt = crate::interrupt::typelevel::RTC;
407 }
408 279
409 fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> { 280 fn read_backup_register(rtc: &Rtc, register: usize) -> Option<u32> {
410 if register < Self::BACKUP_REGISTER_COUNT { 281 if register < Self::BACKUP_REGISTER_COUNT {
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs
index 3297303ee..a6b2655d8 100644
--- a/embassy-stm32/src/rtc/v3.rs
+++ b/embassy-stm32/src/rtc/v3.rs
@@ -1,77 +1,14 @@
1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType}; 1use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Init, Key, Osel, Pol, TampalrmPu, TampalrmType};
2 2
3use super::{sealed, RtcCalibrationCyclePeriod, RtcClockSource, RtcConfig}; 3use super::{sealed, RtcCalibrationCyclePeriod};
4use crate::pac::rtc::Rtc; 4use crate::pac::rtc::Rtc;
5use crate::peripherals::RTC; 5use crate::peripherals::RTC;
6use crate::rtc::sealed::Instance; 6use crate::rtc::sealed::Instance;
7 7
8impl super::Rtc { 8impl super::Rtc {
9 fn unlock_registers() {
10 // Unlock the backup domain
11 #[cfg(not(any(rtc_v3u5, rcc_wl5, rcc_wle)))]
12 {
13 if !crate::pac::PWR.cr1().read().dbp() {
14 crate::pac::PWR.cr1().modify(|w| w.set_dbp(true));
15 while !crate::pac::PWR.cr1().read().dbp() {}
16 }
17 }
18 #[cfg(any(rcc_wl5, rcc_wle))]
19 {
20 use crate::pac::pwr::vals::Dbp;
21
22 if crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {
23 crate::pac::PWR.cr1().modify(|w| w.set_dbp(Dbp::ENABLED));
24 while crate::pac::PWR.cr1().read().dbp() != Dbp::ENABLED {}
25 }
26 }
27 }
28
29 #[allow(dead_code)]
30 pub(crate) fn set_clock_source(clock_source: RtcClockSource) {
31 let clock_source = clock_source as u8;
32 #[cfg(not(any(rcc_wl5, rcc_wle)))]
33 let clock_source = crate::pac::rcc::vals::Rtcsel::from_bits(clock_source);
34
35 Self::unlock_registers();
36
37 crate::pac::RCC.bdcr().modify(|w| {
38 // Select RTC source
39 w.set_rtcsel(clock_source);
40 });
41 }
42
43 pub(super) fn enable() {
44 let bdcr = crate::pac::RCC.bdcr();
45
46 let reg = bdcr.read();
47 assert!(!reg.lsecsson(), "RTC is not compatible with LSE CSS, yet.");
48
49 if !reg.rtcen() {
50 Self::unlock_registers();
51
52 bdcr.modify(|w| w.set_bdrst(true));
53
54 bdcr.modify(|w| {
55 // Reset
56 w.set_bdrst(false);
57
58 w.set_rtcen(true);
59 w.set_rtcsel(reg.rtcsel());
60
61 // Restore bcdr
62 w.set_lscosel(reg.lscosel());
63 w.set_lscoen(reg.lscoen());
64
65 w.set_lseon(reg.lseon());
66 w.set_lsedrv(reg.lsedrv());
67 w.set_lsebyp(reg.lsebyp());
68 });
69 }
70 }
71
72 /// Applies the RTC config 9 /// Applies the RTC config
73 /// It this changes the RTC clock source the time will be reset 10 /// It this changes the RTC clock source the time will be reset
74 pub(super) fn configure(&mut self, rtc_config: RtcConfig) { 11 pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
75 self.write(true, |rtc| { 12 self.write(true, |rtc| {
76 rtc.cr().modify(|w| { 13 rtc.cr().modify(|w| {
77 w.set_fmt(Fmt::TWENTYFOURHOUR); 14 w.set_fmt(Fmt::TWENTYFOURHOUR);
@@ -80,8 +17,8 @@ impl super::Rtc {
80 }); 17 });
81 18
82 rtc.prer().modify(|w| { 19 rtc.prer().modify(|w| {
83 w.set_prediv_s(rtc_config.sync_prescaler); 20 w.set_prediv_s(sync_psc);
84 w.set_prediv_a(rtc_config.async_prescaler); 21 w.set_prediv_a(async_psc);
85 }); 22 });
86 23
87 // TODO: configuration for output pins 24 // TODO: configuration for output pins
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 6b532363c..9fb380fd6 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -33,6 +33,8 @@ impl<T: Instance> InterruptHandler<T> {
33 w.set_dtimeoutie(enable); 33 w.set_dtimeoutie(enable);
34 w.set_dataendie(enable); 34 w.set_dataendie(enable);
35 35
36 #[cfg(sdmmc_v1)]
37 w.set_stbiterre(enable);
36 #[cfg(sdmmc_v2)] 38 #[cfg(sdmmc_v2)]
37 w.set_dabortie(enable); 39 w.set_dabortie(enable);
38 }); 40 });
@@ -102,6 +104,8 @@ pub enum Error {
102 BadClock, 104 BadClock,
103 SignalingSwitchFailed, 105 SignalingSwitchFailed,
104 PeripheralBusy, 106 PeripheralBusy,
107 #[cfg(sdmmc_v1)]
108 StBitErr,
105} 109}
106 110
107/// A SD command 111/// A SD command
@@ -707,9 +711,15 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
707 711
708 if status.dcrcfail() { 712 if status.dcrcfail() {
709 return Poll::Ready(Err(Error::Crc)); 713 return Poll::Ready(Err(Error::Crc));
710 } else if status.dtimeout() { 714 }
715 if status.dtimeout() {
711 return Poll::Ready(Err(Error::Timeout)); 716 return Poll::Ready(Err(Error::Timeout));
712 } else if status.dataend() { 717 }
718 #[cfg(sdmmc_v1)]
719 if status.stbiterr() {
720 return Poll::Ready(Err(Error::StBitErr));
721 }
722 if status.dataend() {
713 return Poll::Ready(Ok(())); 723 return Poll::Ready(Ok(()));
714 } 724 }
715 Poll::Pending 725 Poll::Pending
@@ -782,9 +792,15 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
782 792
783 if status.dcrcfail() { 793 if status.dcrcfail() {
784 return Poll::Ready(Err(Error::Crc)); 794 return Poll::Ready(Err(Error::Crc));
785 } else if status.dtimeout() { 795 }
796 if status.dtimeout() {
786 return Poll::Ready(Err(Error::Timeout)); 797 return Poll::Ready(Err(Error::Timeout));
787 } else if status.dataend() { 798 }
799 #[cfg(sdmmc_v1)]
800 if status.stbiterr() {
801 return Poll::Ready(Err(Error::StBitErr));
802 }
803 if status.dataend() {
788 return Poll::Ready(Ok(())); 804 return Poll::Ready(Ok(()));
789 } 805 }
790 Poll::Pending 806 Poll::Pending
@@ -836,6 +852,8 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
836 w.set_dataendc(true); 852 w.set_dataendc(true);
837 w.set_dbckendc(true); 853 w.set_dbckendc(true);
838 w.set_sdioitc(true); 854 w.set_sdioitc(true);
855 #[cfg(sdmmc_v1)]
856 w.set_stbiterrc(true);
839 857
840 #[cfg(sdmmc_v2)] 858 #[cfg(sdmmc_v2)]
841 { 859 {
@@ -873,9 +891,15 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
873 891
874 if status.dcrcfail() { 892 if status.dcrcfail() {
875 return Poll::Ready(Err(Error::Crc)); 893 return Poll::Ready(Err(Error::Crc));
876 } else if status.dtimeout() { 894 }
895 if status.dtimeout() {
877 return Poll::Ready(Err(Error::Timeout)); 896 return Poll::Ready(Err(Error::Timeout));
878 } else if status.dataend() { 897 }
898 #[cfg(sdmmc_v1)]
899 if status.stbiterr() {
900 return Poll::Ready(Err(Error::StBitErr));
901 }
902 if status.dataend() {
879 return Poll::Ready(Ok(())); 903 return Poll::Ready(Ok(()));
880 } 904 }
881 Poll::Pending 905 Poll::Pending
@@ -1156,9 +1180,15 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1156 1180
1157 if status.dcrcfail() { 1181 if status.dcrcfail() {
1158 return Poll::Ready(Err(Error::Crc)); 1182 return Poll::Ready(Err(Error::Crc));
1159 } else if status.dtimeout() { 1183 }
1184 if status.dtimeout() {
1160 return Poll::Ready(Err(Error::Timeout)); 1185 return Poll::Ready(Err(Error::Timeout));
1161 } else if status.dataend() { 1186 }
1187 #[cfg(sdmmc_v1)]
1188 if status.stbiterr() {
1189 return Poll::Ready(Err(Error::StBitErr));
1190 }
1191 if status.dataend() {
1162 return Poll::Ready(Ok(())); 1192 return Poll::Ready(Ok(()));
1163 } 1193 }
1164 Poll::Pending 1194 Poll::Pending
@@ -1207,9 +1237,15 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> {
1207 1237
1208 if status.dcrcfail() { 1238 if status.dcrcfail() {
1209 return Poll::Ready(Err(Error::Crc)); 1239 return Poll::Ready(Err(Error::Crc));
1210 } else if status.dtimeout() { 1240 }
1241 if status.dtimeout() {
1211 return Poll::Ready(Err(Error::Timeout)); 1242 return Poll::Ready(Err(Error::Timeout));
1212 } else if status.dataend() { 1243 }
1244 #[cfg(sdmmc_v1)]
1245 if status.stbiterr() {
1246 return Poll::Ready(Err(Error::StBitErr));
1247 }
1248 if status.dataend() {
1213 return Poll::Ready(Ok(())); 1249 return Poll::Ready(Ok(()));
1214 } 1250 }
1215 Poll::Pending 1251 Poll::Pending
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index e2bc8d7f2..f40bce784 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -323,7 +323,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> {
323 } 323 }
324 324
325 /// Reconfigures it with the supplied config. 325 /// Reconfigures it with the supplied config.
326 pub fn reconfigure(&mut self, config: Config) { 326 pub fn set_config(&mut self, config: Config) {
327 let cpha = config.raw_phase(); 327 let cpha = config.raw_phase();
328 let cpol = config.raw_polarity(); 328 let cpol = config.raw_polarity();
329 329
@@ -646,6 +646,8 @@ impl<'d, T: Instance, Tx, Rx> Drop for Spi<'d, T, Tx, Rx> {
646 self.sck.as_ref().map(|x| x.set_as_disconnected()); 646 self.sck.as_ref().map(|x| x.set_as_disconnected());
647 self.mosi.as_ref().map(|x| x.set_as_disconnected()); 647 self.mosi.as_ref().map(|x| x.set_as_disconnected());
648 self.miso.as_ref().map(|x| x.set_as_disconnected()); 648 self.miso.as_ref().map(|x| x.set_as_disconnected());
649
650 T::disable();
649 } 651 }
650} 652}
651 653
@@ -1060,6 +1062,6 @@ foreach_peripheral!(
1060impl<'d, T: Instance, Tx, Rx> SetConfig for Spi<'d, T, Tx, Rx> { 1062impl<'d, T: Instance, Tx, Rx> SetConfig for Spi<'d, T, Tx, Rx> {
1061 type Config = Config; 1063 type Config = Config;
1062 fn set_config(&mut self, config: &Self::Config) { 1064 fn set_config(&mut self, config: &Self::Config) {
1063 self.reconfigure(*config); 1065 self.set_config(*config);
1064 } 1066 }
1065} 1067}
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index 2622442f4..5b01937f5 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -14,6 +14,8 @@ use stm32_metapac::timer::regs;
14use crate::interrupt::typelevel::Interrupt; 14use crate::interrupt::typelevel::Interrupt;
15use crate::pac::timer::vals; 15use crate::pac::timer::vals;
16use crate::rcc::sealed::RccPeripheral; 16use crate::rcc::sealed::RccPeripheral;
17#[cfg(feature = "low-power")]
18use crate::rtc::Rtc;
17use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance}; 19use crate::timer::sealed::{Basic16bitInstance as BasicInstance, GeneralPurpose16bitInstance as Instance};
18use crate::{interrupt, peripherals}; 20use crate::{interrupt, peripherals};
19 21
@@ -130,12 +132,14 @@ impl AlarmState {
130 } 132 }
131} 133}
132 134
133struct RtcDriver { 135pub(crate) struct RtcDriver {
134 /// Number of 2^15 periods elapsed since boot. 136 /// Number of 2^15 periods elapsed since boot.
135 period: AtomicU32, 137 period: AtomicU32,
136 alarm_count: AtomicU8, 138 alarm_count: AtomicU8,
137 /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. 139 /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.
138 alarms: Mutex<CriticalSectionRawMutex, [AlarmState; ALARM_COUNT]>, 140 alarms: Mutex<CriticalSectionRawMutex, [AlarmState; ALARM_COUNT]>,
141 #[cfg(feature = "low-power")]
142 rtc: Mutex<CriticalSectionRawMutex, Cell<Option<&'static Rtc>>>,
139} 143}
140 144
141const ALARM_STATE_NEW: AlarmState = AlarmState::new(); 145const ALARM_STATE_NEW: AlarmState = AlarmState::new();
@@ -144,6 +148,8 @@ embassy_time::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver {
144 period: AtomicU32::new(0), 148 period: AtomicU32::new(0),
145 alarm_count: AtomicU8::new(0), 149 alarm_count: AtomicU8::new(0),
146 alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [ALARM_STATE_NEW; ALARM_COUNT]), 150 alarms: Mutex::const_new(CriticalSectionRawMutex::new(), [ALARM_STATE_NEW; ALARM_COUNT]),
151 #[cfg(feature = "low-power")]
152 rtc: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)),
147}); 153});
148 154
149impl RtcDriver { 155impl RtcDriver {
@@ -259,6 +265,127 @@ impl RtcDriver {
259 let f: fn(*mut ()) = unsafe { mem::transmute(alarm.callback.get()) }; 265 let f: fn(*mut ()) = unsafe { mem::transmute(alarm.callback.get()) };
260 f(alarm.ctx.get()); 266 f(alarm.ctx.get());
261 } 267 }
268
269 /*
270 Low-power private functions: all operate within a critical seciton
271 */
272
273 #[cfg(feature = "low-power")]
274 /// Compute the approximate amount of time until the next alarm
275 fn time_until_next_alarm(&self, cs: CriticalSection) -> embassy_time::Duration {
276 let now = self.now() + 32;
277
278 embassy_time::Duration::from_ticks(
279 self.alarms
280 .borrow(cs)
281 .iter()
282 .map(|alarm: &AlarmState| alarm.timestamp.get().saturating_sub(now))
283 .min()
284 .unwrap_or(u64::MAX),
285 )
286 }
287
288 #[cfg(feature = "low-power")]
289 /// Add the given offset to the current time
290 fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) {
291 let offset = offset.as_ticks();
292 let cnt = T::regs_gp16().cnt().read().cnt() as u32;
293 let period = self.period.load(Ordering::SeqCst);
294
295 // Correct the race, if it exists
296 let period = if period & 1 == 1 && cnt < u16::MAX as u32 / 2 {
297 period + 1
298 } else {
299 period
300 };
301
302 // Normalize to the full overflow
303 let period = (period / 2) * 2;
304
305 // Add the offset
306 let period = period + 2 * (offset / u16::MAX as u64) as u32;
307 let cnt = cnt + (offset % u16::MAX as u64) as u32;
308
309 let (cnt, period) = if cnt > u16::MAX as u32 {
310 (cnt - u16::MAX as u32, period + 2)
311 } else {
312 (cnt, period)
313 };
314
315 let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period };
316
317 self.period.store(period, Ordering::SeqCst);
318 T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16));
319
320 // Now, recompute all alarms
321 for i in 0..ALARM_COUNT {
322 let alarm_handle = unsafe { AlarmHandle::new(i as u8) };
323 let alarm = self.get_alarm(cs, alarm_handle);
324
325 self.set_alarm(alarm_handle, alarm.timestamp.get());
326 }
327 }
328
329 #[cfg(feature = "low-power")]
330 /// Stop the wakeup alarm, if enabled, and add the appropriate offset
331 fn stop_wakeup_alarm(&self, cs: CriticalSection) {
332 if let Some(offset) = self.rtc.borrow(cs).get().unwrap().stop_wakeup_alarm(cs) {
333 self.add_time(offset, cs);
334 }
335 }
336
337 /*
338 Low-power public functions: all create a critical section
339 */
340 #[cfg(feature = "low-power")]
341 /// Set the rtc but panic if it's already been set
342 pub(crate) fn set_rtc(&self, rtc: &'static Rtc) {
343 critical_section::with(|cs| assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none()));
344 }
345
346 #[cfg(feature = "low-power")]
347 /// Pause the timer if ready; return err if not
348 pub(crate) fn pause_time(&self) -> Result<(), ()> {
349 critical_section::with(|cs| {
350 /*
351 If the wakeup timer is currently running, then we need to stop it and
352 add the elapsed time to the current time, as this will impact the result
353 of `time_until_next_alarm`.
354 */
355 self.stop_wakeup_alarm(cs);
356
357 let time_until_next_alarm = self.time_until_next_alarm(cs);
358 if time_until_next_alarm < embassy_time::Duration::from_millis(250) {
359 Err(())
360 } else {
361 self.rtc
362 .borrow(cs)
363 .get()
364 .unwrap()
365 .start_wakeup_alarm(time_until_next_alarm, cs);
366
367 T::regs_gp16().cr1().modify(|w| w.set_cen(false));
368
369 Ok(())
370 }
371 })
372 }
373
374 #[cfg(feature = "low-power")]
375 /// Resume the timer with the given offset
376 pub(crate) fn resume_time(&self) {
377 if T::regs_gp16().cr1().read().cen() {
378 // Time isn't currently stopped
379
380 return;
381 }
382
383 critical_section::with(|cs| {
384 self.stop_wakeup_alarm(cs);
385
386 T::regs_gp16().cr1().modify(|w| w.set_cen(true));
387 })
388 }
262} 389}
263 390
264impl Driver for RtcDriver { 391impl Driver for RtcDriver {
@@ -329,6 +456,11 @@ impl Driver for RtcDriver {
329 } 456 }
330} 457}
331 458
459#[cfg(feature = "low-power")]
460pub(crate) fn get_driver() -> &'static RtcDriver {
461 &DRIVER
462}
463
332pub(crate) fn init() { 464pub(crate) fn init() {
333 DRIVER.init() 465 DRIVER.init()
334} 466}
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs
index 4ffb2a289..1d642ed37 100644
--- a/embassy-stm32/src/timer/mod.rs
+++ b/embassy-stm32/src/timer/mod.rs
@@ -1,4 +1,5 @@
1pub mod complementary_pwm; 1pub mod complementary_pwm;
2pub mod qei;
2pub mod simple_pwm; 3pub mod simple_pwm;
3 4
4use stm32_metapac::timer::vals; 5use stm32_metapac::timer::vals;
@@ -14,6 +15,7 @@ pub mod low_level {
14} 15}
15 16
16pub(crate) mod sealed { 17pub(crate) mod sealed {
18
17 use super::*; 19 use super::*;
18 pub trait Basic16bitInstance: RccPeripheral { 20 pub trait Basic16bitInstance: RccPeripheral {
19 type Interrupt: interrupt::typelevel::Interrupt; 21 type Interrupt: interrupt::typelevel::Interrupt;
@@ -31,10 +33,16 @@ pub(crate) mod sealed {
31 fn clear_update_interrupt(&mut self) -> bool; 33 fn clear_update_interrupt(&mut self) -> bool;
32 34
33 fn enable_update_interrupt(&mut self, enable: bool); 35 fn enable_update_interrupt(&mut self, enable: bool);
36
37 fn set_autoreload_preload(&mut self, enable: vals::Arpe);
34 } 38 }
35 39
36 pub trait GeneralPurpose16bitInstance: Basic16bitInstance { 40 pub trait GeneralPurpose16bitInstance: Basic16bitInstance {
37 fn regs_gp16() -> crate::pac::timer::TimGp16; 41 fn regs_gp16() -> crate::pac::timer::TimGp16;
42
43 fn set_count_direction(&mut self, direction: vals::Dir);
44
45 fn set_clock_division(&mut self, ckd: vals::Ckd);
38 } 46 }
39 47
40 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { 48 pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance {
@@ -48,6 +56,18 @@ pub(crate) mod sealed {
48 } 56 }
49 57
50 pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance { 58 pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance {
59 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf);
60
61 fn clear_input_interrupt(&mut self, channel: Channel);
62
63 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool);
64
65 fn set_input_capture_prescaler(&mut self, channel: Channel, val: u8);
66
67 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection);
68
69 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode);
70
51 /// Global output enable. Does not do anything on non-advanced timers. 71 /// Global output enable. Does not do anything on non-advanced timers.
52 fn enable_outputs(&mut self, enable: bool); 72 fn enable_outputs(&mut self, enable: bool);
53 73
@@ -59,6 +79,8 @@ pub(crate) mod sealed {
59 79
60 fn set_compare_value(&mut self, channel: Channel, value: u16); 80 fn set_compare_value(&mut self, channel: Channel, value: u16);
61 81
82 fn get_capture_value(&mut self, channel: Channel) -> u16;
83
62 fn get_max_compare_value(&self) -> u16; 84 fn get_max_compare_value(&self) -> u16;
63 } 85 }
64 86
@@ -73,6 +95,18 @@ pub(crate) mod sealed {
73 } 95 }
74 96
75 pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance { 97 pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance {
98 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf);
99
100 fn clear_input_interrupt(&mut self, channel: Channel);
101
102 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool);
103
104 fn set_input_capture_prescaler(&mut self, channel: Channel, val: u8);
105
106 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection);
107
108 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode);
109
76 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); 110 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode);
77 111
78 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity); 112 fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity);
@@ -81,6 +115,8 @@ pub(crate) mod sealed {
81 115
82 fn set_compare_value(&mut self, channel: Channel, value: u32); 116 fn set_compare_value(&mut self, channel: Channel, value: u32);
83 117
118 fn get_capture_value(&mut self, channel: Channel) -> u32;
119
84 fn get_max_compare_value(&self) -> u32; 120 fn get_max_compare_value(&self) -> u32;
85 } 121 }
86} 122}
@@ -105,6 +141,30 @@ impl Channel {
105} 141}
106 142
107#[derive(Clone, Copy)] 143#[derive(Clone, Copy)]
144pub enum InputCaptureMode {
145 Rising,
146 Falling,
147 BothEdges,
148}
149
150#[derive(Clone, Copy)]
151pub enum InputTISelection {
152 Normal,
153 Alternate,
154 TRC,
155}
156
157impl From<InputTISelection> for stm32_metapac::timer::vals::CcmrInputCcs {
158 fn from(tisel: InputTISelection) -> Self {
159 match tisel {
160 InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4,
161 InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3,
162 InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC,
163 }
164 }
165}
166
167#[derive(Clone, Copy)]
108pub enum OutputCompareMode { 168pub enum OutputCompareMode {
109 Frozen, 169 Frozen,
110 ActiveOnMatch, 170 ActiveOnMatch,
@@ -211,6 +271,7 @@ macro_rules! impl_basic_16bit_timer {
211 use core::convert::TryInto; 271 use core::convert::TryInto;
212 let f = frequency.0; 272 let f = frequency.0;
213 let timer_f = Self::frequency().0; 273 let timer_f = Self::frequency().0;
274 assert!(f > 0);
214 let pclk_ticks_per_timer_period = timer_f / f; 275 let pclk_ticks_per_timer_period = timer_f / f;
215 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); 276 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into());
216 let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); 277 let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into());
@@ -240,6 +301,10 @@ macro_rules! impl_basic_16bit_timer {
240 fn enable_update_interrupt(&mut self, enable: bool) { 301 fn enable_update_interrupt(&mut self, enable: bool) {
241 Self::regs().dier().write(|r| r.set_uie(enable)); 302 Self::regs().dier().write(|r| r.set_uie(enable));
242 } 303 }
304
305 fn set_autoreload_preload(&mut self, enable: vals::Arpe) {
306 Self::regs().cr1().modify(|r| r.set_arpe(enable));
307 }
243 } 308 }
244 }; 309 };
245} 310}
@@ -255,6 +320,7 @@ macro_rules! impl_32bit_timer {
255 fn set_frequency(&mut self, frequency: Hertz) { 320 fn set_frequency(&mut self, frequency: Hertz) {
256 use core::convert::TryInto; 321 use core::convert::TryInto;
257 let f = frequency.0; 322 let f = frequency.0;
323 assert!(f > 0);
258 let timer_f = Self::frequency().0; 324 let timer_f = Self::frequency().0;
259 let pclk_ticks_per_timer_period = (timer_f / f) as u64; 325 let pclk_ticks_per_timer_period = (timer_f / f) as u64;
260 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); 326 let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into());
@@ -276,6 +342,59 @@ macro_rules! impl_32bit_timer {
276macro_rules! impl_compare_capable_16bit { 342macro_rules! impl_compare_capable_16bit {
277 ($inst:ident) => { 343 ($inst:ident) => {
278 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 344 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
345 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
346 use sealed::GeneralPurpose16bitInstance;
347 let raw_channel = channel.raw();
348 Self::regs_gp16()
349 .ccmr_input(raw_channel / 2)
350 .modify(|r| r.set_icf(raw_channel % 2, icf));
351 }
352
353 fn clear_input_interrupt(&mut self, channel: Channel) {
354 use sealed::GeneralPurpose16bitInstance;
355 Self::regs_gp16()
356 .sr()
357 .modify(|r| r.set_ccif(channel.raw(), false));
358 }
359
360 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
361 use sealed::GeneralPurpose16bitInstance;
362 Self::regs_gp16()
363 .dier()
364 .modify(|r| r.set_ccie(channel.raw(), enable));
365 }
366 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
367 use sealed::GeneralPurpose16bitInstance;
368 let raw_channel = channel.raw();
369 Self::regs_gp16()
370 .ccmr_input(raw_channel / 2)
371 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
372 }
373
374 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
375 use sealed::GeneralPurpose16bitInstance;
376 let raw_channel = channel.raw();
377 Self::regs_gp16()
378 .ccmr_input(raw_channel / 2)
379 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
380 }
381 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
382 use sealed::GeneralPurpose16bitInstance;
383 Self::regs_gp16().ccer().modify(|r| match mode {
384 InputCaptureMode::Rising => {
385 r.set_ccnp(channel.raw(), false);
386 r.set_ccp(channel.raw(), false);
387 }
388 InputCaptureMode::Falling => {
389 r.set_ccnp(channel.raw(), false);
390 r.set_ccp(channel.raw(), true);
391 }
392 InputCaptureMode::BothEdges => {
393 r.set_ccnp(channel.raw(), true);
394 r.set_ccp(channel.raw(), true);
395 }
396 });
397 }
279 fn enable_outputs(&mut self, _enable: bool) {} 398 fn enable_outputs(&mut self, _enable: bool) {}
280 399
281 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { 400 fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) {
@@ -305,6 +424,11 @@ macro_rules! impl_compare_capable_16bit {
305 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); 424 Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value));
306 } 425 }
307 426
427 fn get_capture_value(&mut self, channel: Channel) -> u16 {
428 use sealed::GeneralPurpose16bitInstance;
429 Self::regs_gp16().ccr(channel.raw()).read().ccr()
430 }
431
308 fn get_max_compare_value(&self) -> u16 { 432 fn get_max_compare_value(&self) -> u16 {
309 use sealed::GeneralPurpose16bitInstance; 433 use sealed::GeneralPurpose16bitInstance;
310 Self::regs_gp16().arr().read().arr() 434 Self::regs_gp16().arr().read().arr()
@@ -329,6 +453,14 @@ foreach_interrupt! {
329 fn regs_gp16() -> crate::pac::timer::TimGp16 { 453 fn regs_gp16() -> crate::pac::timer::TimGp16 {
330 crate::pac::$inst 454 crate::pac::$inst
331 } 455 }
456
457 fn set_count_direction(&mut self, direction: vals::Dir) {
458 Self::regs_gp16().cr1().modify(|r| r.set_dir(direction));
459 }
460
461 fn set_clock_division(&mut self, ckd: vals::Ckd) {
462 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
463 }
332 } 464 }
333 }; 465 };
334 466
@@ -343,6 +475,59 @@ foreach_interrupt! {
343 impl GeneralPurpose32bitInstance for crate::peripherals::$inst {} 475 impl GeneralPurpose32bitInstance for crate::peripherals::$inst {}
344 476
345 impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { 477 impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {
478 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
479 use sealed::GeneralPurpose32bitInstance;
480 let raw_channel = channel.raw();
481 Self::regs_gp32()
482 .ccmr_input(raw_channel / 2)
483 .modify(|r| r.set_icf(raw_channel % 2, icf));
484 }
485
486 fn clear_input_interrupt(&mut self, channel: Channel) {
487 use sealed::GeneralPurpose32bitInstance;
488 Self::regs_gp32()
489 .sr()
490 .modify(|r| r.set_ccif(channel.raw(), false));
491 }
492 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
493 use sealed::GeneralPurpose32bitInstance;
494 Self::regs_gp32()
495 .dier()
496 .modify(|r| r.set_ccie(channel.raw(), enable));
497 }
498 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
499 use crate::timer::sealed::GeneralPurpose32bitInstance;
500 let raw_channel = channel.raw();
501 Self::regs_gp32()
502 .ccmr_input(raw_channel / 2)
503 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
504 }
505
506 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
507 use crate::timer::sealed::GeneralPurpose32bitInstance;
508 let raw_channel = channel.raw();
509 Self::regs_gp32()
510 .ccmr_input(raw_channel / 2)
511 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
512 }
513
514 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
515 use crate::timer::sealed::GeneralPurpose32bitInstance;
516 Self::regs_gp32().ccer().modify(|r| match mode {
517 InputCaptureMode::Rising => {
518 r.set_ccnp(channel.raw(), false);
519 r.set_ccp(channel.raw(), false);
520 }
521 InputCaptureMode::Falling => {
522 r.set_ccnp(channel.raw(), false);
523 r.set_ccp(channel.raw(), true);
524 }
525 InputCaptureMode::BothEdges => {
526 r.set_ccnp(channel.raw(), true);
527 r.set_ccp(channel.raw(), true);
528 }
529 });
530 }
346 fn set_output_compare_mode( 531 fn set_output_compare_mode(
347 &mut self, 532 &mut self,
348 channel: Channel, 533 channel: Channel,
@@ -370,6 +555,11 @@ foreach_interrupt! {
370 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); 555 Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value));
371 } 556 }
372 557
558 fn get_capture_value(&mut self, channel: Channel) -> u32 {
559 use crate::timer::sealed::GeneralPurpose32bitInstance;
560 Self::regs_gp32().ccr(channel.raw()).read().ccr()
561 }
562
373 fn get_max_compare_value(&self) -> u32 { 563 fn get_max_compare_value(&self) -> u32 {
374 use crate::timer::sealed::GeneralPurpose32bitInstance; 564 use crate::timer::sealed::GeneralPurpose32bitInstance;
375 Self::regs_gp32().arr().read().arr() as u32 565 Self::regs_gp32().arr().read().arr() as u32
@@ -380,6 +570,14 @@ foreach_interrupt! {
380 fn regs_gp16() -> crate::pac::timer::TimGp16 { 570 fn regs_gp16() -> crate::pac::timer::TimGp16 {
381 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } 571 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
382 } 572 }
573
574 fn set_count_direction(&mut self, direction: vals::Dir) {
575 Self::regs_gp16().cr1().modify(|r| r.set_dir(direction));
576 }
577
578 fn set_clock_division(&mut self, ckd: vals::Ckd) {
579 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
580 }
383 } 581 }
384 }; 582 };
385 583
@@ -396,6 +594,14 @@ foreach_interrupt! {
396 fn regs_gp16() -> crate::pac::timer::TimGp16 { 594 fn regs_gp16() -> crate::pac::timer::TimGp16 {
397 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } 595 unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) }
398 } 596 }
597
598 fn set_count_direction(&mut self, direction: vals::Dir) {
599 Self::regs_gp16().cr1().modify(|r| r.set_dir(direction));
600 }
601
602 fn set_clock_division(&mut self, ckd: vals::Ckd) {
603 Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd));
604 }
399 } 605 }
400 606
401 impl sealed::AdvancedControlInstance for crate::peripherals::$inst { 607 impl sealed::AdvancedControlInstance for crate::peripherals::$inst {
@@ -405,6 +611,57 @@ foreach_interrupt! {
405 } 611 }
406 612
407 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { 613 impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {
614 fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) {
615 use crate::timer::sealed::AdvancedControlInstance;
616 let raw_channel = channel.raw();
617 Self::regs_advanced()
618 .ccmr_input(raw_channel / 2)
619 .modify(|r| r.set_icf(raw_channel % 2, icf));
620 }
621
622 fn clear_input_interrupt(&mut self, channel: Channel) {
623 use crate::timer::sealed::AdvancedControlInstance;
624 Self::regs_advanced()
625 .sr()
626 .modify(|r| r.set_ccif(channel.raw(), false));
627 }
628 fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) {
629 use crate::timer::sealed::AdvancedControlInstance;
630 Self::regs_advanced()
631 .dier()
632 .modify(|r| r.set_ccie(channel.raw(), enable));
633 }
634 fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) {
635 use crate::timer::sealed::AdvancedControlInstance;
636 let raw_channel = channel.raw();
637 Self::regs_advanced()
638 .ccmr_input(raw_channel / 2)
639 .modify(|r| r.set_icpsc(raw_channel % 2, factor));
640 }
641 fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) {
642 use crate::timer::sealed::AdvancedControlInstance;
643 let raw_channel = channel.raw();
644 Self::regs_advanced()
645 .ccmr_input(raw_channel / 2)
646 .modify(|r| r.set_ccs(raw_channel % 2, tisel.into()));
647 }
648 fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) {
649 use crate::timer::sealed::AdvancedControlInstance;
650 Self::regs_advanced().ccer().modify(|r| match mode {
651 InputCaptureMode::Rising => {
652 r.set_ccnp(channel.raw(), false);
653 r.set_ccp(channel.raw(), false);
654 }
655 InputCaptureMode::Falling => {
656 r.set_ccnp(channel.raw(), false);
657 r.set_ccp(channel.raw(), true);
658 }
659 InputCaptureMode::BothEdges => {
660 r.set_ccnp(channel.raw(), true);
661 r.set_ccp(channel.raw(), true);
662 }
663 });
664 }
408 fn enable_outputs(&mut self, enable: bool) { 665 fn enable_outputs(&mut self, enable: bool) {
409 use crate::timer::sealed::AdvancedControlInstance; 666 use crate::timer::sealed::AdvancedControlInstance;
410 let r = Self::regs_advanced(); 667 let r = Self::regs_advanced();
@@ -437,6 +694,11 @@ foreach_interrupt! {
437 .modify(|w| w.set_cce(channel.raw(), enable)); 694 .modify(|w| w.set_cce(channel.raw(), enable));
438 } 695 }
439 696
697 fn get_capture_value(&mut self, channel: Channel) -> u16 {
698 use crate::timer::sealed::AdvancedControlInstance;
699 Self::regs_advanced().ccr(channel.raw()).read().ccr()
700 }
701
440 fn set_compare_value(&mut self, channel: Channel, value: u16) { 702 fn set_compare_value(&mut self, channel: Channel, value: u16) {
441 use crate::timer::sealed::AdvancedControlInstance; 703 use crate::timer::sealed::AdvancedControlInstance;
442 Self::regs_advanced() 704 Self::regs_advanced()
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs
new file mode 100644
index 000000000..15f2c3a79
--- /dev/null
+++ b/embassy-stm32/src/timer/qei.rs
@@ -0,0 +1,96 @@
1use core::marker::PhantomData;
2
3use embassy_hal_internal::{into_ref, PeripheralRef};
4
5use super::*;
6use crate::gpio::sealed::AFType;
7use crate::gpio::AnyPin;
8use crate::Peripheral;
9
10pub enum Direction {
11 Upcounting,
12 Downcounting,
13}
14
15pub struct Ch1;
16pub struct Ch2;
17
18pub struct QeiPin<'d, Perip, Channel> {
19 _pin: PeripheralRef<'d, AnyPin>,
20 phantom: PhantomData<(Perip, Channel)>,
21}
22
23macro_rules! channel_impl {
24 ($new_chx:ident, $channel:ident, $pin_trait:ident) => {
25 impl<'d, Perip: CaptureCompare16bitInstance> QeiPin<'d, Perip, $channel> {
26 pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<Perip>> + 'd) -> Self {
27 into_ref!(pin);
28 critical_section::with(|_| {
29 pin.set_low();
30 pin.set_as_af(pin.af_num(), AFType::Input);
31 #[cfg(gpio_v2)]
32 pin.set_speed(crate::gpio::Speed::VeryHigh);
33 });
34 QeiPin {
35 _pin: pin.map_into(),
36 phantom: PhantomData,
37 }
38 }
39 }
40 };
41}
42
43channel_impl!(new_ch1, Ch1, Channel1Pin);
44channel_impl!(new_ch2, Ch2, Channel2Pin);
45
46pub struct Qei<'d, T> {
47 _inner: PeripheralRef<'d, T>,
48}
49
50impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> {
51 pub fn new(tim: impl Peripheral<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
52 Self::new_inner(tim)
53 }
54
55 fn new_inner(tim: impl Peripheral<P = T> + 'd) -> Self {
56 into_ref!(tim);
57
58 T::enable();
59 <T as crate::rcc::sealed::RccPeripheral>::reset();
60
61 // Configure TxC1 and TxC2 as captures
62 T::regs_gp16().ccmr_input(0).modify(|w| {
63 w.set_ccs(0, vals::CcmrInputCcs::TI4);
64 w.set_ccs(1, vals::CcmrInputCcs::TI4);
65 });
66
67 // enable and configure to capture on rising edge
68 T::regs_gp16().ccer().modify(|w| {
69 w.set_cce(0, true);
70 w.set_cce(1, true);
71
72 w.set_ccp(0, false);
73 w.set_ccp(1, false);
74 });
75
76 T::regs_gp16().smcr().modify(|w| {
77 w.set_sms(vals::Sms::ENCODER_MODE_3);
78 });
79
80 T::regs_gp16().arr().modify(|w| w.set_arr(u16::MAX));
81 T::regs_gp16().cr1().modify(|w| w.set_cen(true));
82
83 Self { _inner: tim }
84 }
85
86 pub fn read_direction(&self) -> Direction {
87 match T::regs_gp16().cr1().read().dir() {
88 vals::Dir::DOWN => Direction::Downcounting,
89 vals::Dir::UP => Direction::Upcounting,
90 }
91 }
92
93 pub fn count(&self) -> u16 {
94 T::regs_gp16().cnt().read().cnt()
95 }
96}
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 596d40bf9..e2d6e42af 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -114,6 +114,30 @@ pub struct BufferedUartRx<'d, T: BasicInstance> {
114 phantom: PhantomData<&'d mut T>, 114 phantom: PhantomData<&'d mut T>,
115} 115}
116 116
117impl<'d, T: BasicInstance> SetConfig for BufferedUart<'d, T> {
118 type Config = Config;
119
120 fn set_config(&mut self, config: &Self::Config) {
121 unwrap!(self.set_config(config))
122 }
123}
124
125impl<'d, T: BasicInstance> SetConfig for BufferedUartRx<'d, T> {
126 type Config = Config;
127
128 fn set_config(&mut self, config: &Self::Config) {
129 unwrap!(self.set_config(config))
130 }
131}
132
133impl<'d, T: BasicInstance> SetConfig for BufferedUartTx<'d, T> {
134 type Config = Config;
135
136 fn set_config(&mut self, config: &Self::Config) {
137 unwrap!(self.set_config(config))
138 }
139}
140
117impl<'d, T: BasicInstance> BufferedUart<'d, T> { 141impl<'d, T: BasicInstance> BufferedUart<'d, T> {
118 pub fn new( 142 pub fn new(
119 peri: impl Peripheral<P = T> + 'd, 143 peri: impl Peripheral<P = T> + 'd,
@@ -123,7 +147,9 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
123 tx_buffer: &'d mut [u8], 147 tx_buffer: &'d mut [u8],
124 rx_buffer: &'d mut [u8], 148 rx_buffer: &'d mut [u8],
125 config: Config, 149 config: Config,
126 ) -> BufferedUart<'d, T> { 150 ) -> Result<Self, ConfigError> {
151 // UartRx and UartTx have one refcount ea.
152 T::enable();
127 T::enable(); 153 T::enable();
128 T::reset(); 154 T::reset();
129 155
@@ -140,9 +166,11 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
140 tx_buffer: &'d mut [u8], 166 tx_buffer: &'d mut [u8],
141 rx_buffer: &'d mut [u8], 167 rx_buffer: &'d mut [u8],
142 config: Config, 168 config: Config,
143 ) -> BufferedUart<'d, T> { 169 ) -> Result<Self, ConfigError> {
144 into_ref!(cts, rts); 170 into_ref!(cts, rts);
145 171
172 // UartRx and UartTx have one refcount ea.
173 T::enable();
146 T::enable(); 174 T::enable();
147 T::reset(); 175 T::reset();
148 176
@@ -166,9 +194,11 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
166 tx_buffer: &'d mut [u8], 194 tx_buffer: &'d mut [u8],
167 rx_buffer: &'d mut [u8], 195 rx_buffer: &'d mut [u8],
168 config: Config, 196 config: Config,
169 ) -> BufferedUart<'d, T> { 197 ) -> Result<Self, ConfigError> {
170 into_ref!(de); 198 into_ref!(de);
171 199
200 // UartRx and UartTx have one refcount ea.
201 T::enable();
172 T::enable(); 202 T::enable();
173 T::reset(); 203 T::reset();
174 204
@@ -187,7 +217,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
187 tx_buffer: &'d mut [u8], 217 tx_buffer: &'d mut [u8],
188 rx_buffer: &'d mut [u8], 218 rx_buffer: &'d mut [u8],
189 config: Config, 219 config: Config,
190 ) -> BufferedUart<'d, T> { 220 ) -> Result<Self, ConfigError> {
191 into_ref!(_peri, rx, tx); 221 into_ref!(_peri, rx, tx);
192 222
193 let state = T::buffered_state(); 223 let state = T::buffered_state();
@@ -200,7 +230,7 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
200 rx.set_as_af(rx.af_num(), AFType::Input); 230 rx.set_as_af(rx.af_num(), AFType::Input);
201 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 231 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
202 232
203 configure(r, &config, T::frequency(), T::KIND, true, true); 233 configure(r, &config, T::frequency(), T::KIND, true, true)?;
204 234
205 r.cr1().modify(|w| { 235 r.cr1().modify(|w| {
206 #[cfg(lpuart_v2)] 236 #[cfg(lpuart_v2)]
@@ -213,15 +243,19 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
213 T::Interrupt::unpend(); 243 T::Interrupt::unpend();
214 unsafe { T::Interrupt::enable() }; 244 unsafe { T::Interrupt::enable() };
215 245
216 Self { 246 Ok(Self {
217 rx: BufferedUartRx { phantom: PhantomData }, 247 rx: BufferedUartRx { phantom: PhantomData },
218 tx: BufferedUartTx { phantom: PhantomData }, 248 tx: BufferedUartTx { phantom: PhantomData },
219 } 249 })
220 } 250 }
221 251
222 pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) { 252 pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
223 (self.tx, self.rx) 253 (self.tx, self.rx)
224 } 254 }
255
256 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
257 reconfigure::<T>(config)
258 }
225} 259}
226 260
227impl<'d, T: BasicInstance> BufferedUartRx<'d, T> { 261impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
@@ -298,6 +332,10 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
298 T::Interrupt::pend(); 332 T::Interrupt::pend();
299 } 333 }
300 } 334 }
335
336 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
337 reconfigure::<T>(config)
338 }
301} 339}
302 340
303impl<'d, T: BasicInstance> BufferedUartTx<'d, T> { 341impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
@@ -368,6 +406,10 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
368 } 406 }
369 } 407 }
370 } 408 }
409
410 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
411 reconfigure::<T>(config)
412 }
371} 413}
372 414
373impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> { 415impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> {
@@ -382,6 +424,8 @@ impl<'d, T: BasicInstance> Drop for BufferedUartRx<'d, T> {
382 T::Interrupt::disable(); 424 T::Interrupt::disable();
383 } 425 }
384 } 426 }
427
428 T::disable();
385 } 429 }
386} 430}
387 431
@@ -397,12 +441,8 @@ impl<'d, T: BasicInstance> Drop for BufferedUartTx<'d, T> {
397 T::Interrupt::disable(); 441 T::Interrupt::disable();
398 } 442 }
399 } 443 }
400 }
401}
402 444
403impl embedded_io_async::Error for Error { 445 T::disable();
404 fn kind(&self) -> embedded_io_async::ErrorKind {
405 embedded_io_async::ErrorKind::Other
406 } 446 }
407} 447}
408 448
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 255ddfd4b..9835f1ace 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -5,6 +5,7 @@ use core::marker::PhantomData;
5use core::sync::atomic::{compiler_fence, Ordering}; 5use core::sync::atomic::{compiler_fence, Ordering};
6use core::task::Poll; 6use core::task::Poll;
7 7
8use embassy_embedded_hal::SetConfig;
8use embassy_hal_internal::drop::OnDrop; 9use embassy_hal_internal::drop::OnDrop;
9use embassy_hal_internal::{into_ref, PeripheralRef}; 10use embassy_hal_internal::{into_ref, PeripheralRef};
10use futures::future::{select, Either}; 11use futures::future::{select, Either};
@@ -12,11 +13,10 @@ use futures::future::{select, Either};
12use crate::dma::{NoDma, Transfer}; 13use crate::dma::{NoDma, Transfer};
13use crate::gpio::sealed::AFType; 14use crate::gpio::sealed::AFType;
14use crate::interrupt::typelevel::Interrupt; 15use crate::interrupt::typelevel::Interrupt;
15#[cfg(not(any(usart_v1, usart_v2)))]
16#[allow(unused_imports)] 16#[allow(unused_imports)]
17#[cfg(not(any(usart_v1, usart_v2)))]
17use crate::pac::usart::regs::Isr as Sr; 18use crate::pac::usart::regs::Isr as Sr;
18#[cfg(any(usart_v1, usart_v2))] 19#[cfg(any(usart_v1, usart_v2))]
19#[allow(unused_imports)]
20use crate::pac::usart::regs::Sr; 20use crate::pac::usart::regs::Sr;
21#[cfg(not(any(usart_v1, usart_v2)))] 21#[cfg(not(any(usart_v1, usart_v2)))]
22use crate::pac::usart::Lpuart as Regs; 22use crate::pac::usart::Lpuart as Regs;
@@ -75,12 +75,14 @@ impl<T: BasicInstance> interrupt::typelevel::Handler<T::Interrupt> for Interrupt
75} 75}
76 76
77#[derive(Clone, Copy, PartialEq, Eq, Debug)] 77#[derive(Clone, Copy, PartialEq, Eq, Debug)]
78#[cfg_attr(feature = "defmt", derive(defmt::Format))]
78pub enum DataBits { 79pub enum DataBits {
79 DataBits8, 80 DataBits8,
80 DataBits9, 81 DataBits9,
81} 82}
82 83
83#[derive(Clone, Copy, PartialEq, Eq, Debug)] 84#[derive(Clone, Copy, PartialEq, Eq, Debug)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))]
84pub enum Parity { 86pub enum Parity {
85 ParityNone, 87 ParityNone,
86 ParityEven, 88 ParityEven,
@@ -88,6 +90,7 @@ pub enum Parity {
88} 90}
89 91
90#[derive(Clone, Copy, PartialEq, Eq, Debug)] 92#[derive(Clone, Copy, PartialEq, Eq, Debug)]
93#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91pub enum StopBits { 94pub enum StopBits {
92 #[doc = "1 stop bit"] 95 #[doc = "1 stop bit"]
93 STOP1, 96 STOP1,
@@ -101,6 +104,14 @@ pub enum StopBits {
101 104
102#[non_exhaustive] 105#[non_exhaustive]
103#[derive(Clone, Copy, PartialEq, Eq, Debug)] 106#[derive(Clone, Copy, PartialEq, Eq, Debug)]
107#[cfg_attr(feature = "defmt", derive(defmt::Format))]
108pub enum ConfigError {
109 BaudrateTooLow,
110 BaudrateTooHigh,
111}
112
113#[non_exhaustive]
114#[derive(Clone, Copy, PartialEq, Eq, Debug)]
104pub struct Config { 115pub struct Config {
105 pub baudrate: u32, 116 pub baudrate: u32,
106 pub data_bits: DataBits, 117 pub data_bits: DataBits,
@@ -168,11 +179,28 @@ pub struct Uart<'d, T: BasicInstance, TxDma = NoDma, RxDma = NoDma> {
168 rx: UartRx<'d, T, RxDma>, 179 rx: UartRx<'d, T, RxDma>,
169} 180}
170 181
182impl<'d, T: BasicInstance, TxDma, RxDma> SetConfig for Uart<'d, T, TxDma, RxDma> {
183 type Config = Config;
184
185 fn set_config(&mut self, config: &Self::Config) {
186 unwrap!(self.tx.set_config(config));
187 unwrap!(self.rx.set_config(config));
188 }
189}
190
171pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> { 191pub struct UartTx<'d, T: BasicInstance, TxDma = NoDma> {
172 phantom: PhantomData<&'d mut T>, 192 phantom: PhantomData<&'d mut T>,
173 tx_dma: PeripheralRef<'d, TxDma>, 193 tx_dma: PeripheralRef<'d, TxDma>,
174} 194}
175 195
196impl<'d, T: BasicInstance, TxDma> SetConfig for UartTx<'d, T, TxDma> {
197 type Config = Config;
198
199 fn set_config(&mut self, config: &Self::Config) {
200 unwrap!(self.set_config(config));
201 }
202}
203
176pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> { 204pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
177 _peri: PeripheralRef<'d, T>, 205 _peri: PeripheralRef<'d, T>,
178 rx_dma: PeripheralRef<'d, RxDma>, 206 rx_dma: PeripheralRef<'d, RxDma>,
@@ -181,6 +209,14 @@ pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
181 buffered_sr: stm32_metapac::usart::regs::Sr, 209 buffered_sr: stm32_metapac::usart::regs::Sr,
182} 210}
183 211
212impl<'d, T: BasicInstance, RxDma> SetConfig for UartRx<'d, T, RxDma> {
213 type Config = Config;
214
215 fn set_config(&mut self, config: &Self::Config) {
216 unwrap!(self.set_config(config));
217 }
218}
219
184impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { 220impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
185 /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power. 221 /// Useful if you only want Uart Tx. It saves 1 pin and consumes a little less power.
186 pub fn new( 222 pub fn new(
@@ -188,7 +224,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
188 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 224 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
189 tx_dma: impl Peripheral<P = TxDma> + 'd, 225 tx_dma: impl Peripheral<P = TxDma> + 'd,
190 config: Config, 226 config: Config,
191 ) -> Self { 227 ) -> Result<Self, ConfigError> {
192 T::enable(); 228 T::enable();
193 T::reset(); 229 T::reset();
194 230
@@ -201,7 +237,7 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
201 cts: impl Peripheral<P = impl CtsPin<T>> + 'd, 237 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
202 tx_dma: impl Peripheral<P = TxDma> + 'd, 238 tx_dma: impl Peripheral<P = TxDma> + 'd,
203 config: Config, 239 config: Config,
204 ) -> Self { 240 ) -> Result<Self, ConfigError> {
205 into_ref!(cts); 241 into_ref!(cts);
206 242
207 T::enable(); 243 T::enable();
@@ -219,22 +255,26 @@ impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
219 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 255 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
220 tx_dma: impl Peripheral<P = TxDma> + 'd, 256 tx_dma: impl Peripheral<P = TxDma> + 'd,
221 config: Config, 257 config: Config,
222 ) -> Self { 258 ) -> Result<Self, ConfigError> {
223 into_ref!(_peri, tx, tx_dma); 259 into_ref!(_peri, tx, tx_dma);
224 260
225 let r = T::regs(); 261 let r = T::regs();
226 262
227 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 263 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
228 264
229 configure(r, &config, T::frequency(), T::KIND, false, true); 265 configure(r, &config, T::frequency(), T::KIND, false, true)?;
230 266
231 // create state once! 267 // create state once!
232 let _s = T::state(); 268 let _s = T::state();
233 269
234 Self { 270 Ok(Self {
235 tx_dma, 271 tx_dma,
236 phantom: PhantomData, 272 phantom: PhantomData,
237 } 273 })
274 }
275
276 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
277 reconfigure::<T>(config)
238 } 278 }
239 279
240 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> 280 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
@@ -277,7 +317,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
277 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 317 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
278 rx_dma: impl Peripheral<P = RxDma> + 'd, 318 rx_dma: impl Peripheral<P = RxDma> + 'd,
279 config: Config, 319 config: Config,
280 ) -> Self { 320 ) -> Result<Self, ConfigError> {
281 T::enable(); 321 T::enable();
282 T::reset(); 322 T::reset();
283 323
@@ -291,7 +331,7 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
291 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 331 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
292 rx_dma: impl Peripheral<P = RxDma> + 'd, 332 rx_dma: impl Peripheral<P = RxDma> + 'd,
293 config: Config, 333 config: Config,
294 ) -> Self { 334 ) -> Result<Self, ConfigError> {
295 into_ref!(rts); 335 into_ref!(rts);
296 336
297 T::enable(); 337 T::enable();
@@ -310,14 +350,14 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
310 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 350 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
311 rx_dma: impl Peripheral<P = RxDma> + 'd, 351 rx_dma: impl Peripheral<P = RxDma> + 'd,
312 config: Config, 352 config: Config,
313 ) -> Self { 353 ) -> Result<Self, ConfigError> {
314 into_ref!(peri, rx, rx_dma); 354 into_ref!(peri, rx, rx_dma);
315 355
316 let r = T::regs(); 356 let r = T::regs();
317 357
318 rx.set_as_af(rx.af_num(), AFType::Input); 358 rx.set_as_af(rx.af_num(), AFType::Input);
319 359
320 configure(r, &config, T::frequency(), T::KIND, true, false); 360 configure(r, &config, T::frequency(), T::KIND, true, false)?;
321 361
322 T::Interrupt::unpend(); 362 T::Interrupt::unpend();
323 unsafe { T::Interrupt::enable() }; 363 unsafe { T::Interrupt::enable() };
@@ -325,13 +365,17 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
325 // create state once! 365 // create state once!
326 let _s = T::state(); 366 let _s = T::state();
327 367
328 Self { 368 Ok(Self {
329 _peri: peri, 369 _peri: peri,
330 rx_dma, 370 rx_dma,
331 detect_previous_overrun: config.detect_previous_overrun, 371 detect_previous_overrun: config.detect_previous_overrun,
332 #[cfg(any(usart_v1, usart_v2))] 372 #[cfg(any(usart_v1, usart_v2))]
333 buffered_sr: stm32_metapac::usart::regs::Sr(0), 373 buffered_sr: stm32_metapac::usart::regs::Sr(0),
334 } 374 })
375 }
376
377 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
378 reconfigure::<T>(config)
335 } 379 }
336 380
337 #[cfg(any(usart_v1, usart_v2))] 381 #[cfg(any(usart_v1, usart_v2))]
@@ -545,6 +589,13 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
545 unsafe { rdr(r).read_volatile() }; 589 unsafe { rdr(r).read_volatile() };
546 clear_interrupt_flags(r, sr); 590 clear_interrupt_flags(r, sr);
547 591
592 if enable_idle_line_detection {
593 // enable idle interrupt
594 r.cr1().modify(|w| {
595 w.set_idleie(true);
596 });
597 }
598
548 compiler_fence(Ordering::SeqCst); 599 compiler_fence(Ordering::SeqCst);
549 600
550 let has_errors = sr.pe() || sr.fe() || sr.ne() || sr.ore(); 601 let has_errors = sr.pe() || sr.fe() || sr.ne() || sr.ore();
@@ -618,6 +669,18 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
618 } 669 }
619} 670}
620 671
672impl<'d, T: BasicInstance, TxDma> Drop for UartTx<'d, T, TxDma> {
673 fn drop(&mut self) {
674 T::disable();
675 }
676}
677
678impl<'d, T: BasicInstance, TxDma> Drop for UartRx<'d, T, TxDma> {
679 fn drop(&mut self) {
680 T::disable();
681 }
682}
683
621impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> { 684impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
622 pub fn new( 685 pub fn new(
623 peri: impl Peripheral<P = T> + 'd, 686 peri: impl Peripheral<P = T> + 'd,
@@ -627,7 +690,9 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
627 tx_dma: impl Peripheral<P = TxDma> + 'd, 690 tx_dma: impl Peripheral<P = TxDma> + 'd,
628 rx_dma: impl Peripheral<P = RxDma> + 'd, 691 rx_dma: impl Peripheral<P = RxDma> + 'd,
629 config: Config, 692 config: Config,
630 ) -> Self { 693 ) -> Result<Self, ConfigError> {
694 // UartRx and UartTx have one refcount ea.
695 T::enable();
631 T::enable(); 696 T::enable();
632 T::reset(); 697 T::reset();
633 698
@@ -644,9 +709,11 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
644 tx_dma: impl Peripheral<P = TxDma> + 'd, 709 tx_dma: impl Peripheral<P = TxDma> + 'd,
645 rx_dma: impl Peripheral<P = RxDma> + 'd, 710 rx_dma: impl Peripheral<P = RxDma> + 'd,
646 config: Config, 711 config: Config,
647 ) -> Self { 712 ) -> Result<Self, ConfigError> {
648 into_ref!(cts, rts); 713 into_ref!(cts, rts);
649 714
715 // UartRx and UartTx have one refcount ea.
716 T::enable();
650 T::enable(); 717 T::enable();
651 T::reset(); 718 T::reset();
652 719
@@ -669,9 +736,11 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
669 tx_dma: impl Peripheral<P = TxDma> + 'd, 736 tx_dma: impl Peripheral<P = TxDma> + 'd,
670 rx_dma: impl Peripheral<P = RxDma> + 'd, 737 rx_dma: impl Peripheral<P = RxDma> + 'd,
671 config: Config, 738 config: Config,
672 ) -> Self { 739 ) -> Result<Self, ConfigError> {
673 into_ref!(de); 740 into_ref!(de);
674 741
742 // UartRx and UartTx have one refcount ea.
743 T::enable();
675 T::enable(); 744 T::enable();
676 T::reset(); 745 T::reset();
677 746
@@ -689,7 +758,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
689 tx_dma: impl Peripheral<P = TxDma> + 'd, 758 tx_dma: impl Peripheral<P = TxDma> + 'd,
690 rx_dma: impl Peripheral<P = RxDma> + 'd, 759 rx_dma: impl Peripheral<P = RxDma> + 'd,
691 config: Config, 760 config: Config,
692 ) -> Self { 761 ) -> Result<Self, ConfigError> {
693 into_ref!(peri, rx, tx, tx_dma, rx_dma); 762 into_ref!(peri, rx, tx, tx_dma, rx_dma);
694 763
695 let r = T::regs(); 764 let r = T::regs();
@@ -711,7 +780,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
711 } 780 }
712 } 781 }
713 782
714 configure(r, &config, T::frequency(), T::KIND, true, true); 783 configure(r, &config, T::frequency(), T::KIND, true, true)?;
715 784
716 T::Interrupt::unpend(); 785 T::Interrupt::unpend();
717 unsafe { T::Interrupt::enable() }; 786 unsafe { T::Interrupt::enable() };
@@ -719,7 +788,7 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
719 // create state once! 788 // create state once!
720 let _s = T::state(); 789 let _s = T::state();
721 790
722 Self { 791 Ok(Self {
723 tx: UartTx { 792 tx: UartTx {
724 tx_dma, 793 tx_dma,
725 phantom: PhantomData, 794 phantom: PhantomData,
@@ -731,7 +800,11 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
731 #[cfg(any(usart_v1, usart_v2))] 800 #[cfg(any(usart_v1, usart_v2))]
732 buffered_sr: stm32_metapac::usart::regs::Sr(0), 801 buffered_sr: stm32_metapac::usart::regs::Sr(0),
733 }, 802 },
734 } 803 })
804 }
805
806 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
807 reconfigure::<T>(config)
735 } 808 }
736 809
737 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> 810 pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error>
@@ -779,7 +852,27 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
779 } 852 }
780} 853}
781 854
782fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: bool, enable_tx: bool) { 855fn reconfigure<T: BasicInstance>(config: &Config) -> Result<(), ConfigError> {
856 T::Interrupt::disable();
857 let r = T::regs();
858
859 let cr = r.cr1().read();
860 configure(r, config, T::frequency(), T::KIND, cr.re(), cr.te())?;
861
862 T::Interrupt::unpend();
863 unsafe { T::Interrupt::enable() };
864
865 Ok(())
866}
867
868fn configure(
869 r: Regs,
870 config: &Config,
871 pclk_freq: Hertz,
872 kind: Kind,
873 enable_rx: bool,
874 enable_tx: bool,
875) -> Result<(), ConfigError> {
783 if !enable_rx && !enable_tx { 876 if !enable_rx && !enable_tx {
784 panic!("USART: At least one of RX or TX should be enabled"); 877 panic!("USART: At least one of RX or TX should be enabled");
785 } 878 }
@@ -847,7 +940,7 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
847 found_brr = Some(brr); 940 found_brr = Some(brr);
848 break; 941 break;
849 } 942 }
850 panic!("USART: baudrate too high"); 943 return Err(ConfigError::BaudrateTooHigh);
851 } 944 }
852 945
853 if brr < brr_max { 946 if brr < brr_max {
@@ -859,7 +952,7 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
859 } 952 }
860 } 953 }
861 954
862 let brr = found_brr.expect("USART: baudrate too low"); 955 let brr = found_brr.ok_or(ConfigError::BaudrateTooLow)?;
863 956
864 #[cfg(not(usart_v1))] 957 #[cfg(not(usart_v1))]
865 let oversampling = if over8 { "8 bit" } else { "16 bit" }; 958 let oversampling = if over8 { "8 bit" } else { "16 bit" };
@@ -905,12 +998,16 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx:
905 }); 998 });
906 #[cfg(not(usart_v1))] 999 #[cfg(not(usart_v1))]
907 w.set_over8(vals::Over8::from_bits(over8 as _)); 1000 w.set_over8(vals::Over8::from_bits(over8 as _));
1001 #[cfg(usart_v4)]
1002 w.set_fifoen(true);
908 }); 1003 });
909 1004
910 #[cfg(not(usart_v1))] 1005 #[cfg(not(usart_v1))]
911 r.cr3().modify(|w| { 1006 r.cr3().modify(|w| {
912 w.set_onebit(config.assume_noise_free); 1007 w.set_onebit(config.assume_noise_free);
913 }); 1008 });
1009
1010 Ok(())
914} 1011}
915 1012
916mod eh02 { 1013mod eh02 {
@@ -1012,20 +1109,61 @@ mod eh1 {
1012 } 1109 }
1013} 1110}
1014 1111
1015#[cfg(all(feature = "unstable-traits", feature = "nightly"))] 1112impl embedded_io::Error for Error {
1016mod eio { 1113 fn kind(&self) -> embedded_io::ErrorKind {
1017 use embedded_io_async::{ErrorType, Write}; 1114 embedded_io::ErrorKind::Other
1115 }
1116}
1018 1117
1019 use super::*; 1118impl<T, TxDma, RxDma> embedded_io::ErrorType for Uart<'_, T, TxDma, RxDma>
1119where
1120 T: BasicInstance,
1121{
1122 type Error = Error;
1123}
1020 1124
1021 impl<T, TxDma, RxDma> ErrorType for Uart<'_, T, TxDma, RxDma> 1125impl<T, TxDma> embedded_io::ErrorType for UartTx<'_, T, TxDma>
1022 where 1126where
1023 T: BasicInstance, 1127 T: BasicInstance,
1024 { 1128{
1025 type Error = Error; 1129 type Error = Error;
1130}
1131
1132impl<T, TxDma, RxDma> embedded_io::Write for Uart<'_, T, TxDma, RxDma>
1133where
1134 T: BasicInstance,
1135 TxDma: crate::usart::TxDma<T>,
1136{
1137 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1138 self.blocking_write(buf)?;
1139 Ok(buf.len())
1140 }
1141
1142 fn flush(&mut self) -> Result<(), Self::Error> {
1143 self.blocking_flush()
1144 }
1145}
1146
1147impl<T, TxDma> embedded_io::Write for UartTx<'_, T, TxDma>
1148where
1149 T: BasicInstance,
1150 TxDma: crate::usart::TxDma<T>,
1151{
1152 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
1153 self.blocking_write(buf)?;
1154 Ok(buf.len())
1026 } 1155 }
1027 1156
1028 impl<T, TxDma, RxDma> Write for Uart<'_, T, TxDma, RxDma> 1157 fn flush(&mut self) -> Result<(), Self::Error> {
1158 self.blocking_flush()
1159 }
1160}
1161
1162#[cfg(all(feature = "unstable-traits", feature = "nightly"))]
1163mod eio {
1164 use super::*;
1165
1166 impl<T, TxDma, RxDma> embedded_io_async::Write for Uart<'_, T, TxDma, RxDma>
1029 where 1167 where
1030 T: BasicInstance, 1168 T: BasicInstance,
1031 TxDma: super::TxDma<T>, 1169 TxDma: super::TxDma<T>,
@@ -1040,14 +1178,7 @@ mod eio {
1040 } 1178 }
1041 } 1179 }
1042 1180
1043 impl<T, TxDma> ErrorType for UartTx<'_, T, TxDma> 1181 impl<T, TxDma> embedded_io_async::Write for UartTx<'_, T, TxDma>
1044 where
1045 T: BasicInstance,
1046 {
1047 type Error = Error;
1048 }
1049
1050 impl<T, TxDma> Write for UartTx<'_, T, TxDma>
1051 where 1182 where
1052 T: BasicInstance, 1183 T: BasicInstance,
1053 TxDma: super::TxDma<T>, 1184 TxDma: super::TxDma<T>,
diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs
index b3f570624..347aae7c9 100644
--- a/embassy-stm32/src/usart/ringbuffered.rs
+++ b/embassy-stm32/src/usart/ringbuffered.rs
@@ -1,11 +1,13 @@
1use core::future::poll_fn; 1use core::future::poll_fn;
2use core::mem;
2use core::sync::atomic::{compiler_fence, Ordering}; 3use core::sync::atomic::{compiler_fence, Ordering};
3use core::task::Poll; 4use core::task::Poll;
4 5
6use embassy_embedded_hal::SetConfig;
5use embassy_hal_internal::PeripheralRef; 7use embassy_hal_internal::PeripheralRef;
6use futures::future::{select, Either}; 8use futures::future::{select, Either};
7 9
8use super::{clear_interrupt_flags, rdr, sr, BasicInstance, Error, UartRx}; 10use super::{clear_interrupt_flags, rdr, reconfigure, sr, BasicInstance, Config, ConfigError, Error, UartRx};
9use crate::dma::ReadableRingBuffer; 11use crate::dma::ReadableRingBuffer;
10use crate::usart::{Regs, Sr}; 12use crate::usart::{Regs, Sr};
11 13
@@ -14,6 +16,14 @@ pub struct RingBufferedUartRx<'d, T: BasicInstance, RxDma: super::RxDma<T>> {
14 ring_buf: ReadableRingBuffer<'d, RxDma, u8>, 16 ring_buf: ReadableRingBuffer<'d, RxDma, u8>,
15} 17}
16 18
19impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> SetConfig for RingBufferedUartRx<'d, T, RxDma> {
20 type Config = Config;
21
22 fn set_config(&mut self, config: &Self::Config) {
23 unwrap!(self.set_config(config));
24 }
25}
26
17impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> { 27impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
18 /// Turn the `UartRx` into a buffered uart which can continously receive in the background 28 /// Turn the `UartRx` into a buffered uart which can continously receive in the background
19 /// without the possibility of loosing bytes. The `dma_buf` is a buffer registered to the 29 /// without the possibility of loosing bytes. The `dma_buf` is a buffer registered to the
@@ -24,12 +34,16 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> UartRx<'d, T, RxDma> {
24 let request = self.rx_dma.request(); 34 let request = self.rx_dma.request();
25 let opts = Default::default(); 35 let opts = Default::default();
26 36
27 let ring_buf = unsafe { ReadableRingBuffer::new_read(self.rx_dma, request, rdr(T::regs()), dma_buf, opts) }; 37 // Safety: we forget the struct before this function returns.
38 let rx_dma = unsafe { self.rx_dma.clone_unchecked() };
39 let _peri = unsafe { self._peri.clone_unchecked() };
28 40
29 RingBufferedUartRx { 41 let ring_buf = unsafe { ReadableRingBuffer::new_read(rx_dma, request, rdr(T::regs()), dma_buf, opts) };
30 _peri: self._peri, 42
31 ring_buf, 43 // Don't disable the clock
32 } 44 mem::forget(self);
45
46 RingBufferedUartRx { _peri, ring_buf }
33 } 47 }
34} 48}
35 49
@@ -49,6 +63,11 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
49 Err(err) 63 Err(err)
50 } 64 }
51 65
66 pub fn set_config(&mut self, config: &Config) -> Result<(), ConfigError> {
67 self.teardown_uart();
68 reconfigure::<T>(config)
69 }
70
52 /// Start uart background receive 71 /// Start uart background receive
53 fn setup_uart(&mut self) { 72 fn setup_uart(&mut self) {
54 // fence before starting DMA. 73 // fence before starting DMA.
@@ -186,6 +205,8 @@ impl<'d, T: BasicInstance, RxDma: super::RxDma<T>> RingBufferedUartRx<'d, T, RxD
186impl<T: BasicInstance, RxDma: super::RxDma<T>> Drop for RingBufferedUartRx<'_, T, RxDma> { 205impl<T: BasicInstance, RxDma: super::RxDma<T>> Drop for RingBufferedUartRx<'_, T, RxDma> {
187 fn drop(&mut self) { 206 fn drop(&mut self) {
188 self.teardown_uart(); 207 self.teardown_uart();
208
209 T::disable();
189 } 210 }
190} 211}
191/// Return an error result if the Sr register has errors 212/// Return an error result if the Sr register has errors
diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs
index cef196355..b24fc74eb 100644
--- a/embassy-stm32/src/usb/usb.rs
+++ b/embassy-stm32/src/usb/usb.rs
@@ -264,10 +264,7 @@ impl<'d, T: Instance> Driver<'d, T> {
264 let regs = T::regs(); 264 let regs = T::regs();
265 265
266 #[cfg(stm32l5)] 266 #[cfg(stm32l5)]
267 { 267 crate::pac::PWR.cr2().modify(|w| w.set_usv(true));
268 crate::peripherals::PWR::enable();
269 crate::pac::PWR.cr2().modify(|w| w.set_usv(true));
270 }
271 268
272 #[cfg(pwr_h5)] 269 #[cfg(pwr_h5)]
273 crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)); 270 crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true));
diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs
index 348f0f79d..1fe010bbb 100644
--- a/embassy-stm32/src/usb_otg/usb.rs
+++ b/embassy-stm32/src/usb_otg/usb.rs
@@ -540,10 +540,7 @@ impl<'d, T: Instance> Bus<'d, T> {
540impl<'d, T: Instance> Bus<'d, T> { 540impl<'d, T: Instance> Bus<'d, T> {
541 fn init(&mut self) { 541 fn init(&mut self) {
542 #[cfg(stm32l4)] 542 #[cfg(stm32l4)]
543 { 543 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
544 crate::peripherals::PWR::enable();
545 critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true)));
546 }
547 544
548 #[cfg(stm32f7)] 545 #[cfg(stm32f7)]
549 { 546 {
@@ -618,15 +615,10 @@ impl<'d, T: Instance> Bus<'d, T> {
618 { 615 {
619 // Enable USB power 616 // Enable USB power
620 critical_section::with(|_| { 617 critical_section::with(|_| {
621 crate::pac::RCC.ahb3enr().modify(|w| {
622 w.set_pwren(true);
623 });
624 cortex_m::asm::delay(2);
625
626 crate::pac::PWR.svmcr().modify(|w| { 618 crate::pac::PWR.svmcr().modify(|w| {
627 w.set_usv(true); 619 w.set_usv(true);
628 w.set_uvmen(true); 620 w.set_uvmen(true);
629 }); 621 })
630 }); 622 });
631 623
632 // Wait for USB power to stabilize 624 // Wait for USB power to stabilize