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_mac
|
||||||
rm out/tests/stm32wb55rg/wpan_ble
|
rm out/tests/stm32wb55rg/wpan_ble
|
||||||
|
|
||||||
# unstable
|
|
||||||
rm out/tests/stm32f429zi/stop
|
|
||||||
|
|
||||||
# unstable, I think it's running out of RAM?
|
# unstable, I think it's running out of RAM?
|
||||||
rm out/tests/stm32f207zg/eth
|
rm out/tests/stm32f207zg/eth
|
||||||
|
|
|
@ -90,6 +90,7 @@ defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-emb
|
||||||
|
|
||||||
exti = []
|
exti = []
|
||||||
low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ]
|
low-power = [ "dep:embassy-executor", "embassy-executor/arch-cortex-m" ]
|
||||||
|
low-power-debug-with-sleep = []
|
||||||
embassy-executor = []
|
embassy-executor = []
|
||||||
|
|
||||||
## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/)
|
## 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! {
|
g.extend(quote! {
|
||||||
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
|
impl crate::rcc::sealed::RccPeripheral for peripherals::#pname {
|
||||||
fn frequency() -> crate::time::Hertz {
|
fn frequency() -> crate::time::Hertz {
|
||||||
|
@ -563,8 +589,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
|
fn enable_and_reset_with_cs(_cs: critical_section::CriticalSection) {
|
||||||
#before_enable
|
#before_enable
|
||||||
#[cfg(feature = "low-power")]
|
#incr_stop_refcount
|
||||||
unsafe { crate::rcc::REFCOUNT_STOP2 += 1 };
|
|
||||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
|
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(true));
|
||||||
#after_enable
|
#after_enable
|
||||||
#rst
|
#rst
|
||||||
|
@ -572,8 +597,7 @@ fn main() {
|
||||||
fn disable_with_cs(_cs: critical_section::CriticalSection) {
|
fn disable_with_cs(_cs: critical_section::CriticalSection) {
|
||||||
#before_disable
|
#before_disable
|
||||||
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
|
crate::pac::RCC.#en_reg().modify(|w| w.#set_en_field(false));
|
||||||
#[cfg(feature = "low-power")]
|
#decr_stop_refcount
|
||||||
unsafe { crate::rcc::REFCOUNT_STOP2 -= 1 };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -228,8 +228,9 @@ pub fn init(config: Config) -> Peripherals {
|
||||||
|
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
{
|
{
|
||||||
crate::rcc::REFCOUNT_STOP2 = 0
|
crate::rcc::REFCOUNT_STOP2 = 0;
|
||||||
};
|
crate::rcc::REFCOUNT_STOP1 = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p
|
p
|
||||||
|
|
|
@ -33,11 +33,17 @@ pub fn stop_with_rtc(rtc: &'static Rtc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop_ready(stop_mode: StopMode) -> bool {
|
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]
|
#[non_exhaustive]
|
||||||
|
#[derive(PartialEq)]
|
||||||
pub enum StopMode {
|
pub enum StopMode {
|
||||||
|
Stop1,
|
||||||
Stop2,
|
Stop2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,23 +94,39 @@ impl Executor {
|
||||||
trace!("low power: stop with rtc configured");
|
trace!("low power: stop with rtc configured");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop_ready(&self, stop_mode: StopMode) -> bool {
|
fn stop_mode(&self) -> Option<StopMode> {
|
||||||
match stop_mode {
|
if unsafe { crate::rcc::REFCOUNT_STOP2 == 0 } && unsafe { crate::rcc::REFCOUNT_STOP1 == 0 } {
|
||||||
StopMode::Stop2 => unsafe { crate::rcc::REFCOUNT_STOP2 == 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) {
|
fn configure_pwr(&mut self) {
|
||||||
self.scb.clear_sleepdeep();
|
self.scb.clear_sleepdeep();
|
||||||
|
|
||||||
compiler_fence(Ordering::SeqCst);
|
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");
|
trace!("low power: not ready to stop");
|
||||||
} else if self.time_driver.pause_time().is_err() {
|
} else if self.time_driver.pause_time().is_err() {
|
||||||
trace!("low power: failed to pause time");
|
trace!("low power: failed to pause time");
|
||||||
} else {
|
} 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();
|
self.scb.set_sleepdeep();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,6 +181,15 @@ pub struct Clocks {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "low-power")]
|
#[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;
|
pub(crate) static mut REFCOUNT_STOP2: u32 = 0;
|
||||||
|
|
||||||
/// Frozen clock frequencies
|
/// Frozen clock frequencies
|
||||||
|
|
|
@ -143,13 +143,7 @@ impl Default for RtcCalibrationCyclePeriod {
|
||||||
impl Rtc {
|
impl Rtc {
|
||||||
pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
|
pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self {
|
||||||
#[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
|
#[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
|
||||||
critical_section::with(|cs| {
|
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
|
||||||
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(cs);
|
|
||||||
#[cfg(feature = "low-power")]
|
|
||||||
unsafe {
|
|
||||||
crate::rcc::REFCOUNT_STOP2 -= 1
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
let mut this = Self {
|
let mut this = Self {
|
||||||
#[cfg(feature = "low-power")]
|
#[cfg(feature = "low-power")]
|
||||||
|
|
|
@ -33,7 +33,7 @@ stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"]
|
||||||
eth = []
|
eth = []
|
||||||
rng = []
|
rng = []
|
||||||
sdmmc = []
|
sdmmc = []
|
||||||
stop = ["embassy-stm32/low-power"]
|
stop = ["embassy-stm32/low-power", "embassy-stm32/low-power-debug-with-sleep"]
|
||||||
chrono = ["embassy-stm32/chrono", "dep:chrono"]
|
chrono = ["embassy-stm32/chrono", "dep:chrono"]
|
||||||
can = []
|
can = []
|
||||||
ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
|
ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"]
|
||||||
|
|
Loading…
Reference in a new issue