implementation of stops and reorganization of the codebase

This commit is contained in:
Priec
2025-12-12 22:25:36 +01:00
parent 72a731abef
commit 2c9433cb84
6 changed files with 156 additions and 128 deletions

View File

@@ -11,9 +11,7 @@ use embassy_time::{Duration, Timer};
use dma_gpio::config::BAUD; use dma_gpio::config::BAUD;
use dma_gpio::wakeup::iwdg::{clear_wakeup_flags, init_watchdog_reset}; use dma_gpio::wakeup::iwdg::{clear_wakeup_flags, init_watchdog_reset};
use dma_gpio::sleep::shutdown; use dma_gpio::sleep::handler::execute_low_power;
use dma_gpio::sleep::standby;
use dma_gpio::sleep::stop3;
use dma_gpio::hw_uart_pc::init::{init_hw_uart_to_pc, LowPowerCmd, CMD_CH}; use dma_gpio::hw_uart_pc::init::{init_hw_uart_to_pc, LowPowerCmd, CMD_CH};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
@@ -47,9 +45,7 @@ async fn main(spawner: Spawner) {
[2] Standby + full SRAM2 retention\n\ [2] Standby + full SRAM2 retention\n\
[3] Standby — minimal power, SRAM2 lost\n\ [3] Standby — minimal power, SRAM2 lost\n\
[4] Shutdown — lowest power, full reset on wake\n\ [4] Shutdown — lowest power, full reset on wake\n\
[5] STOP3 mode with WFI\n\ [5] STOP mode (then choose: 0-3 for mode, 1-3 for entry method)",
[6] STOP3 mode with WFE\n\
[7] STOP3 mode with WFE (no event clear)",
BAUD, WATCHDOG_TIMEOUT_US / 1_000_000 BAUD, WATCHDOG_TIMEOUT_US / 1_000_000
); );
@@ -66,41 +62,6 @@ async fn main(spawner: Spawner) {
info!("ready for uart"); info!("ready for uart");
loop { loop {
let cmd = CMD_CH.receive().await; let cmd = CMD_CH.receive().await;
match cmd { execute_low_power(cmd);
LowPowerCmd::Standby8k => {
init_watchdog_reset(p.IWDG).await; // watchdog reset at configurated time
Timer::after(Duration::from_millis(10)).await; // let UART flush
standby::enter_standby_with_sram2_8kb();
}
LowPowerCmd::StandbyFull => {
init_watchdog_reset(p.IWDG).await;
Timer::after(Duration::from_millis(10)).await;
standby::enter_standby_with_sram2_full();
}
LowPowerCmd::Standby => {
init_watchdog_reset(p.IWDG).await;
Timer::after(Duration::from_millis(10)).await;
standby::enter_standby();
}
LowPowerCmd::Shutdown => {
Timer::after(Duration::from_millis(10)).await;
shutdown::enter_shutdown();
}
LowPowerCmd::Stop3Wfi => {
init_watchdog_reset(p.IWDG).await;
Timer::after(Duration::from_millis(10)).await;
stop3::enter_stop3(stop3::StopEntry::Wfi);
}
LowPowerCmd::Stop3Wfe => {
init_watchdog_reset(p.IWDG).await;
Timer::after(Duration::from_millis(10)).await;
stop3::enter_stop3(stop3::StopEntry::Wfe);
}
LowPowerCmd::Stop3WfeNoClear => {
init_watchdog_reset(p.IWDG).await;
Timer::after(Duration::from_millis(10)).await;
stop3::enter_stop3(stop3::StopEntry::WfeNoEventClear);
}
}
} }
} }

View File

