diff --git a/semestralka_2_uart/src/bin/main.rs b/semestralka_2_uart/src/bin/main.rs index d13f4fa..8055405 100644 --- a/semestralka_2_uart/src/bin/main.rs +++ b/semestralka_2_uart/src/bin/main.rs @@ -13,6 +13,7 @@ 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::hw_uart_pc::init::{init_hw_uart_to_pc, LowPowerCmd, CMD_CH}; use {defmt_rtt as _, panic_probe as _}; @@ -45,7 +46,10 @@ async fn main(spawner: Spawner) { [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", + [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 ); @@ -82,6 +86,21 @@ async fn main(spawner: Spawner) { 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); + } } } } diff --git a/semestralka_2_uart/src/hw_uart_pc/init.rs b/semestralka_2_uart/src/hw_uart_pc/init.rs index 1b8263f..5d47381 100644 --- a/semestralka_2_uart/src/hw_uart_pc/init.rs +++ b/semestralka_2_uart/src/hw_uart_pc/init.rs @@ -27,6 +27,9 @@ pub enum LowPowerCmd { StandbyFull, // 2 Standby, // 3 Shutdown, // 4 + Stop3Wfi, + Stop3Wfe, + Stop3WfeNoClear, } pub static CMD_CH: Channel = Channel::new(); @@ -35,7 +38,7 @@ pub static CMD_CH: Channel = Channel::n pub async fn uart_cmd_task() { // Prompt once let _ = PIPE_HW_TX - .write(b"Modes: 1=SB8, 2=SBfull, 3=SB, 4=SD\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") .await; let mut b = [0u8; 1]; @@ -61,8 +64,22 @@ pub async fn uart_cmd_task() { let _ = PIPE_HW_TX.write(b"ACK 4: shutdown\r\n").await; 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; + } + 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\r\n").await; } + _ => { + let _ = PIPE_HW_TX.write(b"ERR: use 1|2|3|4|5|6|7\r\n").await; + } } yield_now().await; } diff --git a/semestralka_2_uart/src/sleep/mod.rs b/semestralka_2_uart/src/sleep/mod.rs index eec9227..4317160 100644 --- a/semestralka_2_uart/src/sleep/mod.rs +++ b/semestralka_2_uart/src/sleep/mod.rs @@ -2,3 +2,4 @@ pub mod standby; pub mod shutdown; +pub mod stop3; diff --git a/semestralka_2_uart/src/sleep/stop3.rs b/semestralka_2_uart/src/sleep/stop3.rs new file mode 100644 index 0000000..72dad33 --- /dev/null +++ b/semestralka_2_uart/src/sleep/stop3.rs @@ -0,0 +1,39 @@ +// 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);