aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-11-04 18:57:44 +0000
committerGitHub <[email protected]>2023-11-04 18:57:44 +0000
commit056c409443b8280fc951669d15df2fb59521a4d8 (patch)
tree3375dd57e07879f2d709f7547d95b2a7f757ae14
parent655ed3aa887fe2d9e424f239cc07db055d8f8d61 (diff)
parent3f2abd4fd5da51d7b8a7711d0eac02c7f7b9deed (diff)
Merge pull request #2140 from xoviat/low-power
stm32: compute stop mode and workaround rtt test bug
-rwxr-xr-xci.sh2
-rw-r--r--embassy-stm32/Cargo.toml1
-rw-r--r--embassy-stm32/build.rs32
-rw-r--r--embassy-stm32/src/lib.rs5
-rw-r--r--embassy-stm32/src/low_power.rs34
-rw-r--r--embassy-stm32/src/rcc/mod.rs9
-rw-r--r--embassy-stm32/src/rtc/mod.rs9
-rw-r--r--tests/stm32/Cargo.toml2
8 files changed, 71 insertions, 23 deletions
diff --git a/ci.sh b/ci.sh
index 5c69d3a29..2e6bbae8e 100755
--- a/ci.sh
+++ b/ci.sh
@@ -218,8 +218,6 @@ cargo batch \
218rm out/tests/stm32wb55rg/wpan_mac 218rm out/tests/stm32wb55rg/wpan_mac
219rm out/tests/stm32wb55rg/wpan_ble 219rm out/tests/stm32wb55rg/wpan_ble
220 220
221# unstable
222rm out/tests/stm32f429zi/stop
223 221
224# unstable, I think it's running out of RAM? 222# unstable, I think it's running out of RAM?
225rm out/tests/stm32f207zg/eth 223rm out/tests/stm32f207zg/eth
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index bc79ab7a2..2a2df5c56 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -90,6 +90,7 @@ defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-emb
90 90
91exti = [] 91exti = []
92low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ] 92low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ]
93low-power-debug-with-sleep = []
93embassy-executor = [] 94embassy-executor = []
94 95
95## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) 96## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/)
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 3400529c9..276c1d637 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -556,6 +556,32 @@ fn main() {
556 }, 556 },
557 }; 557 };
558 558
559 /*
560 If LP and non-LP peripherals share the same RCC enable bit, then a refcount leak will result.
561
562 This should be checked in stm32-data-gen.
563 */
564 let stop_refcount = if p.name.starts_with("LP") {
565 quote! { REFCOUNT_STOP2 }
566 } else {
567 quote! { REFCOUNT_STOP1 }
568 };
569
570 let (incr_stop_refcount, decr_stop_refcount) = if p.name != "RTC" {
571 (
572 quote! {
573 #[cfg(feature = "low-power")]
574 unsafe { crate::rcc::#stop_refcount += 1 };
575 },
576 quote! {
577 #[cfg(feature = "low-power")]
578 unsafe { crate::rcc::#stop_refcount -= 1 };
579 },
580 )
581 } else {
582 (quote! {}, quote! {})
583 };
584
559 g.extend(quote! { 585 g.extend(quote! {
560 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { 586 impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
561 fn frequency() -> crate::time::Hertz { 587 fn frequency() -> crate::time::Hertz {
@@ -563,8 +589,7 @@ fn main() {
563 } 589 }
564 fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) { 590 fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
565 #before_enable 591 #before_enable
566 #[cfg(feature = "low-power")] 592 #incr_stop_refcount
567 unsafe { crate::rcc::REFCOUNT_STOP2 += 1 };
568 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true)); 593 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
569 #after_enable 594 #after_enable
570 #rst 595 #rst
@@ -572,8 +597,7 @@ fn main() {
572 fn disable_with_cs(_cs: critical_section::CriticalSection) { 597 fn disable_with_cs(_cs: critical_section::CriticalSection) {
573 #before_disable 598 #before_disable
574 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false)); 599 crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
575 #[cfg(feature = "low-power")] 600 #decr_stop_refcount
576 unsafe { crate::rcc::REFCOUNT_STOP2 -= 1 };
577 } 601 }
578 } 602 }
579 603
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 23d42bae8..511da9179 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -228,8 +228,9 @@ pub fn init(config: Config) -> Peripherals {
228 228
229 #[cfg(feature = "low-power")] 229 #[cfg(feature = "low-power")]
230 { 230 {
231 crate::rcc::REFCOUNT_STOP2 = 0 231 crate::rcc::REFCOUNT_STOP2 = 0;
232 }; 232 crate::rcc::REFCOUNT_STOP1 = 0;
233 }
233 } 234 }
234 235
235 p 236 p
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index aea3a5ce3..20d8f9045 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -80,11 +80,17 @@ pub fn stop_with_rtc(rtc: &'static Rtc) {
80} 80}
81 81
82pub fn stop_ready(stop_mode: StopMode) -> bool { 82pub fn stop_ready(stop_mode: StopMode) -> bool {
83 unsafe { EXECUTOR.as_mut().unwrap() }.stop_ready(stop_mode) 83 match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() {
84 Some(StopMode::Stop2) => true,
85 Some(StopMode::Stop1) => stop_mode == StopMode::Stop1,
86 None => false,
87 }
84} 88}
85 89
86#[non_exhaustive] 90#[non_exhaustive]
91#[derive(PartialEq)]
87pub enum StopMode { 92pub enum StopMode {
93 Stop1,
88 Stop2, 94 Stop2,
89} 95}
90 96
@@ -135,23 +141,39 @@ impl Executor {
135 trace!("low power: stop with rtc configured"); 141 trace!("low power: stop with rtc configured");
136 } 142 }
137 143
138 fn stop_ready(&self, stop_mode: StopMode) -> bool { 144 fn stop_mode(&self) -> Option<StopMode> {
139 match stop_mode { 145 if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 } && unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
140 StopMode::Stop2 => unsafe { crate::rcc::REFCOUNT_STOP2 == 0 }, 146 Some(StopMode::Stop2)
147 } else if unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
148 Some(StopMode::Stop1)
149 } else {
150 None
141 } 151 }
142 } 152 }
143 153
154 fn configure_stop(&mut self, _stop_mode: StopMode) {
155 // TODO: configure chip-specific settings for stop
156 }
157
144 fn configure_pwr(&mut self) { 158 fn configure_pwr(&mut self) {
145 self.scb.clear_sleepdeep(); 159 self.scb.clear_sleepdeep();
146 160
147 compiler_fence(Ordering::SeqCst); 161 compiler_fence(Ordering::SeqCst);
148 162
149 if !self.stop_ready(StopMode::Stop2) { 163 let stop_mode = self.stop_mode();
164 if stop_mode.is_none() {
150 trace!("low power: not ready to stop"); 165 trace!("low power: not ready to stop");
151 } else if self.time_driver.pause_time().is_err() { 166 } else if self.time_driver.pause_time().is_err() {
152 trace!("low power: failed to pause time"); 167 trace!("low power: failed to pause time");
153 } else { 168 } else {
154 trace!("low power: stop"); 169 let stop_mode = stop_mode.unwrap();
170 match stop_mode {
171 StopMode::Stop1 => trace!("low power: stop 1"),
172 StopMode::Stop2 => trace!("low power: stop 2"),
173 }
174 self.configure_stop(stop_mode);
175
176 #[cfg(not(feature = "low-power-debug-with-sleep"))]
155 self.scb.set_sleepdeep(); 177 self.scb.set_sleepdeep();
156 } 178 }
157 } 179 }
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 3b19e4b95..c11a9cc6b 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -181,6 +181,15 @@ pub struct Clocks {
181} 181}
182 182
183#[cfg(feature = "low-power")] 183#[cfg(feature = "low-power")]
184/// Must be written within a critical section
185///
186/// May be read without a critical section
187pub(crate) static mut REFCOUNT_STOP1: u32 = 0;
188
189#[cfg(feature = "low-power")]
190/// Must be written within a critical section
191///
192/// May be read without a critical section
184pub(crate) static mut REFCOUNT_STOP2: u32 = 0; 193pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
185 194
186/// Frozen clock frequencies 195/// Frozen clock frequencies
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index e527fdfee..e94a58575 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -153,14 +153,7 @@ impl Default for RtcCalibrationCyclePeriod {
153impl Rtc { 153impl Rtc {
154 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { 154 pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
155 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] 155 #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
156 critical_section::with(|cs| { 156 <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
157 <RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs);
158
159 #[cfg(feature = "low-power")]
160 unsafe {
161 crate::rcc::REFCOUNT_STOP2 -= 1
162 };
163 });
164 157
165 let mut this = Self { 158 let mut this = Self {
166 #[cfg(feature = "low-power")] 159 #[cfg(feature = "low-power")]
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index 14f27678f..4b769b1cb 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -33,7 +33,7 @@ stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"]
33eth = [] 33eth = []
34rng = [] 34rng = []
35sdmmc = [] 35sdmmc = []
36stop = ["embassy-stm32/low-power"] 36stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"]
37chrono = ["embassy-stm32/chrono", "dep:chrono"] 37chrono = ["embassy-stm32/chrono", "dep:chrono"]
38can = [] 38can = []
39ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] 39ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]