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