Improve shared data placement, require less atomic support and use unsafecell for the clocks

This commit is contained in:
Dion Dokter 2024-08-05 11:18:16 +02:00
parent e39e93ead4
commit 2a7fe16ceb
7 changed files with 22 additions and 22 deletions

View File

@ -80,7 +80,7 @@ stm32-fmc = "0.3.0"
cfg-if = "1.0.0" cfg-if = "1.0.0"
embedded-io = { version = "0.6.0" } embedded-io = { version = "0.6.0" }
embedded-io-async = { version = "0.6.1" } embedded-io-async = { version = "0.6.1" }
chrono = { version = "^0.4", default-features = false, optional = true} chrono = { version = "^0.4", default-features = false, optional = true }
bit_field = "0.10.2" bit_field = "0.10.2"
document-features = "0.2.7" document-features = "0.2.7"

View File

@ -280,6 +280,7 @@ pub fn init(config: Config) -> Peripherals {
#[cfg(feature = "_dual-core")] #[cfg(feature = "_dual-core")]
mod dual_core { mod dual_core {
use core::cell::UnsafeCell;
use core::mem::MaybeUninit; use core::mem::MaybeUninit;
use core::sync::atomic::{AtomicUsize, Ordering}; use core::sync::atomic::{AtomicUsize, Ordering};
@ -301,9 +302,11 @@ mod dual_core {
/// This static must be placed in the same position for both cores. How and where this is done is left to the user. /// This static must be placed in the same position for both cores. How and where this is done is left to the user.
pub struct SharedData { pub struct SharedData {
init_flag: AtomicUsize, init_flag: AtomicUsize,
clocks: MaybeUninit<Clocks>, clocks: UnsafeCell<MaybeUninit<Clocks>>,
} }
unsafe impl Sync for SharedData {}
const INIT_DONE_FLAG: usize = 0xca11ab1e; const INIT_DONE_FLAG: usize = 0xca11ab1e;
/// Initialize the `embassy-stm32` HAL with the provided configuration. /// Initialize the `embassy-stm32` HAL with the provided configuration.
@ -319,7 +322,7 @@ mod dual_core {
pub fn init_primary(config: Config, shared_data: &'static MaybeUninit<SharedData>) -> Peripherals { pub fn init_primary(config: Config, shared_data: &'static MaybeUninit<SharedData>) -> Peripherals {
let shared_data = unsafe { shared_data.assume_init_ref() }; let shared_data = unsafe { shared_data.assume_init_ref() };
rcc::set_freqs_ptr(&shared_data.clocks); rcc::set_freqs_ptr(shared_data.clocks.get());
let p = init_hw(config); let p = init_hw(config);
shared_data.init_flag.store(INIT_DONE_FLAG, Ordering::SeqCst); shared_data.init_flag.store(INIT_DONE_FLAG, Ordering::SeqCst);
@ -339,14 +342,13 @@ mod dual_core {
pub fn try_init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Option<Peripherals> { pub fn try_init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Option<Peripherals> {
let shared_data = unsafe { shared_data.assume_init_ref() }; let shared_data = unsafe { shared_data.assume_init_ref() };
if shared_data if shared_data.init_flag.load(Ordering::SeqCst) != INIT_DONE_FLAG {
.init_flag
.compare_exchange(INIT_DONE_FLAG, 0, Ordering::SeqCst, Ordering::SeqCst)
.is_err()
{
return None; return None;
} }
// Separate load and store to support the CM0 of the STM32WL
shared_data.init_flag.store(0, Ordering::SeqCst);
Some(init_secondary_hw(shared_data)) Some(init_secondary_hw(shared_data))
} }
@ -360,19 +362,15 @@ mod dual_core {
/// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs
/// for more information on its requirements. /// for more information on its requirements.
pub fn init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Peripherals { pub fn init_secondary(shared_data: &'static MaybeUninit<SharedData>) -> Peripherals {
let shared_data = unsafe { shared_data.assume_init_ref() }; loop {
if let Some(p) = try_init_secondary(shared_data) {
while shared_data return p;
.init_flag }
.compare_exchange(INIT_DONE_FLAG, 0, Ordering::SeqCst, Ordering::SeqCst) }
.is_err()
{}
init_secondary_hw(shared_data)
} }
fn init_secondary_hw(shared_data: &'static SharedData) -> Peripherals { fn init_secondary_hw(shared_data: &'static SharedData) -> Peripherals {
rcc::set_freqs_ptr(&shared_data.clocks); rcc::set_freqs_ptr(shared_data.clocks.get());
// We use different timers on the different cores, so we have to still initialize one here // We use different timers on the different cores, so we have to still initialize one here
#[cfg(feature = "_time-driver")] #[cfg(feature = "_time-driver")]

View File

@ -59,8 +59,8 @@ static CLOCK_FREQS_PTR: core::sync::atomic::AtomicPtr<MaybeUninit<Clocks>> =
core::sync::atomic::AtomicPtr::new(core::ptr::null_mut()); core::sync::atomic::AtomicPtr::new(core::ptr::null_mut());
#[cfg(feature = "_dual-core")] #[cfg(feature = "_dual-core")]
pub(crate) fn set_freqs_ptr(freqs: &'static MaybeUninit<Clocks>) { pub(crate) fn set_freqs_ptr(freqs: *mut MaybeUninit<Clocks>) {
CLOCK_FREQS_PTR.store(freqs as *const _ as *mut _, core::sync::atomic::Ordering::SeqCst); CLOCK_FREQS_PTR.store(freqs, core::sync::atomic::Ordering::SeqCst);
} }
#[cfg(not(feature = "_dual-core"))] #[cfg(not(feature = "_dual-core"))]

View File

@ -9,6 +9,7 @@ SECTIONS
{ {
.ram_d3 : .ram_d3 :
{ {
*(.ram_d3.shared_data)
*(.ram_d3) *(.ram_d3)
} > RAM_D3 } > RAM_D3
} }

View File

@ -10,7 +10,7 @@ use embassy_stm32::SharedData;
use embassy_time::Timer; use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
#[link_section = ".ram_d3"] #[link_section = ".ram_d3.shared_data"]
static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
#[embassy_executor::main] #[embassy_executor::main]

View File

@ -9,6 +9,7 @@ SECTIONS
{ {
.ram_d3 : .ram_d3 :
{ {
*(.ram_d3.shared_data)
*(.ram_d3) *(.ram_d3)
} > RAM_D3 } > RAM_D3
} }

View File

@ -10,7 +10,7 @@ use embassy_stm32::SharedData;
use embassy_time::Timer; use embassy_time::Timer;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
#[link_section = ".ram_d3"] #[link_section = ".ram_d3.shared_data"]
static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
#[embassy_executor::main] #[embassy_executor::main]