1
1
//! Hardware Semaphore (HSEM)
2
2
3
3
use embassy_hal_internal:: PeripheralType ;
4
+ use stm32_metapac:: hsem:: regs:: Rlr ;
4
5
5
6
use crate :: pac;
6
7
use crate :: rcc:: RccPeripheral ;
7
- // TODO: This code works for all HSEM implemenations except for the STM32WBA52/4/5xx MCUs.
8
+ // TODO: This code works for all HSEM implementations except for the STM32WBA52/4/5xx MCUs.
8
9
// Those MCUs have a different HSEM implementation (Secure semaphore lock support,
9
10
// Privileged / unprivileged semaphore lock support, Semaphore lock protection via semaphore attribute),
10
11
// which is not yet supported by this code.
@@ -17,47 +18,135 @@ pub enum HsemError {
17
18
LockFailed ,
18
19
}
19
20
21
+ /// HSEM identifier
22
+ /// Copied from `hw_conf.h` of the STM32WB55 WPAN stack
23
+ #[ cfg( any( stm32wb) ) ]
24
+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Hash ) ]
25
+ #[ repr( u8 ) ]
26
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
27
+ pub enum HsemIdStm32Wb {
28
+ /// Semaphore to lock the RNG access
29
+ Rng = 0 ,
30
+ /// Semaphore to lock the PKA access
31
+ Pka = 1 ,
32
+ /// Semaphore to lock the FLASH access
33
+ Flash = 2 ,
34
+ /// Semaphore to lock the RCC access
35
+ Rcc = 3 ,
36
+ /// Semaphore to synchronize the entry stop mode
37
+ EntryStopMode = 4 ,
38
+ /// Semaphore to lock the Clk48 access
39
+ Clk48Config = 5 ,
40
+ /// Semaphore to sync blockwise flash access CPU1
41
+ BlockFlashRequestByCpu1 = 6 ,
42
+ /// Semaphore to sync blockwise flash access CPU2
43
+ BlockFlashRequestByCpu2 = 7 ,
44
+ /// Semaphore to lock the BLE NVM access
45
+ BleNvmSram = 8 ,
46
+ /// Semaphore to lock the Thread NVM access
47
+ ThreadNvmSram = 9 ,
48
+ }
49
+
50
+ #[ cfg( any( stm32wb) ) ]
51
+ impl From < HsemIdStm32Wb > for u8 {
52
+ fn from ( id : HsemIdStm32Wb ) -> Self {
53
+ id as u8
54
+ }
55
+ }
56
+
20
57
/// CPU core.
21
58
/// The enum values are identical to the bus master IDs / core Ids defined for each
22
59
/// chip family (i.e. stm32h747 see rm0399 table 95)
23
60
#[ derive( Debug , PartialEq , Eq , Clone , Copy , Hash ) ]
24
61
#[ repr( u8 ) ]
25
62
#[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
26
63
pub enum CoreId {
64
+ /// Main processor
65
+ Core0 ,
66
+ /// Coprocessor
67
+ Core1 ,
68
+ }
69
+
70
+ /// The core ID used in the HSEM_RLRx register.
71
+ #[ derive( Debug , PartialEq , Eq , Clone , Copy , Hash ) ]
72
+ #[ repr( u8 ) ]
73
+ #[ cfg_attr( feature = "defmt" , derive( defmt:: Format ) ) ]
74
+ pub enum RlrCoreId {
75
+ /// Main processor (Cortex M4) core ID
76
+ #[ cfg( any( stm32wb, stm32wl) ) ]
77
+ Core0 = 0x4 ,
78
+
79
+ /// Main processor (Cortex M7) core ID
27
80
#[ cfg( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ]
28
- /// Cortex-M7, core 1.
29
81
Core0 = 0x3 ,
30
82
83
+ /// Coprocessor (Cortex M0) core ID
84
+ #[ cfg( any( stm32wb, stm32wl) ) ]
85
+ Core1 = 0x8 ,
86
+
87
+ /// Coprocessor (Cortex M4) core ID
31
88
#[ cfg( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ]
32
- /// Cortex-M4, core 2.
33
89
Core1 = 0x1 ,
90
+ }
34
91
35
- #[ cfg( not( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ) ]
36
- /// Cortex-M4, core 1
37
- Core0 = 0x4 ,
92
+ impl TryFrom < u8 > for RlrCoreId {
93
+ type Error = ( ) ;
38
94
39
- #[ cfg( any( stm32wb, stm32wl) ) ]
40
- /// Cortex-M0+, core 2.
41
- Core1 = 0x8 ,
95
+ fn try_from ( value : u8 ) -> Result < Self , Self :: Error > {
96
+ #[ cfg( any( stm32wb, stm32wl) ) ]
97
+ match value {
98
+ 0x4 => Ok ( RlrCoreId :: Core0 ) ,
99
+ 0x8 => Ok ( RlrCoreId :: Core1 ) ,
100
+ _ => Err ( ( ) ) ,
101
+ }
102
+
103
+ #[ cfg( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ]
104
+ match value {
105
+ 0x3 => Ok ( RlrCoreId :: Core0 ) ,
106
+ 0x1 => Ok ( RlrCoreId :: Core1 ) ,
107
+ _ => Err ( ( ) ) ,
108
+ }
109
+ }
42
110
}
43
111
44
- /// Get the current core id
45
- /// This code assume that it is only executed on a Cortex-M M0+, M4 or M7 core.
112
+ impl From < CoreId > for RlrCoreId {
113
+ fn from ( core : CoreId ) -> Self {
114
+ match core {
115
+ CoreId :: Core0 => RlrCoreId :: Core0 ,
116
+ CoreId :: Core1 => RlrCoreId :: Core1 ,
117
+ }
118
+ }
119
+ }
120
+
121
+ /// Get the current core id.
46
122
#[ inline( always) ]
47
123
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 ,
124
+ const CPUID_PARTNO_MASK : u32 = 0x0000FFF0 ;
125
+ // From the arm developer manual
126
+ // https://developer.arm.com/documentation/ddi0439/b/System-Control/Register-descriptions/CPUID-Base-Register--CPUID
127
+ #[ allow( dead_code) ]
128
+ const CPUID_PARTNO_CORTEX_M4 : u32 = 0x0000C240 ;
129
+ #[ allow( dead_code) ]
130
+ const CPUID_PARTNO_CORTEX_M7 : u32 = 0x0000C270 ;
131
+ #[ allow( dead_code) ]
132
+ const CPUID_PARTNO_CORTEX_M0 : u32 = 0x0000C600 ;
133
+ // const CPUID_PARTNO_CORTEX_M33: u32 = 0x0000D210;
52
134
53
- #[ cfg( not( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ) ]
54
- 0x4 => CoreId :: Core0 ,
135
+ let cpuid = unsafe { cortex_m:: peripheral:: CPUID :: PTR . read_volatile ( ) . base . read ( ) } ;
55
136
56
- #[ cfg( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ]
57
- 0x4 => CoreId :: Core1 ,
137
+ #[ cfg( any( stm32wb, stm32wl) ) ]
138
+ // Cortex M4 as main processor and Cortex M0 as coprocessor
139
+ match cpuid & CPUID_PARTNO_MASK {
140
+ CPUID_PARTNO_CORTEX_M4 => CoreId :: Core0 ,
141
+ CPUID_PARTNO_CORTEX_M0 => CoreId :: Core1 ,
142
+ _ => panic ! ( "Unknown Cortex-M core" ) ,
143
+ }
58
144
59
- #[ cfg( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ]
60
- 0x7 => CoreId :: Core0 ,
145
+ #[ cfg( any( stm32h745, stm32h747, stm32h755, stm32h757) ) ]
146
+ // Cortex M7 as main processor and Cortex M4 as coprocessor
147
+ match cpuid & CPUID_PARTNO_MASK {
148
+ CPUID_PARTNO_CORTEX_M7 => CoreId :: Core0 ,
149
+ CPUID_PARTNO_CORTEX_M4 => CoreId :: Core1 ,
61
150
_ => panic ! ( "Unknown Cortex-M core" ) ,
62
151
}
63
152
}
@@ -89,13 +178,13 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
89
178
pub fn two_step_lock ( & mut self , sem_id : u8 , process_id : u8 ) -> Result < ( ) , HsemError > {
90
179
T :: regs ( ) . r ( sem_id as usize ) . write ( |w| {
91
180
w. set_procid ( process_id) ;
92
- w. set_coreid ( get_current_coreid ( ) as u8 ) ;
181
+ w. set_coreid ( RlrCoreId :: from ( get_current_coreid ( ) ) as u8 ) ;
93
182
w. set_lock ( true ) ;
94
183
} ) ;
95
184
let reg = T :: regs ( ) . r ( sem_id as usize ) . read ( ) ;
96
185
match (
97
186
reg. lock ( ) ,
98
- reg. coreid ( ) == get_current_coreid ( ) as u8 ,
187
+ reg. coreid ( ) == RlrCoreId :: from ( get_current_coreid ( ) ) as u8 ,
99
188
reg. procid ( ) == process_id,
100
189
) {
101
190
( true , true , true ) => Ok ( ( ) ) ,
@@ -108,8 +197,13 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
108
197
/// carried out from the HSEM_RLRx register.
109
198
pub fn one_step_lock ( & mut self , sem_id : u8 ) -> Result < ( ) , HsemError > {
110
199
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 ( ( ) ) ,
200
+
201
+ match (
202
+ reg. lock ( ) ,
203
+ reg. coreid ( ) == RlrCoreId :: from ( get_current_coreid ( ) ) as u8 ,
204
+ reg. procid ( ) ,
205
+ ) {
206
+ ( true , true , 0 ) => Ok ( ( ) ) ,
113
207
_ => Err ( HsemError :: LockFailed ) ,
114
208
}
115
209
}
@@ -120,7 +214,7 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
120
214
pub fn unlock ( & mut self , sem_id : u8 , process_id : u8 ) {
121
215
T :: regs ( ) . r ( sem_id as usize ) . write ( |w| {
122
216
w. set_procid ( process_id) ;
123
- w. set_coreid ( get_current_coreid ( ) as u8 ) ;
217
+ w. set_coreid ( RlrCoreId :: from ( get_current_coreid ( ) ) as u8 ) ;
124
218
w. set_lock ( false ) ;
125
219
} ) ;
126
220
}
@@ -129,10 +223,10 @@ impl<'d, T: Instance> HardwareSemaphore<'d, T> {
129
223
/// All semaphores locked by a COREID can be unlocked at once by using the HSEM_CR
130
224
/// register. Write COREID and correct KEY value in HSEM_CR. All locked semaphores with a
131
225
/// matching COREID are unlocked, and may generate an interrupt when enabled.
132
- pub fn unlock_all ( & mut self , key : u16 , core_id : u8 ) {
226
+ pub fn unlock_all ( & mut self , key : u16 , core_id : CoreId ) {
133
227
T :: regs ( ) . cr ( ) . write ( |w| {
134
228
w. set_key ( key) ;
135
- w. set_coreid ( core_id) ;
229
+ w. set_coreid ( RlrCoreId :: from ( core_id) as u8 ) ;
136
230
} ) ;
137
231
}
138
232
0 commit comments