diff --git a/semestralka_2_uart/src/bin/main.rs b/semestralka_2_uart/src/bin/main.rs index 8055405..5e35704 100644 --- a/semestralka_2_uart/src/bin/main.rs +++ b/semestralka_2_uart/src/bin/main.rs @@ -11,9 +11,7 @@ use embassy_time::{Duration, Timer}; use dma_gpio::config::BAUD; use dma_gpio::wakeup::iwdg::{clear_wakeup_flags, init_watchdog_reset}; -use dma_gpio::sleep::shutdown; -use dma_gpio::sleep::standby; -use dma_gpio::sleep::stop3; +use dma_gpio::sleep::handler::execute_low_power; use dma_gpio::hw_uart_pc::init::{init_hw_uart_to_pc, LowPowerCmd, CMD_CH}; use {defmt_rtt as _, panic_probe as _}; @@ -43,14 +41,12 @@ async fn main(spawner: Spawner) { "Baud: {} bps | Watchdog: {}s\n\ UART1 TX=PA9 RX=PA10\n\ Modes via UART input:\n\ - [1] Standby + 8 KB SRAM2 retention\n\ - [2] Standby + full SRAM2 retention\n\ - [3] Standby — minimal power, SRAM2 lost\n\ - [4] Shutdown — lowest power, full reset on wake\n\ - [5] STOP3 mode with WFI\n\ - [6] STOP3 mode with WFE\n\ - [7] STOP3 mode with WFE (no event clear)", - BAUD, WATCHDOG_TIMEOUT_US / 1_000_000 + [1] Standby + 8 KB SRAM2 retention\n\ + [2] Standby + full SRAM2 retention\n\ + [3] Standby — minimal power, SRAM2 lost\n\ + [4] Shutdown — lowest power, full reset on wake\n\ + [5] STOP mode (then choose: 0-3 for mode, 1-3 for entry method)", + BAUD, WATCHDOG_TIMEOUT_US / 1_000_000 ); // disabling st-link debug @@ -66,41 +62,6 @@ async fn main(spawner: Spawner) { info!("ready for uart"); loop { let cmd = CMD_CH.receive().await; - match 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); - } - } + execute_low_power(cmd); } } diff --git a/semestralka_2_uart/src/hw_uart_pc/init.rs b/semestralka_2_uart/src/hw_uart_pc/init.rs index 5d47381..e61556f 100644 --- a/semestralka_2_uart/src/hw_uart_pc/init.rs +++ b/semestralka_2_uart/src/hw_uart_pc/init.rs @@ -7,6 +7,8 @@ use embassy_futures::yield_now; // UART HW init use crate::config::{BAUD, PIPE_HW_TX, PIPE_HW_RX}; use crate::hw_uart_pc::driver::uart_task; +use crate::sleep::StopEntry; +use crate::sleep::handler::execute_low_power; use static_cell::StaticCell; use embassy_stm32::usart::BufferedInterruptHandler; use embassy_stm32::usart::{BufferedUart, Config as UsartConfig}; @@ -21,67 +23,78 @@ bind_interrupts!(struct Irqs { USART1 => BufferedInterruptHandler; }); -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)] pub enum LowPowerCmd { Standby8k, // 1 StandbyFull, // 2 Standby, // 3 Shutdown, // 4 - Stop3Wfi, - Stop3Wfe, - Stop3WfeNoClear, + StopMode(StopModeConfig), +} + +#[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 = Channel::new(); #[embassy_executor::task] pub async fn uart_cmd_task() { - // Prompt once - let _ = PIPE_HW_TX - .write(b"Modes: 1=SB8, 2=SBfull, 3=SB, 4=SD, 5=STOP3(WFI), 6=STOP3(WFE), 7=STOP3(WFE no clear)\r\n") - .await; + let _ = PIPE_HW_TX.write( + b"\r\n\ + Modes:\r\n\ + [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 { let n = PIPE_HW_RX.read(&mut b).await; - if n == 0 { - continue; - } + if n == 0 { continue; } + match b[0] { - b'1' => { - let _ = PIPE_HW_TX.write(b"ACK 1: standby 8KB\r\n").await; - CMD_CH.send(LowPowerCmd::Standby8k).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'1' => CMD_CH.send(LowPowerCmd::Standby8k).await, + b'2' => CMD_CH.send(LowPowerCmd::StandbyFull).await, + b'3' => CMD_CH.send(LowPowerCmd::Standby).await, + b'4' => CMD_CH.send(LowPowerCmd::Shutdown).await, b'5' => { - let _ = PIPE_HW_TX.write(b"ACK 5: STOP3 with WFI\r\n").await; - CMD_CH.send(LowPowerCmd::Stop3Wfi).await; + // Expect 2 digits: e.g. b'5' + '13' = Stop1 WfeNoEventClear + 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; } } diff --git a/semestralka_2_uart/src/sleep/handler.rs b/semestralka_2_uart/src/sleep/handler.rs new file mode 100644 index 0000000..8a3b360 --- /dev/null +++ b/semestralka_2_uart/src/sleep/handler.rs @@ -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), + } + } + } +} diff --git a/semestralka_2_uart/src/sleep/mod.rs b/semestralka_2_uart/src/sleep/mod.rs index 4317160..a2d253e 100644 --- a/semestralka_2_uart/src/sleep/mod.rs +++ b/semestralka_2_uart/src/sleep/mod.rs @@ -2,4 +2,7 @@ pub mod standby; pub mod shutdown; -pub mod stop3; +pub mod stop; +pub mod handler; + +pub use stop::StopEntry; diff --git a/semestralka_2_uart/src/sleep/stop.rs b/semestralka_2_uart/src/sleep/stop.rs new file mode 100644 index 0000000..8b8ce62 --- /dev/null +++ b/semestralka_2_uart/src/sleep/stop.rs @@ -0,0 +1,55 @@ +// src/sleep/stop.rs + +/// How to enter STOPx mode (STOP0–STOP3) +#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)] +pub enum StopEntry { + Wfi, + Wfe, + WfeNoEventClear, +} + +impl From 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() +} diff --git a/semestralka_2_uart/src/sleep/stop3.rs b/semestralka_2_uart/src/sleep/stop3.rs deleted file mode 100644 index 72dad33..0000000 --- a/semestralka_2_uart/src/sleep/stop3.rs +++ /dev/null @@ -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 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);