Skip to content

Commit 7c8831c

Browse files
committed
fix: core was not recognized and 1-step lock did not work
1 parent 9d62fba commit 7c8831c

File tree

1 file changed

+162
-62
lines changed

1 file changed

+162
-62
lines changed

embassy-stm32/src/hsem/mod.rs

Lines changed: 162 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -4,71 +4,166 @@ use embassy_hal_internal::PeripheralType;
44

55
use crate::pac;
66
use crate::rcc::RccPeripheral;
7-
// TODO: This code works for all HSEM implemenations except for the STM32WBA52/4/5xx MCUs.
7+
// TODO: This code works for all HSEM implementations except for the STM32WBA52/4/5xx MCUs.
88
// Those MCUs have a different HSEM implementation (Secure semaphore lock support,
99
// Privileged / unprivileged semaphore lock support, Semaphore lock protection via semaphore attribute),
1010
// which is not yet supported by this code.
1111
use crate::Peri;
1212

1313
/// HSEM error.
14-
#[derive(Debug)]
14+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
15+
#[repr(u8)]
16+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1517
pub enum HsemError {
1618
/// Locking the semaphore failed.
1719
LockFailed,
1820
}
1921

22+
/// HSEM identifier
23+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
24+
#[repr(u8)]
25+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26+
pub enum SemId {
27+
/// Semaphore 0
28+
Id0 = 0,
29+
/// Semaphore 1
30+
Id1 = 1,
31+
/// Semaphore 2
32+
Id2 = 2,
33+
/// Semaphore 3
34+
Id3 = 3,
35+
/// Semaphore 4
36+
Id4 = 4,
37+
/// Semaphore 5
38+
Id5 = 5,
39+
/// Semaphore 6
40+
Id6 = 6,
41+
/// Semaphore 7
42+
Id7 = 7,
43+
/// Semaphore 8
44+
Id8 = 8,
45+
/// Semaphore 9
46+
Id9 = 9,
47+
/// Semaphore 10
48+
Id10 = 10,
49+
/// Semaphore 11
50+
Id11 = 11,
51+
/// Semaphore 12
52+
Id12 = 12,
53+
/// Semaphore 13
54+
Id13 = 13,
55+
/// Semaphore 14
56+
Id14 = 14,
57+
/// Semaphore 15
58+
Id15 = 15,
59+
/// Semaphore 16
60+
Id16 = 16,
61+
/// Semaphore 17
62+
Id17 = 17,
63+
/// Semaphore 18
64+
Id18 = 18,
65+
/// Semaphore 19
66+
Id19 = 19,
67+
/// Semaphore 20
68+
Id20 = 20,
69+
/// Semaphore 21
70+
Id21 = 21,
71+
/// Semaphore 22
72+
Id22 = 22,
73+
/// Semaphore 23
74+
Id23 = 23,
75+
/// Semaphore 24
76+
Id24 = 24,
77+
/// Semaphore 25
78+
Id25 = 25,
79+
/// Semaphore 26
80+
Id26 = 26,
81+
/// Semaphore 27
82+
Id27 = 27,
83+
/// Semaphore 28
84+
Id28 = 28,
85+
/// Semaphore 29
86+
Id29 = 29,
87+
/// Semaphore 30
88+
Id30 = 30,
89+
/// Semaphore 31
90+
Id31 = 31,
91+
}
92+
93+
impl From<SemId> for usize {
94+
fn from(id: SemId) -> Self {
95+
id as usize
96+
}
97+
}
98+
2099
/// CPU core.
21100
/// The enum values are identical to the bus master IDs / core Ids defined for each
22101
/// chip family (i.e. stm32h747 see rm0399 table 95)
23102
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
24103
#[repr(u8)]
25104
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26105
pub enum CoreId {
27-
#[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
28-
/// Cortex-M7, core 1.
29-
Core0 = 0x3,
106+
/// Main processor
107+
Core0 = 0,
108+
/// Coprocessor
109+
Core1,
110+
}
30111

31-
#[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
32-
/// Cortex-M4, core 2.
33-
Core1 = 0x1,
112+
impl From<CoreId> for usize {
113+
fn from(core: CoreId) -> Self {
114+
core as usize
115+
}
116+
}
34117

