stm32: compute stop mode and workaround rtt test bug
This commit is contained in:
parent
2765f0978f
commit
dc467e89a0
8 changed files with 71 additions and 22 deletions
2
ci.sh
2
ci.sh
|
@ -218,8 +218,6 @@ cargo batch \
|
|||
rm out/tests/stm32wb55rg/wpan_mac
|
||||
rm out/tests/stm32wb55rg/wpan_ble
|
||||
|
||||
# unstable
|
||||
rm out/tests/stm32f429zi/stop
|
||||
|
||||
# unstable, I think it's running out of RAM?
|
||||
rm out/tests/stm32f207zg/eth
|
||||
|
|
|
@ -90,6 +90,7 @@ defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-emb
|
|||
|
||||
exti = []
|
||||
low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ]
|
||||
low-power-debug-with-sleep = []
|
||||
embassy-executor = []
|
||||
|
||||
## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/)
|
||||
|
|
|
@ -556,6 +556,32 @@ fn main() {
|
|||
},
|
||||
};
|
||||
|
||||
/*
|
||||
If LP and non-LP peripherals share the same RCC enable bit, then a refcount leak will result.
|
||||
|
||||
This should be checked in stm32-data-gen.
|
||||
*/
|
||||
let stop_refcount = if p.name.starts_with("LP") {
|
||||
quote! { REFCOUNT_STOP2 }
|
||||
} else {
|
||||
quote! { REFCOUNT_STOP1 }
|
||||
};
|
||||
|
||||
let (incr_stop_refcount, decr_stop_refcount) = if p.name != "RTC" {
|
||||
(
|
||||
quote! {
|
||||
#[cfg(feature = "low-power")]
|
||||
unsafe { crate::rcc::#stop_refcount += 1 };
|
||||
},
|
||||
quote! {
|
||||
#[cfg(feature = "low-power")]
|
||||
unsafe { crate::rcc::#stop_refcount -= 1 };
|
||||
},
|
||||
)
|
||||
} else {
|
||||
(quote! {}, quote! {})
|
||||
};
|
||||
|
||||
g.extend(quote! {
|
||||
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
|
||||
fn frequency() -> crate::time::Hertz {
|
||||
|
@ -563,8 +589,7 @@ fn main() {
|
|||
}
|
||||
fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
|
||||
#before_enable
|
||||
#[cfg(feature = "low-power")]
|
||||
unsafe { crate::rcc::REFCOUNT_STOP2 += 1 };
|
||||
#incr_stop_refcount
|
||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
|
||||
#after_enable
|
||||
#rst
|
||||
|
@ -572,8 +597,7 @@ fn main() {
|
|||
fn disable_with_cs(_cs: critical_section::CriticalSection) {
|
||||
#before_disable
|
||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
|
||||
#[cfg(feature = "low-power")]
|
||||
unsafe { crate::rcc::REFCOUNT_STOP2 -= 1 };
|
||||
#decr_stop_refcount
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -228,8 +228,9 @@ pub fn init(config: Config) -> Peripherals {
|
|||
|
||||
#[cfg(feature = "low-power")]
|
||||
{
|
||||
crate::rcc::REFCOUNT_STOP2 = 0
|
||||
};
|
||||
crate::rcc::REFCOUNT_STOP2 = 0;
|
||||
crate::rcc::REFCOUNT_STOP1 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
p
|
||||
|
|
|
@ -33,11 +33,17 @@ pub fn stop_with_rtc(rtc: &'static Rtc) {
|
|||
}
|
||||
|
||||
pub fn stop_ready(stop_mode: StopMode) -> bool {
|
||||
unsafe { EXECUTOR.as_mut().unwrap() }.stop_ready(stop_mode)
|
||||
match unsafe { EXECUTOR.as_mut().unwrap() }.stop_mode() {
|
||||
Some(StopMode::Stop2) => true,
|
||||
Some(StopMode::Stop1) => stop_mode == StopMode::Stop1,
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
#[derive(PartialEq)]
|
||||
pub enum StopMode {
|
||||
Stop1,
|
||||
Stop2,
|
||||
}
|
||||
|
||||
|
@ -88,23 +94,39 @@ impl Executor {
|
|||
trace!("low power: stop with rtc configured");
|
||||
}
|
||||
|
||||
fn stop_ready(&self, stop_mode: StopMode) -> bool {
|
||||
match stop_mode {
|
||||
StopMode::Stop2 => unsafe { crate::rcc::REFCOUNT_STOP2 == 0 },
|
||||
fn stop_mode(&self) -> Option<StopMode> {
|
||||
if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 } && unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
|
||||
Some(StopMode::Stop2)
|
||||
} else if unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
|
||||
Some(StopMode::Stop1)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn configure_stop(&mut self, _stop_mode: StopMode) {
|
||||
// TODO: configure chip-specific settings for stop
|
||||
}
|
||||
|
||||
fn configure_pwr(&mut self) {
|
||||
self.scb.clear_sleepdeep();
|
||||
|
||||
compiler_fence(Ordering::SeqCst);
|
||||
|
||||
if !self.stop_ready(StopMode::Stop2) {
|
||||
let stop_mode = self.stop_mode();
|
||||
if stop_mode.is_none() {
|
||||
trace!("low power: not ready to stop");
|
||||
} else if self.time_driver.pause_time().is_err() {
|
||||
trace!("low power: failed to pause time");
|
||||
} else {
|
||||
trace!("low power: stop");
|
||||
let stop_mode = stop_mode.unwrap();
|
||||
match stop_mode {
|
||||
StopMode::Stop1 => trace!("low power: stop 1"),
|
||||
StopMode::Stop2 => trace!("low power: stop 2"),
|
||||
}
|
||||
self.configure_stop(stop_mode);
|
||||
|
||||
#[cfg(not(feature = "low-power-debug-with-sleep"))]
|
||||
self.scb.set_sleepdeep();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -181,6 +181,15 @@ pub struct Clocks {
|
|||
}
|
||||
|
||||
#[cfg(feature = "low-power")]
|
||||
/// Must be written within a critical section
|
||||
///
|
||||
/// May be read without a critical section
|
||||
pub(crate) static mut REFCOUNT_STOP1: u32 = 0;
|
||||
|
||||
#[cfg(feature = "low-power")]
|
||||
/// Must be written within a critical section
|
||||
///
|
||||
/// May be read without a critical section
|
||||
pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
|
||||
|
||||
/// Frozen clock frequencies
|
||||
|
|
|
@ -143,13 +143,7 @@ impl Default for RtcCalibrationCyclePeriod {
|
|||
impl Rtc {
|
||||
pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
|
||||
#[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
|
||||
critical_section::with(|cs| {
|
||||
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs);
|
||||
#[cfg(feature = "low-power")]
|
||||
unsafe {
|
||||
crate::rcc::REFCOUNT_STOP2 -= 1
|
||||
};
|
||||
});
|
||||
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
|
||||
|
||||
let mut this = Self {
|
||||
#[cfg(feature = "low-power")]
|
||||
|
|
|
@ -33,7 +33,7 @@ stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"]
|
|||
eth = []
|
||||
rng = []
|
||||
sdmmc = []
|
||||
stop = ["embassy-stm32/low-power"]
|
||||
stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"]
|
||||
chrono = ["embassy-stm32/chrono", "dep:chrono"]
|
||||
can = []
|
||||
ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
|
||||
|
|
Loading…
Reference in a new issue