stm32wl55: abscond with HSEM 3 for reset locking so only one core issues the reset

This commit is contained in:
liebman
2025-12-26 14:29:18 -08:00
parent 778edb2816
commit 65b6fc4658
4 changed files with 32 additions and 11 deletions

View File

@@ -80,9 +80,12 @@ impl CoreId {
}
}
#[cfg(not(all(stm32wb, feature = "low-power")))]
#[cfg(all(not(all(stm32wb, feature = "low-power")), not(stm32wl5x)))]
const PUB_CHANNELS: usize = 6;
#[cfg(stm32wl5x)]
const PUB_CHANNELS: usize = 5;
#[cfg(all(stm32wb, feature = "low-power"))]
const PUB_CHANNELS: usize = 4;
@@ -273,7 +276,7 @@ impl<T: Instance> HardwareSemaphore<T> {
[
HardwareSemaphoreChannel::new(1),
HardwareSemaphoreChannel::new(2),
#[cfg(not(all(stm32wb, feature = "low-power")))]
#[cfg(all(not(all(stm32wb, feature = "low-power")), not(stm32wl5x)))]
HardwareSemaphoreChannel::new(3),
#[cfg(not(all(stm32wb, feature = "low-power")))]
HardwareSemaphoreChannel::new(4),

View File

@@ -278,7 +278,7 @@ pub struct Ipcc {
}
impl Ipcc {
/// Creates a new HardwareSemaphore instance.
/// Creates a new Ipcc instance.
#[cfg(not(feature = "_core-cm0p"))]
pub fn new<'d>(
_peripheral: Peri<'d, crate::peripherals::IPCC>,
@@ -302,7 +302,7 @@ impl Ipcc {
Self { _private: () }
}
/// Creates a new HardwareSemaphore instance.
/// Creates a new Ipcc instance.
#[cfg(feature = "_core-cm0p")]
pub fn new<'d>(
_peripheral: Peri<'d, crate::peripherals::IPCC>,

View File

@@ -222,6 +222,18 @@ impl RccInfo {
}
}
#[cfg(stm32wl5x)]
fn wait_for_lock(&self) -> crate::hsem::HardwareSemaphoreMutex<'_, crate::peripherals::HSEM> {
use crate::hsem::HardwareSemaphoreChannel;
use crate::peripherals::HSEM;
let mut sem = HardwareSemaphoreChannel::<HSEM>::new(3);
loop {
if let Some(lock) = sem.try_lock(0) {
return lock;
}
}
}
// TODO: should this be `unsafe`?
pub(crate) fn enable_and_reset_with_cs(&self, _cs: CriticalSection) {
if self.refcount_idx_or_0xff != 0xff {
@@ -253,14 +265,18 @@ impl RccInfo {
// on stm32wl5x each CPU has its own peripheral enable bits and if the othert CPU has enabled the peripheral we don;t want to reset it
// as that would reset the configuration that the other CPU has set up.
// TODO: race condition!
// we hold a hardware lock to prevent the other CPU from enabling the peripheral while we are resetting it.
#[cfg(stm32wl5x)]
if unsafe { !self.is_enabled_by_other_core() } {
unsafe {
let val = reset_ptr.read_volatile();
reset_ptr.write_volatile(val | 1u32 << self.reset_bit);
{
let lock = self.wait_for_lock();
if unsafe { !self.is_enabled_by_other_core() } {
unsafe {
let val = reset_ptr.read_volatile();
reset_ptr.write_volatile(val | 1u32 << self.reset_bit);
}
trace!("rcc: reset 0x{:x}:{}", self.enable_offset, self.enable_bit);
}
trace!("rcc: reset 0x{:x}:{}", self.enable_offset, self.enable_bit);
drop(lock);
}
}

View File

@@ -32,7 +32,9 @@ async fn main(_spawner: Spawner) {
#[cfg(feature = "stm32wb55rg")]
let [_channel1, _channel2, mut channel5, _channel6] = hsem.split();
#[cfg(not(feature = "stm32wb55rg"))]
#[cfg(feature = "stm32wl55jc")]
let [_channel1, _channel2, _channel4, mut channel5, _channel6] = hsem.split();
#[cfg(not(any(feature = "stm32wb55rg", feature = "stm32wl55jc")))]
let [_channel1, _channel2, _channel3, _channel4, mut channel5, _channel6] = hsem.split();
info!("Locking channel 5");