Compare commits
4 Commits
20dfdbc335
...
c60f8db3c8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c60f8db3c8 | ||
|
|
4c7d9af29a | ||
|
|
88341314dd | ||
|
|
053cba171d |
@@ -10,10 +10,11 @@ use embassy_stm32::gpio::{Output, Level, Speed};
|
||||
use embassy_time::{Duration, Timer};
|
||||
|
||||
use dma_gpio::config::BAUD;
|
||||
use dma_gpio::wakeup::iwdg::{clear_wakeup_flags, init_watchdog_reset};
|
||||
use dma_gpio::wakeup::iwdg::clear_wakeup_flags;
|
||||
use dma_gpio::wakeup::gpio::gpio_wakeup;
|
||||
use dma_gpio::sleep::handler::execute_low_power;
|
||||
use dma_gpio::hw_uart_pc::init::{init_hw_uart_to_pc, LowPowerCmd, CMD_CH};
|
||||
use dma_gpio::logic::handler::execute_low_power;
|
||||
use dma_gpio::hw_uart_pc::init::init_hw_uart_to_pc;
|
||||
use dma_gpio::logic::uart_cmd::CMD_CH;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
@@ -30,7 +31,7 @@ async fn main(spawner: Spawner) {
|
||||
info!("LED ON (MCU awake)");
|
||||
|
||||
// LED BLINK
|
||||
spawner.spawn(led_blink(led).unwrap());
|
||||
// spawner.spawn(led_blink(led).unwrap());
|
||||
|
||||
// INIT HW UART
|
||||
init_hw_uart_to_pc(p.USART1, p.PA10, p.PA9, &spawner);
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
// src/hw_uart_pc/init.rs
|
||||
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::channel::Channel;
|
||||
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 crate::logic::uart_cmd::uart_cmd_task;
|
||||
use static_cell::StaticCell;
|
||||
use embassy_stm32::usart::BufferedInterruptHandler;
|
||||
use embassy_stm32::usart::{BufferedUart, Config as UsartConfig};
|
||||
@@ -23,101 +17,6 @@ bind_interrupts!(struct Irqs {
|
||||
USART1 => BufferedInterruptHandler<peripherals::USART1>;
|
||||
});
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
|
||||
pub enum LowPowerCmd {
|
||||
Standby8k, // 1
|
||||
StandbyFull, // 2
|
||||
Standby, // 3
|
||||
Shutdown, // 4
|
||||
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 {
|
||||
Stop0,
|
||||
Stop1,
|
||||
Stop2,
|
||||
Stop3,
|
||||
}
|
||||
|
||||
pub static CMD_CH: Channel<CriticalSectionRawMutex, LowPowerCmd, 1> = Channel::new();
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn uart_cmd_task() {
|
||||
async fn print_menu() {
|
||||
while PIPE_HW_TX.len() > 0 {
|
||||
embassy_time::Timer::after(embassy_time::Duration::from_millis(8)).await;
|
||||
}
|
||||
let _ = PIPE_HW_TX.write(
|
||||
b"\x1B[2J\x1B[H\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;
|
||||
embassy_time::Timer::after(embassy_time::Duration::from_millis(8)).await;
|
||||
}
|
||||
|
||||
print_menu().await;
|
||||
|
||||
let mut b = [0u8; 2];
|
||||
loop {
|
||||
b.fill(0);
|
||||
let n = PIPE_HW_RX.read(&mut b).await;
|
||||
if n == 0 { continue; }
|
||||
|
||||
match b[0] {
|
||||
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"Enter Stop mode number (0-3): ").await;
|
||||
b.fill(0);
|
||||
let n = PIPE_HW_RX.read(&mut b).await;
|
||||
if n == 0 { print_menu().await; continue; }
|
||||
let stop_mode = match b[0] {
|
||||
b'0' => StopMode::Stop0,
|
||||
b'1' => StopMode::Stop1,
|
||||
b'2' => StopMode::Stop2,
|
||||
b'3' => StopMode::Stop3,
|
||||
_ => { print_menu().await; continue; }
|
||||
};
|
||||
|
||||
if matches!(stop_mode, StopMode::Stop0) {
|
||||
CMD_CH.send(LowPowerCmd::StopMode(StopModeConfig {
|
||||
mode: stop_mode,
|
||||
entry: StopEntry::Wfi, // to tu je, lebo nejdem prepisovat kod, kvoli
|
||||
// pos**temu halu co si nevie urobit konzistentnost
|
||||
})).await;
|
||||
continue;
|
||||
}
|
||||
let _ = PIPE_HW_TX.write(b"Enter entry method (1=WFI,2=WFE,3=WFE no clear): ").await;
|
||||
b.fill(0);
|
||||
let n = PIPE_HW_RX.read(&mut b).await;
|
||||
if n == 0 { print_menu().await; continue; }
|
||||
let entry = match b[0] {
|
||||
b'1' => StopEntry::Wfi,
|
||||
b'2' => StopEntry::Wfe,
|
||||
b'3' => StopEntry::WfeNoEventClear,
|
||||
_ => { print_menu().await; continue; }
|
||||
};
|
||||
CMD_CH.send(LowPowerCmd::StopMode(StopModeConfig { mode: stop_mode, entry })).await;
|
||||
}
|
||||
_ => { print_menu().await; continue; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_hw_uart_to_pc(
|
||||
usart1: Peri<'static, USART1>,
|
||||
pa10: Peri<'static, PA10>,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// src/hw_uart_pc/mod.rs
|
||||
|
||||
pub mod driver;
|
||||
pub mod usart1;
|
||||
pub mod safety;
|
||||
|
||||
@@ -6,3 +6,4 @@ pub mod hw_uart_pc;
|
||||
pub mod config;
|
||||
pub mod sleep;
|
||||
pub mod wakeup;
|
||||
pub mod logic;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
// src/sleep/handler.rs
|
||||
// src/logic/handler.rs
|
||||
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_stm32::peripherals;
|
||||
use embassy_stm32::Peri;
|
||||
|
||||
use crate::sleep::stop::StopEntry;
|
||||
use crate::sleep::stop::*;
|
||||
use crate::sleep::stop::{enter_stop0, enter_stop1, enter_stop2, enter_stop3};
|
||||
use crate::sleep::sleep::{enter_sleep_mode, SleepEntry};
|
||||
use crate::sleep::{standby, shutdown};
|
||||
use crate::wakeup::iwdg::init_watchdog_reset;
|
||||
use crate::hw_uart_pc::init::{LowPowerCmd, StopMode, StopModeConfig};
|
||||
use crate::logic::uart_cmd::{LowPowerCmd, StopMode, StopModeConfig};
|
||||
|
||||
use defmt::info;
|
||||
|
||||
@@ -23,25 +24,25 @@ pub async fn execute_low_power(
|
||||
if let Some(wdg) = iwdg.take() {
|
||||
init_watchdog_reset(wdg).await;
|
||||
}
|
||||
super::standby::enter_standby_with_sram2_8kb();
|
||||
standby::enter_standby_with_sram2_8kb();
|
||||
}
|
||||
LowPowerCmd::StandbyFull => {
|
||||
info!("Entering Standby with full SRAM2 retention");
|
||||
if let Some(wdg) = iwdg.take() {
|
||||
init_watchdog_reset(wdg).await;
|
||||
}
|
||||
super::standby::enter_standby_with_sram2_full();
|
||||
standby::enter_standby_with_sram2_full();
|
||||
}
|
||||
LowPowerCmd::Standby => {
|
||||
info!("Entering minimal Standby");
|
||||
if let Some(wdg) = iwdg.take() {
|
||||
init_watchdog_reset(wdg).await;
|
||||
}
|
||||
super::standby::enter_standby();
|
||||
standby::enter_standby();
|
||||
}
|
||||
LowPowerCmd::Shutdown => {
|
||||
info!("Entering Shutdown mode");
|
||||
super::shutdown::enter_shutdown();
|
||||
shutdown::enter_shutdown();
|
||||
}
|
||||
LowPowerCmd::StopMode(StopModeConfig { mode, entry }) => {
|
||||
info!("Entering {:?} with {:?}", mode, entry);
|
||||
@@ -57,5 +58,10 @@ pub async fn execute_low_power(
|
||||
}
|
||||
}
|
||||
}
|
||||
LowPowerCmd::Sleep => {
|
||||
info!("Entering Sleep mode (WFI)...");
|
||||
enter_sleep_mode(SleepEntry::Wfi);
|
||||
info!("Woke up from Sleep mode.");
|
||||
}
|
||||
}
|
||||
}
|
||||
4
semestralka_2_uart/src/logic/mod.rs
Normal file
4
semestralka_2_uart/src/logic/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
// src/logic/mod.rs
|
||||
|
||||
pub mod handler;
|
||||
pub mod uart_cmd;
|
||||
106
semestralka_2_uart/src/logic/uart_cmd.rs
Normal file
106
semestralka_2_uart/src/logic/uart_cmd.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
// src/logic/uart_cmd.rs
|
||||
|
||||
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
|
||||
use embassy_sync::channel::Channel;
|
||||
|
||||
// UART HW init
|
||||
use crate::config::{PIPE_HW_TX, PIPE_HW_RX};
|
||||
use crate::sleep::StopEntry;
|
||||
|
||||
pub static CMD_CH: Channel<CriticalSectionRawMutex, LowPowerCmd, 1> = Channel::new();
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
|
||||
pub enum LowPowerCmd {
|
||||
Standby8k, // 1
|
||||
StandbyFull, // 2
|
||||
Standby, // 3
|
||||
Shutdown, // 4
|
||||
StopMode(StopModeConfig),
|
||||
Sleep,
|
||||
}
|
||||
|
||||
#[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 {
|
||||
Stop0,
|
||||
Stop1,
|
||||
Stop2,
|
||||
Stop3,
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
pub async fn uart_cmd_task() {
|
||||
async fn print_menu() {
|
||||
while PIPE_HW_TX.len() > 0 {
|
||||
embassy_time::Timer::after(embassy_time::Duration::from_millis(8)).await;
|
||||
}
|
||||
let _ = PIPE_HW_TX.write(
|
||||
b"\x1B[2J\x1B[H\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\
|
||||
[6] Sleep mode (WFI or WFE)\r\n\
|
||||
"
|
||||
).await;
|
||||
embassy_time::Timer::after(embassy_time::Duration::from_millis(8)).await;
|
||||
}
|
||||
|
||||
print_menu().await;
|
||||
|
||||
let mut b = [0u8; 2];
|
||||
loop {
|
||||
b.fill(0);
|
||||
let n = PIPE_HW_RX.read(&mut b).await;
|
||||
if n == 0 { continue; }
|
||||
|
||||
match b[0] {
|
||||
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"Enter Stop mode number (0-3): ").await;
|
||||
b.fill(0);
|
||||
let n = PIPE_HW_RX.read(&mut b).await;
|
||||
if n == 0 { print_menu().await; continue; }
|
||||
let stop_mode = match b[0] {
|
||||
b'0' => StopMode::Stop0,
|
||||
b'1' => StopMode::Stop1,
|
||||
b'2' => StopMode::Stop2,
|
||||
b'3' => StopMode::Stop3,
|
||||
_ => { print_menu().await; continue; }
|
||||
};
|
||||
|
||||
if matches!(stop_mode, StopMode::Stop0) {
|
||||
CMD_CH.send(LowPowerCmd::StopMode(StopModeConfig {
|
||||
mode: stop_mode,
|
||||
entry: StopEntry::Wfi, // to tu je, lebo nejdem prepisovat kod, kvoli
|
||||
// pos**temu halu co si nevie urobit konzistentnost
|
||||
})).await;
|
||||
continue;
|
||||
}
|
||||
let _ = PIPE_HW_TX.write(b"Enter entry method (1=WFI,2=WFE,3=WFE no clear): ").await;
|
||||
b.fill(0);
|
||||
let n = PIPE_HW_RX.read(&mut b).await;
|
||||
if n == 0 { print_menu().await; continue; }
|
||||
let entry = match b[0] {
|
||||
b'1' => StopEntry::Wfi,
|
||||
b'2' => StopEntry::Wfe,
|
||||
b'3' => StopEntry::WfeNoEventClear,
|
||||
_ => { print_menu().await; continue; }
|
||||
};
|
||||
CMD_CH.send(LowPowerCmd::StopMode(StopModeConfig { mode: stop_mode, entry })).await;
|
||||
},
|
||||
b'6' => CMD_CH.send(LowPowerCmd::Sleep).await,
|
||||
_ => { print_menu().await; continue; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,6 @@
|
||||
pub mod standby;
|
||||
pub mod shutdown;
|
||||
pub mod stop;
|
||||
pub mod handler;
|
||||
pub mod sleep;
|
||||
|
||||
pub use stop::StopEntry;
|
||||
|
||||
19
semestralka_2_uart/src/sleep/sleep.rs
Normal file
19
semestralka_2_uart/src/sleep/sleep.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
// src/sleep/sleep.rs
|
||||
|
||||
use cortex_m::Peripherals;
|
||||
|
||||
#[derive(Clone, Copy, Debug, defmt::Format)]
|
||||
pub enum SleepEntry {
|
||||
Wfi,
|
||||
Wfe,
|
||||
}
|
||||
|
||||
pub fn enter_sleep_mode(entry: SleepEntry) {
|
||||
let mut core = unsafe { Peripherals::steal() };
|
||||
core.SCB.clear_sleepdeep();
|
||||
|
||||
match entry {
|
||||
SleepEntry::Wfi => cortex_m::asm::wfi(),
|
||||
SleepEntry::Wfe => cortex_m::asm::wfe(),
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ pub fn enter_standby() -> ! {
|
||||
HAL_PWR_EnterSTANDBYMode();
|
||||
}
|
||||
|
||||
cortex_m::asm::udf(); // never happen marker
|
||||
cortex_m::asm::udf();
|
||||
}
|
||||
|
||||
pub fn enter_standby_with_sram2_8kb() -> ! {
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
// src/sleep/stop.rs
|
||||
|
||||
use cortex_m::peripheral::SCB;
|
||||
use cortex_m::Peripherals;
|
||||
use cortex_m::asm;
|
||||
|
||||
/// How to enter STOPx mode (STOP0–STOP3)
|
||||
/// Enter STOPx mode parameter
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, defmt::Format)]
|
||||
pub enum StopEntry {
|
||||
Wfi,
|
||||
|
||||
@@ -3,23 +3,23 @@
|
||||
use defmt::info;
|
||||
use embassy_stm32::exti::ExtiInput;
|
||||
use embassy_stm32::gpio::Pull;
|
||||
use embassy_stm32::{peripherals, interrupt};
|
||||
use embassy_stm32::peripherals;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_hal_internal::Peri;
|
||||
|
||||
/// GPIO pin as an EXTI wake‑up source.
|
||||
/// GPIO pin as an EXTI wake-up source.
|
||||
#[embassy_executor::task]
|
||||
pub async fn gpio_wakeup(
|
||||
pin: Peri<'static, peripherals::PA0>,
|
||||
ch: Peri<'static, peripherals::EXTI0>
|
||||
) {
|
||||
info!("Configuring EXTI wake input on PA0 (rising edge)");
|
||||
info!("EXTI wake input on PA0");
|
||||
let mut btn = ExtiInput::new(pin, ch, Pull::Up);
|
||||
|
||||
loop {
|
||||
info!("Waiting for rising edge on PA0");
|
||||
info!("Waiting for falling edge on PA0");
|
||||
btn.wait_for_falling_edge().await;
|
||||
info!("GPIO wake‑up: event detected!");
|
||||
info!("GPIO wake-up");
|
||||
Timer::after(Duration::from_millis(50)).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,10 +10,8 @@ use crate::sleep::standby;
|
||||
|
||||
use crate::config::WATCHDOG_TIMEOUT_US;
|
||||
|
||||
/// Clears system reset and standby flags after wakeup.
|
||||
/// Call early in startup
|
||||
///
|
||||
/// # Registers
|
||||
/// - `RCC_CSR` — Reset and Clock Control / Status
|
||||
/// - `PWR_SR` — Power Control / Status
|
||||
pub fn clear_wakeup_flags() {
|
||||
@@ -34,10 +32,10 @@ pub fn clear_wakeup_flags() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Initializes the Independent Watchdog (IWDG) timer.
|
||||
/// Init Independent Watchdog (IWDG) timer.
|
||||
/// Timeout value is configured in `WATCHDOG_TIMEOUT_US` from config.rs
|
||||
pub async fn init_watchdog_reset(iwdg: Peri<'static, peripherals::IWDG>) {
|
||||
info!("Initializing watchdog after watchdog wake...");
|
||||
info!("Init watchdog after watchdog wake...");
|
||||
let mut watchdog = IndependentWatchdog::new(iwdg, WATCHDOG_TIMEOUT_US);
|
||||
watchdog.unleash();
|
||||
Timer::after(Duration::from_millis(10)).await;
|
||||
|
||||
Reference in New Issue
Block a user