@@ -7,6 +7,8 @@ use embassy_futures::yield_now;
// UART HW init // UART HW init
use crate::config::{BAUD, PIPE_HW_TX, PIPE_HW_RX}; use crate::config::{BAUD, PIPE_HW_TX, PIPE_HW_RX};
use crate::hw_uart_pc::driver::uart_task; use crate::hw_uart_pc::driver::uart_task;
use crate::sleep::StopEntry;
use crate::sleep::handler::execute_low_power;
use static_cell::StaticCell; use static_cell::StaticCell;
use embassy_stm32::usart::BufferedInterruptHandler; use embassy_stm32::usart::BufferedInterruptHandler;
use embassy_stm32::usart::{BufferedUart, Config as UsartConfig}; use embassy_stm32::usart::{BufferedUart, Config as UsartConfig};
@@ -21,67 +23,78 @@ bind_interrupts!(struct Irqs {
USART1 => BufferedInterruptHandler<peripherals::USART1>; USART1 => BufferedInterruptHandler<peripherals::USART1>;
}); });
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
pub enum LowPowerCmd { pub enum LowPowerCmd {
Standby8k, // 1 Standby8k, // 1
StandbyFull, // 2 StandbyFull, // 2
Standby, // 3 Standby, // 3
Shutdown, // 4 Shutdown, // 4
Stop3Wfi, StopMode(StopModeConfig),
Stop3Wfe, }
Stop3WfeNoClear,
#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
pub struct StopModeConfig {
pub mode: StopMode,
pub entry: StopEntry,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
pub enum StopMode {
Stop1,
Stop2,
Stop3,
} }
pub static CMD_CH: Channel<CriticalSectionRawMutex, LowPowerCmd, 1> = Channel::new(); pub static CMD_CH: Channel<CriticalSectionRawMutex, LowPowerCmd, 1> = Channel::new();
#[embassy_executor::task] #[embassy_executor::task]
pub async fn uart_cmd_task() { pub async fn uart_cmd_task() {
// Prompt once let _ = PIPE_HW_TX.write(
let _ = PIPE_HW_TX b"\r\n\
.write(b"Modes: 1=SB8, 2=SBfull, 3=SB, 4=SD, 5=STOP3(WFI), 6=STOP3(WFE), 7=STOP3(WFE no clear)\r\n") Modes:\r\n\
.await; [1] Standby + 8 KB SRAM2 retention\r\n\
[2] Standby + full SRAM2 retention\r\n\
[3] Standby minimal\r\n\
[4] Shutdown\r\n\
[5] Stop mode (0-3)\r\n\
"
).await;
let mut b = [0u8; 1]; let mut b = [0u8; 2];
loop { loop {
let n = PIPE_HW_RX.read(&mut b).await; let n = PIPE_HW_RX.read(&mut b).await;
if n == 0 { if n == 0 { continue; }
continue;
}
match b[0] { match b[0] {
b'1' => { b'1' => CMD_CH.send(LowPowerCmd::Standby8k).await,
let _ = PIPE_HW_TX.write(b"ACK 1: standby 8KB\r\n").await; b'2' => CMD_CH.send(LowPowerCmd::StandbyFull).await,
CMD_CH.send(LowPowerCmd::Standby8k).await; b'3' => CMD_CH.send(LowPowerCmd::Standby).await,
} b'4' => CMD_CH.send(LowPowerCmd::Shutdown).await,
b'2' => {
let _ = PIPE_HW_TX.write(b"ACK 2: standby full\r\n").await;
CMD_CH.send(LowPowerCmd::StandbyFull).await;
}
b'3' => {
let _ = PIPE_HW_TX.write(b"ACK 3: standby\r\n").await;
CMD_CH.send(LowPowerCmd::Standby).await;
}
b'4' => {
let _ = PIPE_HW_TX.write(b"ACK 4: shutdown\r\n").await;
CMD_CH.send(LowPowerCmd::Shutdown).await;
}
b'5' => { b'5' => {
let _ = PIPE_HW_TX.write(b"ACK 5: STOP3 with WFI\r\n").await; // Expect 2 digits: e.g. b'5' + '13' = Stop1 WfeNoEventClear
CMD_CH.send(LowPowerCmd::Stop3Wfi).await; let _ = PIPE_HW_TX.write(b"Enter Stop mode number (0-3): ").await;
let _ = PIPE_HW_RX.read(&mut b[1..2]).await;
let stop_mode = match b[1] {
b'1' => StopMode::Stop1,
b'2' => StopMode::Stop2,
_ => StopMode::Stop3,
};
let _ = PIPE_HW_TX.write(b"Enter entry method (1=WFI,2=WFE,3=WFE no clear): ").await;
let n = PIPE_HW_RX.read(&mut b[1..2]).await;
if n > 0 {
let entry = match b[1] {
b'1' => StopEntry::Wfi,
b'2' => StopEntry::Wfe,
_ => StopEntry::WfeNoEventClear,
};
CMD_CH.send(LowPowerCmd::StopMode(StopModeConfig { mode: stop_mode, entry })).await;
} }
b'6' => {
let _ = PIPE_HW_TX.write(b"ACK 6: STOP3 with WFE\r\n").await;
CMD_CH.send(LowPowerCmd::Stop3Wfe).await;
} }
b'7' => {
let _ = PIPE_HW_TX.write(b"ACK 7: STOP3 with WFE (no event clear)\r\n").await;
CMD_CH.send(LowPowerCmd::Stop3WfeNoClear).await;
}
b'\r' | b'\n' | b' ' => {}
_ => { _ => {
let _ = PIPE_HW_TX.write(b"ERR: use 1|2|3|4|5|6|7\r\n").await; let _ = PIPE_HW_TX.write(b"Unknown command\r\n").await;
} }
} }
yield_now().await;
} }
} }