35-
#[cfg(not(any(stm32h745, stm32h747, stm32h755, stm32h757)))]
36-
/// Cortex-M4, core 1
37-
Core0 = 0x4,
118+
/// The core ID used in the HSEM_RLRx register.
119+
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
120+
#[repr(u8)]
121+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
122+
pub enum RlrCoreId {
123+
#[cfg(any(stm32h7a3, stm32h7b3, stm32h7b0))]
124+
/// Cortex-M7, core 1. MASTERID = 1
125+
Core0 = 1,
38126

39-
#[cfg(any(stm32wb, stm32wl))]
40-
/// Cortex-M0+, core 2.
41-
Core1 = 0x8,
42-
}
127+
#[cfg(any(
128+
stm32h723, stm32h725, stm32h730, stm32h733, stm32h735, stm32h742, stm32h743, stm32h745, stm32h747, stm32h750,
129+
stm32h753, stm32h755, stm32h757,
130+
))]
131+
/// Cortex-M7, core 1. MASTERID = 3
132+
Core0 = 3,
43133

44-
/// Get the current core id
45-
/// This code assume that it is only executed on a Cortex-M M0+, M4 or M7 core.
46-
#[inline(always)]
47-
pub fn get_current_coreid() -> CoreId {
48-
let cpuid = unsafe { cortex_m::peripheral::CPUID::PTR.read_volatile().base.read() };
49-
match cpuid & 0x000000F0 {
50-
#[cfg(any(stm32wb, stm32wl))]
51-
0x0 => CoreId::Core1,
134+
#[cfg(any(stm32wb, stm32wl))]
135+
/// Cortex-M4, core 1
136+
Core0 = 4,
52137

53-
#[cfg(not(any(stm32h745, stm32h747, stm32h755, stm32h757)))]
54-
0x4 => CoreId::Core0,
138+
#[cfg(not(any(stm32wb, stm32wl, stm32h7a3, stm32h7b3, stm32h7b0)))]
139+
/// Cortex-M4, core 2
140+
Core1 = 1,
55141

56-
#[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
57-
0x4 => CoreId::Core1,
142+
#[cfg(any(stm32wb, stm32wl))]
143+
/// Cortex M0+, core 2
144+
Core1 = 8,
145+
}
58146

59-
#[cfg(any(stm32h745, stm32h747, stm32h755, stm32h757))]
60-
0x7 => CoreId::Core0,
61-
_ => panic!("Unknown Cortex-M core"),
147+
impl From<CoreId> for RlrCoreId {
148+
fn from(core: CoreId) -> Self {
149+
match core {
150+
CoreId::Core0 => RlrCoreId::Core0,
151+
CoreId::Core1 => RlrCoreId::Core1,
152+
}
62153
}
63154
}
64155

65-
/// Translates the core ID to an index into the interrupt registers.
66-
#[inline(always)]
67-
fn 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,
156+
impl CoreId {
157+
/// Returns the ID of the current running core.
158+
pub fn get_current() -> Self {
159+
#[cfg(any(
160+
all(stm32wl, not(feature = "_core-cm0p")),
161+
all(not(stm32wl), any(feature = "_core-cm7", not(feature = "_core-cm4"))),
162+
))]
163+
return CoreId::Core0;
164+
165+
#[cfg(any(all(not(stm32wl), feature = "_core-cm4"), all(stm32wl, feature = "_core-cm0p")))]
166+
return CoreId::Core1;
72167
}
73168
}
74169

