aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDion Dokter <[email protected]>2024-07-08 16:54:06 +0200
committerDion Dokter <[email protected]>2024-07-08 16:54:06 +0200
commit203297b56912c05d2dd6a009ffeb433fb2ffbea6 (patch)
treefa1708215925ad861d68dc8454069c11ae5c861c
parentb1ea90a87e5ce6b16bbc155ad30d6d3473a998bb (diff)
Make clocks repr C.
Add shared data. Modify freq functions to use shared data. Modify examples to use new init/
-rw-r--r--embassy-stm32/Cargo.toml123
-rw-r--r--embassy-stm32/build.rs7
-rw-r--r--embassy-stm32/src/lib.rs116
-rw-r--r--embassy-stm32/src/rcc/mod.rs27
-rw-r--r--embassy-stm32/src/rtc/mod.rs2
-rw-r--r--embassy-stm32/src/time.rs36
-rw-r--r--examples/stm32h755cm4/.cargo/config.toml2
-rw-r--r--examples/stm32h755cm4/memory.x2
-rw-r--r--examples/stm32h755cm4/src/bin/blinky.rs16
-rw-r--r--examples/stm32h755cm7/.cargo/config.toml2
-rw-r--r--examples/stm32h755cm7/src/bin/blinky.rs12
11 files changed, 272 insertions, 73 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 523bacb11..a72a1a667 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -181,6 +181,9 @@ split-pc3 = ["_split-pins-enabled"]
181## internal use only 181## internal use only
182_split-pins-enabled = [] 182_split-pins-enabled = []
183 183
184## internal use only
185_dual-core = []
186
184#! ## Chip-selection features 187#! ## Chip-selection features
185#! Select your chip by specifying the model as a feature, e.g. `stm32c011d6`. 188#! Select your chip by specifying the model as a feature, e.g. `stm32c011d6`.
186#! Check the `Cargo.toml` for the latest list of supported chips. 189#! Check the `Cargo.toml` for the latest list of supported chips.
@@ -1004,40 +1007,40 @@ stm32h743xg = [ "stm32-metapac/stm32h743xg" ]
1004stm32h743xi = [ "stm32-metapac/stm32h743xi" ] 1007stm32h743xi = [ "stm32-metapac/stm32h743xi" ]
1005stm32h743zg = [ "stm32-metapac/stm32h743zg" ] 1008stm32h743zg = [ "stm32-metapac/stm32h743zg" ]
1006stm32h743zi = [ "stm32-metapac/stm32h743zi" ] 1009stm32h743zi = [ "stm32-metapac/stm32h743zi" ]
1007stm32h745bg-cm7 = [ "stm32-metapac/stm32h745bg-cm7" ] 1010stm32h745bg-cm7 = [ "stm32-metapac/stm32h745bg-cm7", "_dual-core" ]
1008stm32h745bg-cm4 = [ "stm32-metapac/stm32h745bg-cm4" ] 1011stm32h745bg-cm4 = [ "stm32-metapac/stm32h745bg-cm4", "_dual-core" ]
1009stm32h745bi-cm7 = [ "stm32-metapac/stm32h745bi-cm7" ] 1012stm32h745bi-cm7 = [ "stm32-metapac/stm32h745bi-cm7", "_dual-core" ]
1010stm32h745bi-cm4 = [ "stm32-metapac/stm32h745bi-cm4" ] 1013stm32h745bi-cm4 = [ "stm32-metapac/stm32h745bi-cm4", "_dual-core" ]
1011stm32h745ig-cm7 = [ "stm32-metapac/stm32h745ig-cm7" ] 1014stm32h745ig-cm7 = [ "stm32-metapac/stm32h745ig-cm7", "_dual-core" ]
1012stm32h745ig-cm4 = [ "stm32-metapac/stm32h745ig-cm4" ] 1015stm32h745ig-cm4 = [ "stm32-metapac/stm32h745ig-cm4", "_dual-core" ]
1013stm32h745ii-cm7 = [ "stm32-metapac/stm32h745ii-cm7" ] 1016stm32h745ii-cm7 = [ "stm32-metapac/stm32h745ii-cm7", "_dual-core" ]
1014stm32h745ii-cm4 = [ "stm32-metapac/stm32h745ii-cm4" ] 1017stm32h745ii-cm4 = [ "stm32-metapac/stm32h745ii-cm4", "_dual-core" ]
1015stm32h745xg-cm7 = [ "stm32-metapac/stm32h745xg-cm7" ] 1018stm32h745xg-cm7 = [ "stm32-metapac/stm32h745xg-cm7", "_dual-core" ]
1016stm32h745xg-cm4 = [ "stm32-metapac/stm32h745xg-cm4" ] 1019stm32h745xg-cm4 = [ "stm32-metapac/stm32h745xg-cm4", "_dual-core" ]
1017stm32h745xi-cm7 = [ "stm32-metapac/stm32h745xi-cm7" ] 1020stm32h745xi-cm7 = [ "stm32-metapac/stm32h745xi-cm7", "_dual-core" ]
1018stm32h745xi-cm4 = [ "stm32-metapac/stm32h745xi-cm4" ] 1021stm32h745xi-cm4 = [ "stm32-metapac/stm32h745xi-cm4", "_dual-core" ]
1019stm32h745zg-cm7 = [ "stm32-metapac/stm32h745zg-cm7" ] 1022stm32h745zg-cm7 = [ "stm32-metapac/stm32h745zg-cm7", "_dual-core" ]
1020stm32h745zg-cm4 = [ "stm32-metapac/stm32h745zg-cm4" ] 1023stm32h745zg-cm4 = [ "stm32-metapac/stm32h745zg-cm4", "_dual-core" ]
1021stm32h745zi-cm7 = [ "stm32-metapac/stm32h745zi-cm7" ] 1024stm32h745zi-cm7 = [ "stm32-metapac/stm32h745zi-cm7", "_dual-core" ]
1022stm32h745zi-cm4 = [ "stm32-metapac/stm32h745zi-cm4" ] 1025stm32h745zi-cm4 = [ "stm32-metapac/stm32h745zi-cm4", "_dual-core" ]
1023stm32h747ag-cm7 = [ "stm32-metapac/stm32h747ag-cm7" ] 1026stm32h747ag-cm7 = [ "stm32-metapac/stm32h747ag-cm7", "_dual-core" ]
1024stm32h747ag-cm4 = [ "stm32-metapac/stm32h747ag-cm4" ] 1027stm32h747ag-cm4 = [ "stm32-metapac/stm32h747ag-cm4", "_dual-core" ]
1025stm32h747ai-cm7 = [ "stm32-metapac/stm32h747ai-cm7" ] 1028stm32h747ai-cm7 = [ "stm32-metapac/stm32h747ai-cm7", "_dual-core" ]
1026stm32h747ai-cm4 = [ "stm32-metapac/stm32h747ai-cm4" ] 1029stm32h747ai-cm4 = [ "stm32-metapac/stm32h747ai-cm4", "_dual-core" ]
1027stm32h747bg-cm7 = [ "stm32-metapac/stm32h747bg-cm7" ] 1030stm32h747bg-cm7 = [ "stm32-metapac/stm32h747bg-cm7", "_dual-core" ]
1028stm32h747bg-cm4 = [ "stm32-metapac/stm32h747bg-cm4" ] 1031stm32h747bg-cm4 = [ "stm32-metapac/stm32h747bg-cm4", "_dual-core" ]
1029stm32h747bi-cm7 = [ "stm32-metapac/stm32h747bi-cm7" ] 1032stm32h747bi-cm7 = [ "stm32-metapac/stm32h747bi-cm7", "_dual-core" ]
1030stm32h747bi-cm4 = [ "stm32-metapac/stm32h747bi-cm4" ] 1033stm32h747bi-cm4 = [ "stm32-metapac/stm32h747bi-cm4", "_dual-core" ]
1031stm32h747ig-cm7 = [ "stm32-metapac/stm32h747ig-cm7" ] 1034stm32h747ig-cm7 = [ "stm32-metapac/stm32h747ig-cm7", "_dual-core" ]
1032stm32h747ig-cm4 = [ "stm32-metapac/stm32h747ig-cm4" ] 1035stm32h747ig-cm4 = [ "stm32-metapac/stm32h747ig-cm4", "_dual-core" ]
1033stm32h747ii-cm7 = [ "stm32-metapac/stm32h747ii-cm7" ] 1036stm32h747ii-cm7 = [ "stm32-metapac/stm32h747ii-cm7", "_dual-core" ]
1034stm32h747ii-cm4 = [ "stm32-metapac/stm32h747ii-cm4" ] 1037stm32h747ii-cm4 = [ "stm32-metapac/stm32h747ii-cm4", "_dual-core" ]
1035stm32h747xg-cm7 = [ "stm32-metapac/stm32h747xg-cm7" ] 1038stm32h747xg-cm7 = [ "stm32-metapac/stm32h747xg-cm7", "_dual-core" ]
1036stm32h747xg-cm4 = [ "stm32-metapac/stm32h747xg-cm4" ] 1039stm32h747xg-cm4 = [ "stm32-metapac/stm32h747xg-cm4", "_dual-core" ]
1037stm32h747xi-cm7 = [ "stm32-metapac/stm32h747xi-cm7" ] 1040stm32h747xi-cm7 = [ "stm32-metapac/stm32h747xi-cm7", "_dual-core" ]
1038stm32h747xi-cm4 = [ "stm32-metapac/stm32h747xi-cm4" ] 1041stm32h747xi-cm4 = [ "stm32-metapac/stm32h747xi-cm4", "_dual-core" ]
1039stm32h747zi-cm7 = [ "stm32-metapac/stm32h747zi-cm7" ] 1042stm32h747zi-cm7 = [ "stm32-metapac/stm32h747zi-cm7", "_dual-core" ]
1040stm32h747zi-cm4 = [ "stm32-metapac/stm32h747zi-cm4" ] 1043stm32h747zi-cm4 = [ "stm32-metapac/stm32h747zi-cm4", "_dual-core" ]
1041stm32h750ib = [ "stm32-metapac/stm32h750ib" ] 1044stm32h750ib = [ "stm32-metapac/stm32h750ib" ]
1042stm32h750vb = [ "stm32-metapac/stm32h750vb" ] 1045stm32h750vb = [ "stm32-metapac/stm32h750vb" ]
1043stm32h750xb = [ "stm32-metapac/stm32h750xb" ] 1046stm32h750xb = [ "stm32-metapac/stm32h750xb" ]
@@ -1048,24 +1051,24 @@ stm32h753ii = [ "stm32-metapac/stm32h753ii" ]
1048stm32h753vi = [ "stm32-metapac/stm32h753vi" ] 1051stm32h753vi = [ "stm32-metapac/stm32h753vi" ]
1049stm32h753xi = [ "stm32-metapac/stm32h753xi" ] 1052stm32h753xi = [ "stm32-metapac/stm32h753xi" ]
1050stm32h753zi = [ "stm32-metapac/stm32h753zi" ] 1053stm32h753zi = [ "stm32-metapac/stm32h753zi" ]
1051stm32h755bi-cm7 = [ "stm32-metapac/stm32h755bi-cm7" ] 1054stm32h755bi-cm7 = [ "stm32-metapac/stm32h755bi-cm7", "_dual-core" ]
1052stm32h755bi-cm4 = [ "stm32-metapac/stm32h755bi-cm4" ] 1055stm32h755bi-cm4 = [ "stm32-metapac/stm32h755bi-cm4", "_dual-core" ]
1053stm32h755ii-cm7 = [ "stm32-metapac/stm32h755ii-cm7" ] 1056stm32h755ii-cm7 = [ "stm32-metapac/stm32h755ii-cm7", "_dual-core" ]
1054stm32h755ii-cm4 = [ "stm32-metapac/stm32h755ii-cm4" ] 1057stm32h755ii-cm4 = [ "stm32-metapac/stm32h755ii-cm4", "_dual-core" ]
1055stm32h755xi-cm7 = [ "stm32-metapac/stm32h755xi-cm7" ] 1058stm32h755xi-cm7 = [ "stm32-metapac/stm32h755xi-cm7", "_dual-core" ]
1056stm32h755xi-cm4 = [ "stm32-metapac/stm32h755xi-cm4" ] 1059stm32h755xi-cm4 = [ "stm32-metapac/stm32h755xi-cm4", "_dual-core" ]
1057stm32h755zi-cm7 = [ "stm32-metapac/stm32h755zi-cm7" ] 1060stm32h755zi-cm7 = [ "stm32-metapac/stm32h755zi-cm7", "_dual-core" ]
1058stm32h755zi-cm4 = [ "stm32-metapac/stm32h755zi-cm4" ] 1061stm32h755zi-cm4 = [ "stm32-metapac/stm32h755zi-cm4", "_dual-core" ]
1059stm32h757ai-cm7 = [ "stm32-metapac/stm32h757ai-cm7" ] 1062stm32h757ai-cm7 = [ "stm32-metapac/stm32h757ai-cm7", "_dual-core" ]
1060stm32h757ai-cm4 = [ "stm32-metapac/stm32h757ai-cm4" ] 1063stm32h757ai-cm4 = [ "stm32-metapac/stm32h757ai-cm4", "_dual-core" ]
1061stm32h757bi-cm7 = [ "stm32-metapac/stm32h757bi-cm7" ] 1064stm32h757bi-cm7 = [ "stm32-metapac/stm32h757bi-cm7", "_dual-core" ]
1062stm32h757bi-cm4 = [ "stm32-metapac/stm32h757bi-cm4" ] 1065stm32h757bi-cm4 = [ "stm32-metapac/stm32h757bi-cm4", "_dual-core" ]
1063stm32h757ii-cm7 = [ "stm32-metapac/stm32h757ii-cm7" ] 1066stm32h757ii-cm7 = [ "stm32-metapac/stm32h757ii-cm7", "_dual-core" ]
1064stm32h757ii-cm4 = [ "stm32-metapac/stm32h757ii-cm4" ] 1067stm32h757ii-cm4 = [ "stm32-metapac/stm32h757ii-cm4", "_dual-core" ]
1065stm32h757xi-cm7 = [ "stm32-metapac/stm32h757xi-cm7" ] 1068stm32h757xi-cm7 = [ "stm32-metapac/stm32h757xi-cm7", "_dual-core" ]
1066stm32h757xi-cm4 = [ "stm32-metapac/stm32h757xi-cm4" ] 1069stm32h757xi-cm4 = [ "stm32-metapac/stm32h757xi-cm4", "_dual-core" ]
1067stm32h757zi-cm7 = [ "stm32-metapac/stm32h757zi-cm7" ] 1070stm32h757zi-cm7 = [ "stm32-metapac/stm32h757zi-cm7", "_dual-core" ]
1068stm32h757zi-cm4 = [ "stm32-metapac/stm32h757zi-cm4" ] 1071stm32h757zi-cm4 = [ "stm32-metapac/stm32h757zi-cm4", "_dual-core" ]
1069stm32h7a3ag = [ "stm32-metapac/stm32h7a3ag" ] 1072stm32h7a3ag = [ "stm32-metapac/stm32h7a3ag" ]
1070stm32h7a3ai = [ "stm32-metapac/stm32h7a3ai" ] 1073stm32h7a3ai = [ "stm32-metapac/stm32h7a3ai" ]
1071stm32h7a3ig = [ "stm32-metapac/stm32h7a3ig" ] 1074stm32h7a3ig = [ "stm32-metapac/stm32h7a3ig" ]
@@ -1598,14 +1601,14 @@ stm32wba55he = [ "stm32-metapac/stm32wba55he" ]
1598stm32wba55hg = [ "stm32-metapac/stm32wba55hg" ] 1601stm32wba55hg = [ "stm32-metapac/stm32wba55hg" ]
1599stm32wba55ue = [ "stm32-metapac/stm32wba55ue" ] 1602stm32wba55ue = [ "stm32-metapac/stm32wba55ue" ]
1600stm32wba55ug = [ "stm32-metapac/stm32wba55ug" ] 1603stm32wba55ug = [ "stm32-metapac/stm32wba55ug" ]
1601stm32wl54cc-cm4 = [ "stm32-metapac/stm32wl54cc-cm4" ] 1604stm32wl54cc-cm4 = [ "stm32-metapac/stm32wl54cc-cm4", "_dual-core" ]
1602stm32wl54cc-cm0p = [ "stm32-metapac/stm32wl54cc-cm0p" ] 1605stm32wl54cc-cm0p = [ "stm32-metapac/stm32wl54cc-cm0p", "_dual-core" ]
1603stm32wl54jc-cm4 = [ "stm32-metapac/stm32wl54jc-cm4" ] 1606stm32wl54jc-cm4 = [ "stm32-metapac/stm32wl54jc-cm4", "_dual-core" ]
1604stm32wl54jc-cm0p = [ "stm32-metapac/stm32wl54jc-cm0p" ] 1607stm32wl54jc-cm0p = [ "stm32-metapac/stm32wl54jc-cm0p", "_dual-core" ]
1605stm32wl55cc-cm4 = [ "stm32-metapac/stm32wl55cc-cm4" ] 1608stm32wl55cc-cm4 = [ "stm32-metapac/stm32wl55cc-cm4", "_dual-core" ]
1606stm32wl55cc-cm0p = [ "stm32-metapac/stm32wl55cc-cm0p" ] 1609stm32wl55cc-cm0p = [ "stm32-metapac/stm32wl55cc-cm0p", "_dual-core" ]
1607stm32wl55jc-cm4 = [ "stm32-metapac/stm32wl55jc-cm4" ] 1610stm32wl55jc-cm4 = [ "stm32-metapac/stm32wl55jc-cm4", "_dual-core" ]
1608stm32wl55jc-cm0p = [ "stm32-metapac/stm32wl55jc-cm0p" ] 1611stm32wl55jc-cm0p = [ "stm32-metapac/stm32wl55jc-cm0p", "_dual-core" ]
1609stm32wle4c8 = [ "stm32-metapac/stm32wle4c8" ] 1612stm32wle4c8 = [ "stm32-metapac/stm32wle4c8" ]
1610stm32wle4cb = [ "stm32-metapac/stm32wle4cb" ] 1613stm32wle4cb = [ "stm32-metapac/stm32wle4cb" ]
1611stm32wle4cc = [ "stm32-metapac/stm32wle4cc" ] 1614stm32wle4cc = [ "stm32-metapac/stm32wle4cc" ]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 8457e3a13..d8a7ea0e6 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -480,7 +480,7 @@ fn main() {
480 self.clock_names.insert(name.to_ascii_lowercase()); 480 self.clock_names.insert(name.to_ascii_lowercase());
481 quote!(unsafe { 481 quote!(unsafe {
482 unwrap!( 482 unwrap!(
483 crate::rcc::get_freqs().#clock_name, 483 crate::rcc::get_freqs().#clock_name.to_hertz(),
484 "peripheral '{}' is configured to use the '{}' clock, which is not running. \ 484 "peripheral '{}' is configured to use the '{}' clock, which is not running. \
485 Either enable it in 'config.rcc' or change 'config.rcc.mux' to use another clock", 485 Either enable it in 'config.rcc' or change 'config.rcc.mux' to use another clock",
486 #peripheral, 486 #peripheral,
@@ -713,9 +713,10 @@ fn main() {
713 g.extend(quote! { 713 g.extend(quote! {
714 #[derive(Clone, Copy, Debug)] 714 #[derive(Clone, Copy, Debug)]
715 #[cfg_attr(feature = "defmt", derive(defmt::Format))] 715 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
716 #[repr(C)]
716 pub struct Clocks { 717 pub struct Clocks {
717 #( 718 #(
718 pub #clock_idents: Option<crate::time::Hertz>, 719 pub #clock_idents: crate::time::MaybeHertz,
719 )* 720 )*
720 } 721 }
721 }); 722 });
@@ -732,7 +733,7 @@ fn main() {
732 $($(#[$m])* $k: $v,)* 733 $($(#[$m])* $k: $v,)*
733 }; 734 };
734 crate::rcc::set_freqs(crate::rcc::Clocks { 735 crate::rcc::set_freqs(crate::rcc::Clocks {
735 #( #clock_idents: all.#clock_idents, )* 736 #( #clock_idents: all.#clock_idents.into(), )*
736 }); 737 });
737 } 738 }
738 }; 739 };
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 95f59360a..8f001f03b 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -273,7 +273,123 @@ impl Default for Config {
273/// This returns the peripheral singletons that can be used for creating drivers. 273/// This returns the peripheral singletons that can be used for creating drivers.
274/// 274///
275/// This should only be called once at startup, otherwise it panics. 275/// This should only be called once at startup, otherwise it panics.
276#[cfg(not(feature = "_dual-core"))]
276pub fn init(config: Config) -> Peripherals { 277pub fn init(config: Config) -> Peripherals {
278 init_hw(config)
279}
280
281#[cfg(feature = "_dual-core")]
282mod dual_core {
283 use rcc::Clocks;
284
285 use super::*;
286 use core::{
287 mem::MaybeUninit,
288 sync::atomic::{AtomicUsize, Ordering},
289 };
290
291 /// Object containing data that embassy needs to share between cores.
292 ///
293 /// It cannot be initialized by the user. The intended use is:
294 ///
295 /// ```
296 /// #[link_section = ".ram_d3"]
297 /// static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
298 ///
299 /// init_secondary(&SHARED_DATA);
300 /// ```
301 ///
302 /// This static must be placed in the same position for both cores. How and where this is done is left to the user.
303 pub struct SharedData {
304 init_flag: AtomicUsize,
305 clocks: MaybeUninit<Clocks>,
306 }
307
308 const INIT_DONE_FLAG: usize = 0xca11ab1e;
309
310 /// Initialize the `embassy-stm32` HAL with the provided configuration.
311 /// This function does the actual initialization of the hardware, in contrast to [init_secondary] or [try_init_secondary].
312 /// Any core can do the init, but it's important only one core does it.
313 ///
314 /// This returns the peripheral singletons that can be used for creating drivers.
315 ///
316 /// This should only be called once at startup, otherwise it panics.
317 ///
318 /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs
319 /// for more information on its requirements.
320 pub fn init_primary(config: Config, shared_data: &'static MaybeUninit<SharedData>) -> Peripherals {
321 let shared_data = unsafe { shared_data.assume_init_ref() };
322
323 rcc::set_freqs_ptr(&shared_data.clocks);
324 let p = init_hw(config);
325
326 shared_data.init_flag.store(INIT_DONE_FLAG, Ordering::SeqCst);
327
328 p
329 }
330
331 /// Try to initialize the `embassy-stm32` HAL based on the init done by the other core using [init_primary].
332 ///
333 /// This returns the peripheral singletons that can be used for creating drivers if the other core is done with its init.
334 /// If the other core is not done yet, this will return `None`.
335 ///
336 /// This should only be called once at startup, otherwise it may panic.
337 ///
338 /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs
339 /// for more information on its requirements.
340 pub fn try_init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Option<Peripherals> {
341 let shared_data = unsafe { shared_data.assume_init_ref() };
342
343 if shared_data
344 .init_flag
345 .compare_exchange(INIT_DONE_FLAG, 0, Ordering::SeqCst, Ordering::SeqCst)
346 .is_err()
347 {
348 return None;
349 }
350
351 Some(init_secondary_hw(shared_data))
352 }
353
354 /// Initialize the `embassy-stm32` HAL based on the init done by the other core using [init_primary].
355 ///
356 /// This returns the peripheral singletons that can be used for creating drivers when the other core is done with its init.
357 /// If the other core is not done yet, this will spinloop wait on it.
358 ///
359 /// This should only be called once at startup, otherwise it may panic.
360 ///
361 /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs
362 /// for more information on its requirements.
363 pub fn init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Peripherals {
364 let shared_data = unsafe { shared_data.assume_init_ref() };
365
366 while shared_data
367 .init_flag
368 .compare_exchange(INIT_DONE_FLAG, 0, Ordering::SeqCst, Ordering::SeqCst)
369 .is_err()
370 {}
371
372 init_secondary_hw(shared_data)
373 }
374
375 fn init_secondary_hw(shared_data: &'static SharedData) -> Peripherals {
376 rcc::set_freqs_ptr(&shared_data.clocks);
377
378 // We use different timers on the different cores, so we have to still initialize one here
379 critical_section::with(|cs| {
380 // must be after rcc init
381 #[cfg(feature = "_time-driver")]
382 time_driver::init(cs);
383 });
384
385 Peripherals::take()
386 }
387}
388
389#[cfg(feature = "_dual-core")]
390pub use dual_core::*;
391
392fn init_hw(config: Config) -> Peripherals {
277 critical_section::with(|cs| { 393 critical_section::with(|cs| {
278 let p = Peripherals::take_with_cs(cs); 394 let p = Peripherals::take_with_cs(cs);
279 395
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 024c63cf5..587231b0c 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -48,11 +48,22 @@ pub(crate) static mut REFCOUNT_STOP1: u32 = 0;
48/// May be read without a critical section 48/// May be read without a critical section
49pub(crate) static mut REFCOUNT_STOP2: u32 = 0; 49pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
50 50
51#[cfg(not(feature = "_dual-core"))]
51/// Frozen clock frequencies 52/// Frozen clock frequencies
52/// 53///
53/// The existence of this value indicates that the clock configuration can no longer be changed 54/// The existence of this value indicates that the clock configuration can no longer be changed
54static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit(); 55static mut CLOCK_FREQS: MaybeUninit<Clocks> = MaybeUninit::uninit();
55 56
57#[cfg(feature = "_dual-core")]
58static CLOCK_FREQS_PTR: core::sync::atomic::AtomicPtr<MaybeUninit<Clocks>> =
59 core::sync::atomic::AtomicPtr::new(core::ptr::null_mut());
60
61#[cfg(feature = "_dual-core")]
62pub(crate) fn set_freqs_ptr(freqs: &'static MaybeUninit<Clocks>) {
63 CLOCK_FREQS_PTR.store(freqs as *const _ as *mut _, core::sync::atomic::Ordering::SeqCst);
64}
65
66#[cfg(not(feature = "_dual-core"))]
56/// Sets the clock frequencies 67/// Sets the clock frequencies
57/// 68///
58/// Safety: Sets a mutable global. 69/// Safety: Sets a mutable global.
@@ -61,11 +72,27 @@ pub(crate) unsafe fn set_freqs(freqs: Clocks) {
61 CLOCK_FREQS = MaybeUninit::new(freqs); 72 CLOCK_FREQS = MaybeUninit::new(freqs);
62} 73}
63 74
75#[cfg(feature = "_dual-core")]
76/// Sets the clock frequencies
77///
78/// Safety: Sets a mutable global.
79pub(crate) unsafe fn set_freqs(freqs: Clocks) {
80 debug!("rcc: {:?}", freqs);
81 CLOCK_FREQS_PTR.load(core::sync::atomic::Ordering::SeqCst).write(MaybeUninit::new(freqs));
82}
83
84#[cfg(not(feature = "_dual-core"))]
64/// Safety: Reads a mutable global. 85/// Safety: Reads a mutable global.
65pub(crate) unsafe fn get_freqs() -> &'static Clocks { 86pub(crate) unsafe fn get_freqs() -> &'static Clocks {
66 CLOCK_FREQS.assume_init_ref() 87 CLOCK_FREQS.assume_init_ref()
67} 88}
68 89
90#[cfg(feature = "_dual-core")]
91/// Safety: Reads a mutable global.
92pub(crate) unsafe fn get_freqs() -> &'static Clocks {
93 unwrap!(CLOCK_FREQS_PTR.load(core::sync::atomic::Ordering::SeqCst).as_ref()).assume_init_ref()
94}
95
69pub(crate) trait SealedRccPeripheral { 96pub(crate) trait SealedRccPeripheral {
70 fn frequency() -> Hertz; 97 fn frequency() -> Hertz;
71 const RCC_INFO: RccInfo; 98 const RCC_INFO: RccInfo;
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index a7f70b153..fe57cfe66 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -168,7 +168,7 @@ impl Rtc {
168 168
169 fn frequency() -> Hertz { 169 fn frequency() -> Hertz {
170 let freqs = unsafe { crate::rcc::get_freqs() }; 170 let freqs = unsafe { crate::rcc::get_freqs() };
171 freqs.rtc.unwrap() 171 freqs.rtc.to_hertz().unwrap()
172 } 172 }
173 173
174 /// Acquire a [`RtcTimeProvider`] instance. 174 /// Acquire a [`RtcTimeProvider`] instance.
diff --git a/embassy-stm32/src/time.rs b/embassy-stm32/src/time.rs
index 17690aefc..d7337191d 100644
--- a/embassy-stm32/src/time.rs
+++ b/embassy-stm32/src/time.rs
@@ -87,3 +87,39 @@ impl Div<Hertz> for Hertz {
87 self.0 / rhs.0 87 self.0 / rhs.0
88 } 88 }
89} 89}
90
91#[repr(C)]
92#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Default)]
93#[cfg_attr(feature = "defmt", derive(defmt::Format))]
94/// A variant on [Hertz] that acts as an `Option<Hertz>` that is smaller and repr C.
95///
96/// An `Option<Hertz>` can be `.into()`'d into this type and back.
97/// The only restriction is that that [Hertz] cannot have the value 0 since that's
98/// seen as the `None` variant.
99pub struct MaybeHertz(u32);
100
101impl MaybeHertz {
102 /// Same as calling the `.into()` function, but without type inference.
103 pub fn to_hertz(self) -> Option<Hertz> {
104 self.into()
105 }
106}
107
108impl From<Option<Hertz>> for MaybeHertz {
109 fn from(value: Option<Hertz>) -> Self {
110 match value {
111 Some(Hertz(0)) => panic!("Hertz cannot be 0"),
112 Some(Hertz(val)) => Self(val),
113 None => Self(0),
114 }
115 }
116}
117
118impl From<MaybeHertz> for Option<Hertz> {
119 fn from(value: MaybeHertz) -> Self {
120 match value {
121 MaybeHertz(0) => None,
122 MaybeHertz(val) => Some(Hertz(val)),
123 }
124 }
125}
diff --git a/examples/stm32h755cm4/.cargo/config.toml b/examples/stm32h755cm4/.cargo/config.toml
index f9ae6f2e7..193e6bbc3 100644
--- a/examples/stm32h755cm4/.cargo/config.toml
+++ b/examples/stm32h755cm4/.cargo/config.toml
@@ -1,5 +1,5 @@
1[target.thumbv7em-none-eabihf] 1[target.thumbv7em-none-eabihf]
2runner = 'probe-rs run --chip STM32H755ZITx' 2runner = 'probe-rs run --chip STM32H755ZITx --catch-hardfault --always-print-stacktrace'
3 3
4[build] 4[build]
5target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 5target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
diff --git a/examples/stm32h755cm4/memory.x b/examples/stm32h755cm4/memory.x
index f946b6210..538bac586 100644
--- a/examples/stm32h755cm4/memory.x
+++ b/examples/stm32h755cm4/memory.x
@@ -1,7 +1,7 @@
1MEMORY 1MEMORY
2{ 2{
3 FLASH : ORIGIN = 0x08100000, LENGTH = 1024K /* BANK_2 */ 3 FLASH : ORIGIN = 0x08100000, LENGTH = 1024K /* BANK_2 */
4 RAM : ORIGIN = 0x30000000, LENGTH = 128K /* SRAM1 */ 4 RAM : ORIGIN = 0x10000000, LENGTH = 128K /* SRAM1 */
5 RAM_D3 : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 */ 5 RAM_D3 : ORIGIN = 0x38000000, LENGTH = 64K /* SRAM4 */
6} 6}
7 7
diff --git a/examples/stm32h755cm4/src/bin/blinky.rs b/examples/stm32h755cm4/src/bin/blinky.rs
index 765be5ba1..52db326b0 100644
--- a/examples/stm32h755cm4/src/bin/blinky.rs
+++ b/examples/stm32h755cm4/src/bin/blinky.rs
@@ -1,15 +1,23 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::mem::MaybeUninit;
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::{
9 gpio::{Level, Output, Speed},
10 SharedData,
11};
7use embassy_time::Timer; 12use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
9 14
15#[link_section = ".ram_d3"]
16static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
17
10#[embassy_executor::main] 18#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 20 let p = embassy_stm32::init_secondary(&SHARED_DATA);
13 info!("Hello World!"); 21 info!("Hello World!");
14 22
15 let mut led = Output::new(p.PE1, Level::High, Speed::Low); 23 let mut led = Output::new(p.PE1, Level::High, Speed::Low);
@@ -17,10 +25,10 @@ async fn main(_spawner: Spawner) {
17 loop { 25 loop {
18 info!("high"); 26 info!("high");
19 led.set_high(); 27 led.set_high();
20 Timer::after_millis(500).await; 28 Timer::after_millis(250).await;
21 29
22 info!("low"); 30 info!("low");
23 led.set_low(); 31 led.set_low();
24 Timer::after_millis(500).await; 32 Timer::after_millis(250).await;
25 } 33 }
26} 34}
diff --git a/examples/stm32h755cm7/.cargo/config.toml b/examples/stm32h755cm7/.cargo/config.toml
index f9ae6f2e7..193e6bbc3 100644
--- a/examples/stm32h755cm7/.cargo/config.toml
+++ b/examples/stm32h755cm7/.cargo/config.toml
@@ -1,5 +1,5 @@
1[target.thumbv7em-none-eabihf] 1[target.thumbv7em-none-eabihf]
2runner = 'probe-rs run --chip STM32H755ZITx' 2runner = 'probe-rs run --chip STM32H755ZITx --catch-hardfault --always-print-stacktrace'
3 3
4[build] 4[build]
5target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) 5target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU)
diff --git a/examples/stm32h755cm7/src/bin/blinky.rs b/examples/stm32h755cm7/src/bin/blinky.rs
index 396b8c718..f76395326 100644
--- a/examples/stm32h755cm7/src/bin/blinky.rs
+++ b/examples/stm32h755cm7/src/bin/blinky.rs
@@ -1,12 +1,20 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::mem::MaybeUninit;
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
6use embassy_stm32::gpio::{Level, Output, Speed}; 8use embassy_stm32::{
9 gpio::{Level, Output, Speed},
10 SharedData,
11};
7use embassy_time::Timer; 12use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
9 14
15#[link_section = ".ram_d3"]
16static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
17
10#[embassy_executor::main] 18#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
12 let mut config = embassy_stm32::Config::default(); 20 let mut config = embassy_stm32::Config::default();
@@ -31,7 +39,7 @@ async fn main(_spawner: Spawner) {
31 config.rcc.voltage_scale = VoltageScale::Scale1; 39 config.rcc.voltage_scale = VoltageScale::Scale1;
32 config.rcc.supply_config = SupplyConfig::DirectSMPS; 40 config.rcc.supply_config = SupplyConfig::DirectSMPS;
33 } 41 }
34 let p = embassy_stm32::init(config); 42 let p = embassy_stm32::init_primary(config, &SHARED_DATA);
35 info!("Hello World!"); 43 info!("Hello World!");
36 44
37 let mut led = Output::new(p.PB14, Level::High, Speed::Low); 45 let mut led = Output::new(p.PB14, Level::High, Speed::Low);