View File

@@ -0,0 +1,35 @@
use crate::sleep::stop::StopEntry;
use crate::sleep::stop::*;
use crate::hw_uart_pc::init::{LowPowerCmd, StopMode, StopModeConfig};
use defmt::info;
pub fn execute_low_power(cmd: LowPowerCmd) -> ! {
match cmd {
LowPowerCmd::Standby8k => {
info!("Entering Standby with 8KB SRAM2 retention");
// call your existing standby function here
super::standby::enter_standby_with_sram2_8kb();
}
LowPowerCmd::StandbyFull => {
info!("Entering Standby with full SRAM2 retention");
super::standby::enter_standby_with_sram2_full();
}
LowPowerCmd::Standby => {
info!("Entering minimal Standby");
super::standby::enter_standby();
}
LowPowerCmd::Shutdown => {
info!("Entering Shutdown mode");
super::shutdown::enter_shutdown();
}
LowPowerCmd::StopMode(StopModeConfig { mode, entry }) => {
info!("Entering {:?} with {:?}", mode, entry);
match mode {
StopMode::Stop1 => enter_stop1(entry),
StopMode::Stop2 => enter_stop2(entry),
StopMode::Stop3 => enter_stop3(entry),
}
}
}
}

View File

@@ -2,4 +2,7 @@
pub mod standby; pub mod standby;
pub mod shutdown; pub mod shutdown;
pub mod stop3; pub mod stop;
pub mod handler;
pub use stop::StopEntry;

View File

@@ -0,0 +1,55 @@
// src/sleep/stop.rs
/// How to enter STOPx mode (STOP0STOP3)
#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
pub enum StopEntry {
Wfi,
Wfe,
WfeNoEventClear,
}
impl From<StopEntry> for u8 {
fn from(value: StopEntry) -> Self {
match value {
StopEntry::Wfi => 0x01,
StopEntry::Wfe => 0x02,
StopEntry::WfeNoEventClear => 0x03,
}
}
}
pub fn enter_stop1(entry: StopEntry) -> ! {
unsafe extern "C" {
fn HAL_PWREx_EnterSTOP1Mode(entry: u8);
}
unsafe {
HAL_PWREx_EnterSTOP1Mode(entry.into());
}
cortex_m::asm::udf()
}
pub fn enter_stop2(entry: StopEntry) -> ! {
unsafe extern "C" {
fn HAL_PWREx_EnterSTOP2Mode(entry: u8);
}
unsafe {
HAL_PWREx_EnterSTOP2Mode(entry.into());
}
cortex_m::asm::udf()
}
pub fn enter_stop3(entry: StopEntry) -> ! {
unsafe extern "C" {
fn HAL_PWREx_EnterSTOP3Mode(entry: u8);
}
unsafe {
HAL_PWREx_EnterSTOP3Mode(entry.into());
}
cortex_m::asm::udf()
}

View File

@@ -1,39 +0,0 @@
// src/sleep/stop3.rs
// #define PWR_STOPENTRY_WFI (0x01U) //*!< Wait For Interruption instruction to enter Stop mode */
// #define PWR_STOPENTRY_WFE (0x02U) //*!< Wait For Event instruction to enter Stop mode */
// #define PWR_STOPENTRY_WFE_NO_EVT_CLEAR (0x03U)
/// How to enter STOP3 mode
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StopEntry {
Wfi,
Wfe,
WfeNoEventClear,
}
impl From<StopEntry> for u8 {
fn from(value: StopEntry) -> Self {
match value {
StopEntry::Wfi => 0x01,
StopEntry::Wfe => 0x02,
StopEntry::WfeNoEventClear => 0x03,
}
}
}
pub fn enter_stop3(stop_entry: StopEntry) -> ! {
unsafe extern "C" {
fn HAL_PWREx_EnterSTOP3Mode(stop_entry: u8);
}
unsafe {
HAL_PWREx_EnterSTOP3Mode(stop_entry.into());
}
cortex_m::asm::udf(); //panic
}
// Example usage:
// enter_stop3(StopEntry::Wfi);
// enter_stop3(StopEntry::Wfe);
// enter_stop3(StopEntry::WfeNoEventClear);