@@ -86,16 +181,16 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
86181
/// Locks the semaphore.
87182
/// The 2-step lock procedure consists in a write to lock the semaphore, followed by a read to
88183
/// check if the lock has been successful, carried out from the HSEM_Rx register.
89-
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| {
184+
pub fn two_step_lock(&mut self, sem_id: SemId, process_id: u8) -> Result<(), HsemError> {
185+
T::regs().r(sem_id.into()).write(|w| {
91186
w.set_procid(process_id);
92-
w.set_coreid(get_current_coreid() as u8);
187+
w.set_coreid(RlrCoreId::from(CoreId::get_current()) as u8);
93188
w.set_lock(true);
94189
});
95-
let reg = T::regs().r(sem_id as usize).read();
190+
let reg = T::regs().r(sem_id.into()).read();
96191
match (
97192
reg.lock(),
98-
reg.coreid() == get_current_coreid() as u8,
193+
reg.coreid() == RlrCoreId::from(CoreId::get_current()) as u8,
99194
reg.procid() == process_id,
100195
) {
101196
(true, true, true) => Ok(()),
@@ -106,21 +201,28 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
106201
/// Locks the semaphore.
107202
/// The 1-step procedure consists in a read to lock and check the semaphore in a single step,
108203
/// carried out from the HSEM_RLRx register.
109-
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(()),
204+
pub fn one_step_lock(&mut self, sem_id: SemId) -> Result<(), HsemError> {
205+
let reg = T::regs().rlr(sem_id.into()).read();
206+
207+
match (
208+
reg.lock(),
209+
reg.coreid() == RlrCoreId::from(CoreId::get_current()) as u8,
210+
reg.procid(),
211+
) {
212+
(true, true, 0) => Ok(()),
113213
_ => Err(HsemError::LockFailed),
114214
}
115215
}
116216

117217
/// Unlocks the semaphore.
118218
/// Unlocking a semaphore is a protected process, to prevent accidental clearing by a AHB bus
119219
/// core ID or by a process not having the semaphore lock right.
120-
pub fn unlock(&mut self, sem_id: u8, process_id: u8) {
121-
T::regs().r(sem_id as usize).write(|w| {
220+
pub fn unlock(&mut self, sem_id: SemId, process_id: Option<u8>) {
221+
let process_id = process_id.unwrap_or(0);
222+
223+
T::regs().r(sem_id.into()).write(|w| {
122224
w.set_procid(process_id);
123-
w.set_coreid(get_current_coreid() as u8);
225+
w.set_coreid(RlrCoreId::from(CoreId::get_current()) as u8);
124226
w.set_lock(false);
125227
});
126228
}
@@ -129,16 +231,16 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
129231
/// All semaphores locked by a COREID can be unlocked at once by using the HSEM_CR
130232
/// register. Write COREID and correct KEY value in HSEM_CR. All locked semaphores with a
131233
/// matching COREID are unlocked, and may generate an interrupt when enabled.
132-
pub fn unlock_all(&mut self, key: u16, core_id: u8) {
234+
pub fn unlock_all(&mut self, key: u16, core_id: CoreId) {
133235
T::regs().cr().write(|w| {
134236
w.set_key(key);
135-
w.set_coreid(core_id);
237+
w.set_coreid(RlrCoreId::from(core_id) as u8);
136238
});
137239
}
138240

139241
/// Checks if the semaphore is locked.
140-
pub fn is_semaphore_locked(&self, sem_id: u8) -> bool {
141-
T::regs().r(sem_id as usize).read().lock()
242+
pub fn is_semaphore_locked(&self, sem_id: SemId) -> bool {
243+
T::regs().r(sem_id.into()).read().lock()
142244
}
143245

144246
/// Sets the clear (unlock) key
@@ -152,22 +254,20 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
152254
}
153255

154256
/// Sets the interrupt enable bit for the semaphore.
155-
pub fn enable_interrupt(&mut self, core_id: CoreId, sem_x: usize, enable: bool) {
257+
pub fn enable_interrupt(&mut self, core_id: CoreId, sem_id: SemId, enable: bool) {
156258
T::regs()
157-
.ier(core_id_to_index(core_id))
158-
.modify(|w| w.set_ise(sem_x, enable));
259+
.ier(core_id.into())
260+
.modify(|w| w.set_ise(sem_id.into(), enable));
159261
}
160262

161263
/// Gets the interrupt flag for the semaphore.
162-
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)
264+
pub fn is_interrupt_active(&mut self, core_id: CoreId, sem_id: SemId) -> bool {
265+
T::regs().isr(core_id.into()).read().isf(sem_id.into())
164266
}
165267

166268
/// Clears the interrupt flag for the semaphore.
167-
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));
269+
pub fn clear_interrupt(&mut self, core_id: CoreId, sem_id: SemId) {
270+
T::regs().icr(core_id.into()).write(|w| w.set_isc(sem_id.into(), false));
171271
}
172272
}
173273

0 commit comments

Comments
 (0)