@@ -4,71 +4,178 @@ use embassy_hal_internal::PeripheralType;
4
4
5
5
use crate :: pac;
6
6
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.
8
8
// Those MCUs have a different HSEM implementation (Secure semaphore lock support,
9
9
// Privileged / unprivileged semaphore lock support, Semaphore lock protection via semaphore attribute),
10
10
// which is not yet supported by this code.
11
11
use crate :: Peri ;
12
12
13
13
/// HSEM error.
14
- #[ derive( Debug ) ]
14
+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Hash ) ]
15
+ #[ repr( u8 ) ]
16
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
15
17
pub enum HsemError {
16
18
/// Locking the semaphore failed.
17
19
LockFailed ,
18
20
}
19
21
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
+
20
99
/// CPU core.
21
100
/// The enum values are identical to the bus master IDs / core Ids defined for each
22
101
/// chip family (i.e. stm32h747 see rm0399 table 95)
23
102
#[ derive( Debug , PartialEq , Eq , Clone , Copy , Hash ) ]
24
103
#[ repr( u8 ) ]
25
104
#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
26
105
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
+ }
30
111
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
+ }
34
117
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 ,
38
126
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 ,
43
133
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 ,
52
137
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 ,
55
141
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
+ }
58
146
59
- #[ cfg( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ]
60
- 0x7 => CoreId :: Core0 ,
61
- _ => panic ! ( "Unknown Cortex-M core" ) ,
147
+ impl From < CoreId > for RlrCoreId {
148
+ #[ rustfmt:: skip]
149
+ fn from ( core : CoreId ) -> Self {
150
+ match core {
151
+ #[ cfg( any(
152
+ any(
153
+ stm32h723, stm32h725, stm32h730, stm32h733, stm32h735, stm32h742, stm32h743, stm32h745, stm32h747, stm32h750,
154
+ stm32h753, stm32h755, stm32h757,
155
+ ) ,
156
+ any( stm32wb, stm32wl) )
157
+ ) ]
158
+ CoreId :: Core0 => RlrCoreId :: Core0 ,
159
+ #[ cfg( any(
160
+ not( any( stm32wb, stm32wl, stm32h7a3, stm32h7b3, stm32h7b0) ) ,
161
+ any( stm32wb, stm32wl) )
162
+ ) ]
163
+ CoreId :: Core1 => RlrCoreId :: Core1 ,
164
+ }
62
165
}
63
166
}
64
167
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 ,
168
+ impl CoreId {
169
+ /// Returns the ID of the current running core.
170
+ pub fn get_current ( ) -> Self {
171
+ #[ cfg( any(
172
+ all( stm32wl, not( feature = "_core-cm0p" ) ) ,
173
+ all( not( stm32wl) , any( feature = "_core-cm7" , not( feature = "_core-cm4" ) ) ) ,
174
+ ) ) ]
175
+ return CoreId :: Core0 ;
176
+
177
+ #[ cfg( any( all( not( stm32wl) , feature = "_core-cm4" ) , all( stm32wl, feature = "_core-cm0p" ) ) ) ]
178
+ return CoreId :: Core1 ;
72
179
}
73
180
}
74
181
@@ -86,16 +193,16 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
86
193
/// Locks the semaphore.
87
194
/// The 2-step lock procedure consists in a write to lock the semaphore, followed by a read to
88
195
/// 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| {
196
+ pub fn two_step_lock ( & mut self , sem_id : SemId , process_id : u8 ) -> Result < ( ) , HsemError > {
197
+ T :: regs ( ) . r ( sem_id. into ( ) ) . write ( |w| {
91
198
w. set_procid ( process_id) ;
92
- w. set_coreid ( get_current_coreid ( ) as u8 ) ;
199
+ w. set_coreid ( RlrCoreId :: from ( CoreId :: get_current ( ) ) as u8 ) ;
93
200
w. set_lock ( true ) ;
94
201
} ) ;
95
- let reg = T :: regs ( ) . r ( sem_id as usize ) . read ( ) ;
202
+ let reg = T :: regs ( ) . r ( sem_id. into ( ) ) . read ( ) ;
96
203
match (
97
204
reg. lock ( ) ,
98
- reg. coreid ( ) == get_current_coreid ( ) as u8 ,
205
+ reg. coreid ( ) == RlrCoreId :: from ( CoreId :: get_current ( ) ) as u8 ,
99
206
reg. procid ( ) == process_id,
100
207
) {
101
208
( true , true , true ) => Ok ( ( ) ) ,
@@ -106,21 +213,28 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
106
213
/// Locks the semaphore.
107
214
/// The 1-step procedure consists in a read to lock and check the semaphore in a single step,
108
215
/// 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 ( ( ) ) ,
216
+ pub fn one_step_lock ( & mut self , sem_id : SemId ) -> Result < ( ) , HsemError > {
217
+ let reg = T :: regs ( ) . rlr ( sem_id. into ( ) ) . read ( ) ;
218
+
219
+ match (
220
+ reg. lock ( ) ,
221
+ reg. coreid ( ) == RlrCoreId :: from ( CoreId :: get_current ( ) ) as u8 ,
222
+ reg. procid ( ) ,
223
+ ) {
224
+ ( true , true , 0 ) => Ok ( ( ) ) ,
113
225
_ => Err ( HsemError :: LockFailed ) ,
114
226
}
115
227
}
116
228
117
229
/// Unlocks the semaphore.
118
230
/// Unlocking a semaphore is a protected process, to prevent accidental clearing by a AHB bus
119
231
/// 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| {
232
+ pub fn unlock ( & mut self , sem_id : SemId , process_id : Option < u8 > ) {
233
+ let process_id = process_id. unwrap_or ( 0 ) ;
234
+
235
+ T :: regs ( ) . r ( sem_id. into ( ) ) . write ( |w| {
122
236
w. set_procid ( process_id) ;
123
- w. set_coreid ( get_current_coreid ( ) as u8 ) ;
237
+ w. set_coreid ( RlrCoreId :: from ( CoreId :: get_current ( ) ) as u8 ) ;
124
238
w. set_lock ( false ) ;
125
239
} ) ;
126
240
}
@@ -129,16 +243,16 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
129
243
/// All semaphores locked by a COREID can be unlocked at once by using the HSEM_CR
130
244
/// register. Write COREID and correct KEY value in HSEM_CR. All locked semaphores with a
131
245
/// matching COREID are unlocked, and may generate an interrupt when enabled.
132
- pub fn unlock_all ( & mut self , key : u16 , core_id : u8 ) {
246
+ pub fn unlock_all ( & mut self , key : u16 , core_id : CoreId ) {
133
247
T :: regs ( ) . cr ( ) . write ( |w| {
134
248
w. set_key ( key) ;
135
- w. set_coreid ( core_id) ;
249
+ w. set_coreid ( RlrCoreId :: from ( core_id) as u8 ) ;
136
250
} ) ;
137
251
}
138
252
139
253
/// 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 ( )
254
+ pub fn is_semaphore_locked ( & self , sem_id : SemId ) -> bool {
255
+ T :: regs ( ) . r ( sem_id. into ( ) ) . read ( ) . lock ( )
142
256
}
143
257
144
258
/// Sets the clear (unlock) key
@@ -152,22 +266,20 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
152
266
}
153
267
154
268
/// Sets the interrupt enable bit for the semaphore.
155
- pub fn enable_interrupt ( & mut self , core_id : CoreId , sem_x : usize , enable : bool ) {
269
+ pub fn enable_interrupt ( & mut self , core_id : CoreId , sem_id : SemId , enable : bool ) {
156
270
T :: regs ( )
157
- . ier ( core_id_to_index ( core_id) )
158
- . modify ( |w| w. set_ise ( sem_x , enable) ) ;
271
+ . ier ( core_id. into ( ) )
272
+ . modify ( |w| w. set_ise ( sem_id . into ( ) , enable) ) ;
159
273
}
160
274
161
275
/// 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 )
276
+ pub fn is_interrupt_active ( & mut self , core_id : CoreId , sem_id : SemId ) -> bool {
277
+ T :: regs ( ) . isr ( core_id. into ( ) ) . read ( ) . isf ( sem_id . into ( ) )
164
278
}
165
279
166
280
/// 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 ) ) ;
281
+ pub fn clear_interrupt ( & mut self , core_id : CoreId , sem_id : SemId ) {
282
+ T :: regs ( ) . icr ( core_id. into ( ) ) . write ( |w| w. set_isc ( sem_id. into ( ) , false ) ) ;
171
283
}
172
284
}
173
285
0 commit comments