@@ -58,11 +58,10 @@ use core::arch::asm;
58
58
use core:: marker:: PhantomData ;
59
59
use core:: sync:: atomic:: { compiler_fence, Ordering } ;
60
60
61
- use cortex_m:: peripheral:: SCB ;
62
- use embassy_executor:: * ;
63
-
64
61
use crate :: interrupt;
65
62
use crate :: time_driver:: { get_driver, RtcDriver } ;
63
+ use cortex_m:: peripheral:: SCB ;
64
+ use embassy_executor:: * ;
66
65
67
66
const THREAD_PENDER : usize = usize:: MAX ;
68
67
@@ -98,10 +97,22 @@ pub(crate) unsafe fn on_wakeup_irq() {
98
97
}
99
98
100
99
/// Configure STOP mode with RTC.
100
+ #[ cfg( all( feature = "low-power" , not( any( stm32wb) ) ) ) ]
101
101
pub fn stop_with_rtc ( rtc : & ' static Rtc ) {
102
102
unsafe { EXECUTOR . as_mut ( ) . unwrap ( ) } . stop_with_rtc ( rtc)
103
103
}
104
104
105
+ /// Configure STOP mode with RTC and HSEM. The hardware semaphore is needed for configuring the coprocessor
106
+ #[ cfg( all( feature = "low-power" , any( stm32wb) ) ) ]
107
+ pub fn stop_with_rtc_and_hsem (
108
+ rtc : & ' static Rtc ,
109
+ hsem : & ' static mut crate :: hsem:: HardwareSemaphore < ' static , crate :: peripherals:: HSEM > ,
110
+ ) {
111
+ let exec = unsafe { EXECUTOR . as_mut ( ) . unwrap ( ) } ;
112
+ exec. set_hsem ( hsem) ;
113
+ exec. stop_with_rtc ( rtc)
114
+ }
115
+
105
116
/// Get whether the core is ready to enter the given stop mode.
106
117
///
107
118
/// This will return false if some peripheral driver is in use that
@@ -124,10 +135,10 @@ pub enum StopMode {
124
135
Stop2 ,
125
136
}
126
137
127
- #[ cfg( any( stm32l4, stm32l5, stm32u5, stm32u0) ) ]
138
+ #[ cfg( any( stm32l4, stm32l5, stm32u5, stm32u0, stm32wb ) ) ]
128
139
use stm32_metapac:: pwr:: vals:: Lpms ;
129
140
130
- #[ cfg( any( stm32l4, stm32l5, stm32u5, stm32u0) ) ]
141
+ #[ cfg( any( stm32l4, stm32l5, stm32u5, stm32u0, stm32wb ) ) ]
131
142
impl Into < Lpms > for StopMode {
132
143
fn into ( self ) -> Lpms {
133
144
match self {
@@ -152,6 +163,12 @@ pub struct Executor {
152
163
not_send : PhantomData < * mut ( ) > ,
153
164
scb : SCB ,
154
165
time_driver : & ' static RtcDriver ,
166
+
167
+ #[ cfg( all( feature = "low-power" , any( stm32wb) ) ) ]
168
+ /// Special treatment of coprocessor requires a hardware semaphore
169
+ hsem : embassy_sync:: blocking_mutex:: NoopMutex <
170
+ core:: cell:: Cell < Option < & ' static mut crate :: hsem:: HardwareSemaphore < ' static , crate :: peripherals:: HSEM > > > ,
171
+ > ,
155
172
}
156
173
157
174
impl Executor {
@@ -165,6 +182,8 @@ impl Executor {
165
182
not_send : PhantomData ,
166
183
scb : cortex_m:: Peripherals :: steal ( ) . SCB ,
167
184
time_driver : get_driver ( ) ,
185
+ #[ cfg( all( feature = "low-power" , any( stm32wb) ) ) ]
186
+ hsem : embassy_sync:: blocking_mutex:: NoopMutex :: new ( core:: cell:: Cell :: default ( ) ) ,
168
187
} ) ;
169
188
170
189
let executor = EXECUTOR . as_mut ( ) . unwrap ( ) ;
@@ -178,6 +197,15 @@ impl Executor {
178
197
trace ! ( "low power: resume" ) ;
179
198
}
180
199
200
+ #[ cfg( all( feature = "low-power" , any( stm32wb) ) ) ]
201
+ pub ( self ) fn set_hsem (
202
+ & mut self ,
203
+ hsem : & ' static mut crate :: hsem:: HardwareSemaphore < ' static , crate :: peripherals:: HSEM > ,
204
+ ) {
205
+ assert ! ( self . hsem. lock( |x| x. replace( Some ( hsem) ) ) . is_none( ) ) ;
206
+ trace ! ( "low power: hsem configured" ) ;
207
+ }
208
+
181
209
pub ( self ) fn stop_with_rtc ( & mut self , rtc : & ' static Rtc ) {
182
210
self . time_driver . set_rtc ( rtc) ;
183
211
@@ -198,7 +226,17 @@ impl Executor {
198
226
199
227
#[ allow( unused_variables) ]
200
228
fn configure_stop ( & mut self , stop_mode : StopMode ) {
201
- #[ cfg( any( stm32l4, stm32l5, stm32u5, stm32u0) ) ]
229
+ #[ cfg( all( feature = "low-power" , any( stm32wb) ) ) ]
230
+ {
231
+ // Special treatment for MCUs with a coprocessor
232
+ unsafe {
233
+ self . hsem . lock_mut ( |x| {
234
+ crate :: rcc:: low_power:: stm32wb_configure_clocks_enter_stop_mode ( x. get_mut ( ) . as_mut ( ) . unwrap ( ) ) ;
235
+ } ) ;
236
+ }
237
+ }
238
+
239
+ #[ cfg( any( stm32l4, stm32l5, stm32u5, stm32u0, stm32wb) ) ]
202
240
crate :: pac:: PWR . cr1 ( ) . modify ( |m| m. set_lpms ( stop_mode. into ( ) ) ) ;
203
241
#[ cfg( stm32h5) ]
204
242
crate :: pac:: PWR . pmcr ( ) . modify ( |v| {
@@ -263,6 +301,15 @@ impl Executor {
263
301
executor. inner . poll ( ) ;
264
302
self . configure_pwr ( ) ;
265
303
asm ! ( "wfe" ) ;
304
+
305
+ #[ cfg( all( feature = "low-power" , any( stm32wb) ) ) ]
306
+ {
307
+ // Special treatment for MCUs with a coprocessor
308
+ self . hsem . lock_mut ( |x|
309
+
310
+ // Inentionally not calling from a critical section, as the critical section is handled internally
311
+ crate :: rcc:: low_power:: stm32wb_configure_clocks_exit_stop_mode ( x. get_mut ( ) . as_mut ( ) . unwrap ( ) ) ) ;
312
+ }
266
313
} ;
267
314
}
268
315
}
0 commit comments