aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-12-16 17:24:12 +0000
committerGitHub <[email protected]>2025-12-16 17:24:12 +0000
commit996a8d74d7a1a67eec528c34407efb0d6f2a20ba (patch)
treea5a4bd069fe2db917ec24225ff18aa1805f8da49 /embassy-stm32/src
parent49040dfb760d54067e5d2e1b6d490002c0c04a24 (diff)
parenta02d74c78f1a8192da701965575fe975092aaf9e (diff)
Merge pull request #5085 from xoviat/stm32-pender
stm32: add low power pender
Diffstat (limited to 'embassy-stm32/src')
-rw-r--r--embassy-stm32/src/low_power.rs43
1 files changed, 34 insertions, 9 deletions
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 0cdd7789e..5c10c1a5d 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -43,7 +43,7 @@
43use core::arch::asm; 43use core::arch::asm;
44use core::marker::PhantomData; 44use core::marker::PhantomData;
45use core::mem; 45use core::mem;
46use core::sync::atomic::{Ordering, compiler_fence}; 46use core::sync::atomic::{AtomicBool, Ordering, compiler_fence};
47 47
48use cortex_m::peripheral::SCB; 48use cortex_m::peripheral::SCB;
49use critical_section::CriticalSection; 49use critical_section::CriticalSection;
@@ -56,7 +56,27 @@ use crate::time_driver::get_driver;
56 56
57const THREAD_PENDER: usize = usize::MAX; 57const THREAD_PENDER: usize = usize::MAX;
58 58
59static mut EXECUTOR_TAKEN: bool = false; 59static EXECUTOR_TAKEN: AtomicBool = AtomicBool::new(false);
60#[cfg(feature = "low-power-pender")]
61static TASKS_PENDING: AtomicBool = AtomicBool::new(false);
62
63#[cfg(feature = "low-power-pender")]
64#[unsafe(export_name = "__pender")]
65fn __pender(context: *mut ()) {
66 unsafe {
67 // Safety: `context` is either `usize::MAX` created by `Executor::run`, or a valid interrupt
68 // request number given to `InterruptExecutor::start`.
69
70 let context = context as usize;
71
72 // Try to make Rust optimize the branching away if we only use thread mode.
73 if context == THREAD_PENDER {
74 TASKS_PENDING.store(true, Ordering::Release);
75 core::arch::asm!("sev");
76 return;
77 }
78 }
79}
60 80
61/// Prevent the device from going into the stop mode if held 81/// Prevent the device from going into the stop mode if held
62pub struct DeviceBusy { 82pub struct DeviceBusy {
@@ -150,12 +170,10 @@ pub struct Executor {
150impl Executor { 170impl Executor {
151 /// Create a new Executor. 171 /// Create a new Executor.
152 pub fn new() -> Self { 172 pub fn new() -> Self {
153 unsafe { 173 if EXECUTOR_TAKEN.load(Ordering::Acquire) {
154 if EXECUTOR_TAKEN { 174 panic!("Low power executor can only be taken once.");
155 panic!("Low power executor can only be taken once."); 175 } else {
156 } else { 176 EXECUTOR_TAKEN.store(true, Ordering::Release);
157 EXECUTOR_TAKEN = true;
158 }
159 } 177 }
160 178
161 Self { 179 Self {
@@ -338,7 +356,14 @@ impl Executor {
338 w.set_c1cssf(true); 356 w.set_c1cssf(true);
339 }); 357 });
340 358
341 compiler_fence(Ordering::SeqCst); 359 #[cfg(feature = "low-power-pender")]
360 if TASKS_PENDING.load(Ordering::Acquire) {
361 TASKS_PENDING.store(false, Ordering::Release);
362
363 return;
364 }
365
366 compiler_fence(Ordering::Acquire);
342 367
343 critical_section::with(|cs| { 368 critical_section::with(|cs| {
344 let _ = unsafe { RCC_CONFIG }?; 369 let _ = unsafe { RCC_CONFIG }?;