aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-12-16 17:09:55 +0000
committerGitHub <[email protected]>2025-12-16 17:09:55 +0000
commit49040dfb760d54067e5d2e1b6d490002c0c04a24 (patch)
treed3a8d75991d6f9c5a3936c578dde5fdbf4557f50 /embassy-stm32
parentcf2bbdd9138430fe401a3bcef1a3c9afef851652 (diff)
parent98eda74661ef0dc2b11a4b2a4df10c0f50dc5ae6 (diff)
Merge pull request #5062 from xoviat/stm32wb-stop
low-power: stop cpu2 on stm32wb
Diffstat (limited to 'embassy-stm32')
-rw-r--r--embassy-stm32/src/hsem/mod.rs27
-rw-r--r--embassy-stm32/src/low_power.rs46
-rw-r--r--embassy-stm32/src/rcc/mod.rs4
3 files changed, 61 insertions, 16 deletions
diff --git a/embassy-stm32/src/hsem/mod.rs b/embassy-stm32/src/hsem/mod.rs
index b5fa3c897..e5c68acbd 100644
--- a/embassy-stm32/src/hsem/mod.rs
+++ b/embassy-stm32/src/hsem/mod.rs
@@ -94,17 +94,14 @@ pub struct HardwareSemaphoreInterruptHandler<T: Instance> {
94impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for HardwareSemaphoreInterruptHandler<T> { 94impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for HardwareSemaphoreInterruptHandler<T> {
95 unsafe fn on_interrupt() { 95 unsafe fn on_interrupt() {
96 let core_id = CoreId::current(); 96 let core_id = CoreId::current();
97 let isr = T::regs().isr(core_id.to_index()).read();
97 98
98 for number in 0..5 { 99 for number in 0..5 {
99 if T::regs().isr(core_id.to_index()).read().isf(number as usize) { 100 if isr.isf(number as usize) {
100 T::regs() 101 T::regs()
101 .icr(core_id.to_index()) 102 .icr(core_id.to_index())
102 .write(|w| w.set_isc(number as usize, true)); 103 .write(|w| w.set_isc(number as usize, true));
103 104
104 T::regs()
105 .ier(core_id.to_index())
106 .modify(|w| w.set_ise(number as usize, false));
107
108 T::state().waker_for(number).wake(); 105 T::state().waker_for(number).wake();
109 } 106 }
110 } 107 }
@@ -120,6 +117,18 @@ pub struct HardwareSemaphoreMutex<'a, T: Instance> {
120 117
121impl<'a, T: Instance> Drop for HardwareSemaphoreMutex<'a, T> { 118impl<'a, T: Instance> Drop for HardwareSemaphoreMutex<'a, T> {
122 fn drop(&mut self) { 119 fn drop(&mut self) {
120 let core_id = CoreId::current();
121
122 T::regs()
123 .icr(core_id.to_index())
124 .write(|w| w.set_isc(self.index as usize, true));
125
126 critical_section::with(|_| {
127 T::regs()
128 .ier(core_id.to_index())
129 .modify(|w| w.set_ise(self.index as usize, false));
130 });
131
123 HardwareSemaphoreChannel::<'a, T> { 132 HardwareSemaphoreChannel::<'a, T> {
124 index: self.index, 133 index: self.index,
125 _lifetime: PhantomData, 134 _lifetime: PhantomData,
@@ -156,9 +165,11 @@ impl<'a, T: Instance> HardwareSemaphoreChannel<'a, T> {
156 165
157 compiler_fence(Ordering::SeqCst); 166 compiler_fence(Ordering::SeqCst);
158 167
159 T::regs() 168 critical_section::with(|_| {
160 .ier(core_id.to_index()) 169 T::regs()
161 .modify(|w| w.set_ise(self.index as usize, true)); 170 .ier(core_id.to_index())
171 .modify(|w| w.set_ise(self.index as usize, true));
172 });
162 173
163 match self.try_lock(process_id) { 174 match self.try_lock(process_id) {
164 Some(mutex) => Poll::Ready(mutex), 175 Some(mutex) => Poll::Ready(mutex),
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 2388abe3c..0cdd7789e 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -124,9 +124,9 @@ impl Into<Lpms> for StopMode {
124 fn into(self) -> Lpms { 124 fn into(self) -> Lpms {
125 match self { 125 match self {
126 StopMode::Stop1 => Lpms::STOP1, 126 StopMode::Stop1 => Lpms::STOP1,
127 #[cfg(not(any(stm32wb, stm32wba)))] 127 #[cfg(not(stm32wba))]
128 StopMode::Standby | StopMode::Stop2 => Lpms::STOP2, 128 StopMode::Standby | StopMode::Stop2 => Lpms::STOP2,
129 #[cfg(any(stm32wb, stm32wba))] 129 #[cfg(stm32wba)]
130 StopMode::Standby | StopMode::Stop2 => Lpms::STOP1, // TODO: WBA has no STOP2? 130 StopMode::Standby | StopMode::Stop2 => Lpms::STOP1, // TODO: WBA has no STOP2?
131 } 131 }
132 } 132 }
@@ -170,24 +170,44 @@ impl Executor {
170 } 170 }
171 171
172 critical_section::with(|cs| { 172 critical_section::with(|cs| {
173 #[cfg(stm32wlex)] 173 #[cfg(any(stm32wlex, stm32wb))]
174 { 174 {
175 let es = crate::pac::PWR.extscr().read(); 175 let es = crate::pac::PWR.extscr().read();
176 #[cfg(stm32wlex)]
176 match (es.c1stopf(), es.c1stop2f()) { 177 match (es.c1stopf(), es.c1stop2f()) {
177 (true, false) => debug!("low power: wake from STOP1"), 178 (true, false) => debug!("low power: wake from STOP1"),
178 (false, true) => debug!("low power: wake from STOP2"), 179 (false, true) => debug!("low power: wake from STOP2"),
179 (true, true) => debug!("low power: wake from STOP1 and STOP2 ???"), 180 (true, true) => debug!("low power: wake from STOP1 and STOP2 ???"),
180 (false, false) => trace!("low power: stop mode not entered"), 181 (false, false) => trace!("low power: stop mode not entered"),
181 }; 182 };
183
184 #[cfg(stm32wb)]
185 match (es.c1stopf(), es.c2stopf()) {
186 (true, false) => debug!("low power: cpu1 wake from STOP"),
187 (false, true) => debug!("low power: cpu2 wake from STOP"),
188 (true, true) => debug!("low power: cpu1 and cpu2 wake from STOP"),
189 (false, false) => trace!("low power: stop mode not entered"),
190 };
182 crate::pac::PWR.extscr().modify(|w| { 191 crate::pac::PWR.extscr().modify(|w| {
183 w.set_c1cssf(false); 192 w.set_c1cssf(false);
184 }); 193 });
185 194
186 if es.c1stop2f() || es.c1stopf() { 195 let has_stopped2 = {
196 #[cfg(stm32wb)]
197 {
198 es.c2stopf()
199 }
200
201 #[cfg(stm32wlex)]
202 {
203 es.c1stop2f()
204 }
205 };
206
207 if es.c1stopf() || has_stopped2 {
187 // when we wake from any stop mode we need to re-initialize the rcc 208 // when we wake from any stop mode we need to re-initialize the rcc
188 crate::rcc::init(RCC_CONFIG.unwrap()); 209 crate::rcc::init(RCC_CONFIG.unwrap());
189 210 if has_stopped2 {
190 if es.c1stop2f() {
191 // when we wake from STOP2, we need to re-initialize the time driver 211 // when we wake from STOP2, we need to re-initialize the time driver
192 get_driver().init_timer(cs); 212 get_driver().init_timer(cs);
193 // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer) 213 // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer)
@@ -276,6 +296,20 @@ impl Executor {
276 296
277 drop(sem3_mutex); 297 drop(sem3_mutex);
278 298
299 // on PWR
300 RCC.apb1enr1().modify(|r| r.0 |= 1 << 28);
301 cortex_m::asm::dsb();
302
303 // off SMPS, on Bypass
304 PWR.cr5().modify(|r| {
305 let mut val = r.0;
306 val &= !(1 << 15); // sdeb = 0 (off SMPS)
307 val |= 1 << 14; // sdben = 1 (on Bypass)
308 r.0 = val
309 });
310
311 cortex_m::asm::delay(1000);
312
279 Ok(()) 313 Ok(())
280 } 314 }
281 315
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index d25c922d8..753ee1290 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -313,7 +313,7 @@ impl RccInfo {
313 313
314 #[allow(dead_code)] 314 #[allow(dead_code)]
315 fn increment_minimum_stop_refcount_with_cs(&self, _cs: CriticalSection) { 315 fn increment_minimum_stop_refcount_with_cs(&self, _cs: CriticalSection) {
316 #[cfg(all(stm32wlex, feature = "low-power"))] 316 #[cfg(all(any(stm32wlex, stm32wb), feature = "low-power"))]
317 match self.stop_mode { 317 match self.stop_mode {
318 StopMode::Stop1 | StopMode::Stop2 => increment_stop_refcount(_cs, StopMode::Stop2), 318 StopMode::Stop1 | StopMode::Stop2 => increment_stop_refcount(_cs, StopMode::Stop2),
319 _ => {} 319 _ => {}
@@ -334,7 +334,7 @@ impl RccInfo {
334 334
335 #[allow(dead_code)] 335 #[allow(dead_code)]
336 fn decrement_minimum_stop_refcount_with_cs(&self, _cs: CriticalSection) { 336 fn decrement_minimum_stop_refcount_with_cs(&self, _cs: CriticalSection) {
337 #[cfg(all(stm32wlex, feature = "low-power"))] 337 #[cfg(all(any(stm32wlex, stm32wb), feature = "low-power"))]
338 match self.stop_mode { 338 match self.stop_mode {
339 StopMode::Stop1 | StopMode::Stop2 => decrement_stop_refcount(_cs, StopMode::Stop2), 339 StopMode::Stop1 | StopMode::Stop2 => decrement_stop_refcount(_cs, StopMode::Stop2),
340 _ => {} 340 _ => {}