embassy_stm32/hsem/
mod.rs1use embassy_hal_internal::PeripheralType;
4
5use crate::pac;
6use crate::rcc::{self, RccPeripheral};
7use crate::Peri;
12
13#[derive(Debug)]
15pub enum HsemError {
16 LockFailed,
18}
19
20#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
24#[repr(u8)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub enum CoreId {
27 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
28 Core0 = 0x3,
30
31 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
32 Core1 = 0x1,
34
35 #[cfg(not(any(stm32h745, stm32h747, stm32h755, stm32h757)))]
36 Core0 = 0x4,
38
39 #[cfg(any(stm32wb, stm32wl))]
40 Core1 = 0x8,
42}
43
44#[inline(always)]
47pub fn get_current_coreid() -> CoreId {
48 let cpuid = unsafe { cortex_m::peripheral::CPUID::PTR.read_volatile().base.read() };
49 match (cpuid & 0x000000F0) >> 4 {
50 #[cfg(any(stm32wb, stm32wl))]
51 0x0 => CoreId::Core1,
52
53 #[cfg(not(any(stm32h745, stm32h747, stm32h755, stm32h757)))]
54 0x4 => CoreId::Core0,
55
56 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
57 0x4 => CoreId::Core1,
58
59 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
60 0x7 => CoreId::Core0,
61 _ => panic!("Unknown Cortex-M core"),
62 }
63}
64
65#[inline(always)]
67fn core_id_to_index(core: CoreId) -> usize {
68 match core {
69 CoreId::Core0 => 0,
70 #[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757, stm32wb, stm32wl))]
71 CoreId::Core1 => 1,
72 }
73}
74
75pub struct HardwareSemaphore<'d, T: Instance> {
77 _peri: Peri<'d, T>,
78}
79
80impl<'d, T: Instance> HardwareSemaphore<'d, T> {
81 pub fn new(peripheral: Peri<'d, T>) -> Self {
83 rcc::enable_and_reset::<T>();
84
85 HardwareSemaphore { _peri: peripheral }
86 }
87
88 pub fn two_step_lock(&mut self, sem_id: u8, process_id: u8) -> Result<(), HsemError> {
92 T::regs().r(sem_id as usize).write(|w| {
93 w.set_procid(process_id);
94 w.set_coreid(get_current_coreid() as u8);
95 w.set_lock(true);
96 });
97 let reg = T::regs().r(sem_id as usize).read();
98 match (
99 reg.lock(),
100 reg.coreid() == get_current_coreid() as u8,
101 reg.procid() == process_id,
102 ) {
103 (true, true, true) => Ok(()),
104 _ => Err(HsemError::LockFailed),
105 }
106 }
107
108 pub fn one_step_lock(&mut self, sem_id: u8) -> Result<(), HsemError> {
112 let reg = T::regs().rlr(sem_id as usize).read();
113 match (reg.lock(), reg.coreid() == get_current_coreid() as u8, reg.procid()) {
114 (false, true, 0) => Ok(()),
115 _ => Err(HsemError::LockFailed),
116 }
117 }
118
119 pub fn unlock(&mut self, sem_id: u8, process_id: u8) {
123 T::regs().r(sem_id as usize).write(|w| {
124 w.set_procid(process_id);
125 w.set_coreid(get_current_coreid() as u8);
126 w.set_lock(false);
127 });
128 }
129
130 pub fn unlock_all(&mut self, key: u16, core_id: u8) {
135 T::regs().cr().write(|w| {
136 w.set_key(key);
137 w.set_coreid(core_id);
138 });
139 }
140
141 pub fn is_semaphore_locked(&self, sem_id: u8) -> bool {
143 T::regs().r(sem_id as usize).read().lock()
144 }
145
146 pub fn set_clear_key(&mut self, key: u16) {
148 T::regs().keyr().modify(|w| w.set_key(key));
149 }
150
151 pub fn get_clear_key(&mut self) -> u16 {
153 T::regs().keyr().read().key()
154 }
155
156 pub fn enable_interrupt(&mut self, core_id: CoreId, sem_x: usize, enable: bool) {
158 T::regs()
159 .ier(core_id_to_index(core_id))
160 .modify(|w| w.set_ise(sem_x, enable));
161 }
162
163 pub fn is_interrupt_active(&mut self, core_id: CoreId, sem_x: usize) -> bool {
165 T::regs().isr(core_id_to_index(core_id)).read().isf(sem_x)
166 }
167
168 pub fn clear_interrupt(&mut self, core_id: CoreId, sem_x: usize) {
170 T::regs()
171 .icr(core_id_to_index(core_id))
172 .write(|w| w.set_isc(sem_x, false));
173 }
174}
175
176trait SealedInstance {
177 fn regs() -> pac::hsem::Hsem;
178}
179
180#[allow(private_bounds)]
182pub trait Instance: SealedInstance + PeripheralType + RccPeripheral + Send + 'static {}
183
184impl SealedInstance for crate::peripherals::HSEM {
185 fn regs() -> crate::pac::hsem::Hsem {
186 crate::pac::HSEM
187 }
188}
189impl Instance for crate::peripherals::HSEM {}