Compare commits
14 Commits
7184ce9898
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c60f8db3c8 | ||
|
|
4c7d9af29a | ||
|
|
88341314dd | ||
|
|
053cba171d | ||
|
|
20dfdbc335 | ||
|
|
f4ca3071f0 | ||
|
|
bbddc7cf9c | ||
|
|
49cc8dcc71 | ||
|
|
58561ec392 | ||
|
|
f36a9fd9e2 | ||
|
|
2c9433cb84 | ||
|
|
72a731abef | ||
|
|
55398e8459 | ||
|
|
e2afb2f2f0 |
@@ -16,7 +16,7 @@ embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", branch =
|
|||||||
embassy-time = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["tick-hz-32_768"] }
|
embassy-time = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["tick-hz-32_768"] }
|
||||||
embassy-hal-internal = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
|
embassy-hal-internal = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
|
||||||
embassy-usb = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
|
embassy-usb = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" }
|
||||||
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["unstable-pac", "stm32u575zi", "time-driver-tim2", "memory-x", "defmt"] }
|
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["unstable-pac", "stm32u575zi", "time-driver-tim2", "memory-x", "defmt", "exti"] }
|
||||||
|
|
||||||
embedded-hal = "1.0.0"
|
embedded-hal = "1.0.0"
|
||||||
embedded-graphics = "0.8.1"
|
embedded-graphics = "0.8.1"
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ fn main() {
|
|||||||
build.file(hal_driver.join("Src").join(src));
|
build.file(hal_driver.join("Src").join(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build.file("src/c_ll/stop0_ll.c");
|
||||||
|
|
||||||
build
|
build
|
||||||
.include(hal_driver.join("Inc"))
|
.include(hal_driver.join("Inc"))
|
||||||
.include(device.join("Include"))
|
.include(device.join("Include"))
|
||||||
|
|||||||
@@ -4,66 +4,19 @@
|
|||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use embassy_stm32::pac;
|
use embassy_stm32::pac;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::{Spawner, task};
|
||||||
use embassy_futures::yield_now;
|
|
||||||
use embassy_stm32::bind_interrupts;
|
|
||||||
use embassy_stm32::peripherals;
|
|
||||||
use embassy_stm32::Config;
|
use embassy_stm32::Config;
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, channel::Channel};
|
|
||||||
use embassy_stm32::usart::{BufferedUart, Config as UsartConfig, BufferedInterruptHandler};
|
|
||||||
use embassy_stm32::gpio::{Output, Level, Speed};
|
use embassy_stm32::gpio::{Output, Level, Speed};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
|
|
||||||
use static_cell::StaticCell;
|
use dma_gpio::config::BAUD;
|
||||||
use dma_gpio::config::{
|
use dma_gpio::wakeup::iwdg::clear_wakeup_flags;
|
||||||
BAUD, PIPE_HW_RX, PIPE_HW_TX,
|
use dma_gpio::wakeup::gpio::gpio_wakeup;
|
||||||
};
|
use dma_gpio::logic::handler::execute_low_power;
|
||||||
use dma_gpio::hw_uart_pc::driver::uart_task;
|
use dma_gpio::hw_uart_pc::init::init_hw_uart_to_pc;
|
||||||
use dma_gpio::wakeup::iwdg::{clear_wakeup_flags, init_watchdog_reset};
|
use dma_gpio::logic::uart_cmd::CMD_CH;
|
||||||
use dma_gpio::sleep::shutdown;
|
|
||||||
use dma_gpio::sleep::standby;
|
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
|
||||||
USART1 => BufferedInterruptHandler<peripherals::USART1>;
|
|
||||||
});
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
||||||
enum LowPowerCmd {
|
|
||||||
Standby8k, // 1
|
|
||||||
StandbyFull, // 2
|
|
||||||
Standby, // 3
|
|
||||||
Shutdown, // 4
|
|
||||||
}
|
|
||||||
|
|
||||||
static CMD_CH: Channel<CriticalSectionRawMutex, LowPowerCmd, 1> = Channel::new();
|
|
||||||
|
|
||||||
#[embassy_executor::task]
|
|
||||||
async fn uart_cmd_task() {
|
|
||||||
// Prompt once
|
|
||||||
let _ = PIPE_HW_TX
|
|
||||||
.write(b"Modes: 1=SB8, 2=SBfull, 3=SB, 4=SD\r\n")
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let mut b = [0u8; 1];
|
|
||||||
loop {
|
|
||||||
let n = PIPE_HW_RX.read(&mut b).await;
|
|
||||||
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'\r' | b'\n' | b' ' => {}
|
|
||||||
_ => { let _ = PIPE_HW_TX.write(b"ERR: use 1|2|3|4\r\n").await; }
|
|
||||||
}
|
|
||||||
yield_now().await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
info!("boot");
|
info!("boot");
|
||||||
@@ -77,24 +30,11 @@ async fn main(spawner: Spawner) {
|
|||||||
led.set_high();
|
led.set_high();
|
||||||
info!("LED ON (MCU awake)");
|
info!("LED ON (MCU awake)");
|
||||||
|
|
||||||
// HARDWARE UART to the PC
|
// LED BLINK
|
||||||
let mut cfg = UsartConfig::default();
|
// spawner.spawn(led_blink(led).unwrap());
|
||||||
cfg.baudrate = BAUD;
|
|
||||||
static TX_BUF: StaticCell<[u8; 256]> = StaticCell::new();
|
// INIT HW UART
|
||||||
static RX_BUF: StaticCell<[u8; 256]> = StaticCell::new();
|
init_hw_uart_to_pc(p.USART1, p.PA10, p.PA9, &spawner);
|
||||||
let uart = BufferedUart::new(
|
|
||||||
p.USART1,
|
|
||||||
p.PA10, // RX pin
|
|
||||||
p.PA9, // TX pin
|
|
||||||
TX_BUF.init([0; 256]),
|
|
||||||
RX_BUF.init([0; 256]),
|
|
||||||
Irqs,
|
|
||||||
cfg,
|
|
||||||
).unwrap();
|
|
||||||
// let yield_period = usart1::setup_and_spawn(BAUD);
|
|
||||||
spawner.spawn(uart_task(uart, &PIPE_HW_TX, &PIPE_HW_RX).unwrap());
|
|
||||||
spawner.spawn(uart_cmd_task().unwrap());
|
|
||||||
// END OF HARDWARE UART to the PC
|
|
||||||
|
|
||||||
// DEBUG INFO
|
// DEBUG INFO
|
||||||
let dbg = pac::DBGMCU;
|
let dbg = pac::DBGMCU;
|
||||||
@@ -109,7 +49,8 @@ async fn main(spawner: Spawner) {
|
|||||||
[1] Standby + 8 KB SRAM2 retention\n\
|
[1] Standby + 8 KB SRAM2 retention\n\
|
||||||
[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",
|
[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
|
BAUD, WATCHDOG_TIMEOUT_US / 1_000_000
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -124,28 +65,19 @@ async fn main(spawner: Spawner) {
|
|||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
|
||||||
info!("ready for uart");
|
info!("ready for uart");
|
||||||
|
let mut iwdg = Some(p.IWDG);
|
||||||
|
|
||||||
|
spawner.spawn(gpio_wakeup(p.PA0, p.EXTI0).unwrap()); // exti wake up
|
||||||
loop {
|
loop {
|
||||||
let cmd = CMD_CH.receive().await;
|
let cmd = CMD_CH.receive().await;
|
||||||
match cmd {
|
execute_low_power(cmd, &mut iwdg).await;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[task]
|
||||||
|
async fn led_blink(mut led: Output<'static>) {
|
||||||
|
loop {
|
||||||
|
led.toggle();
|
||||||
|
Timer::after(Duration::from_millis(300)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
semestralka_2_uart/src/c_ll/stop0_ll.c
Normal file
8
semestralka_2_uart/src/c_ll/stop0_ll.c
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "stm32u5xx_ll_pwr.h"
|
||||||
|
|
||||||
|
void rust_LL_PWR_SetPowerMode(unsigned int mode)
|
||||||
|
{
|
||||||
|
// Configure STOP0
|
||||||
|
LL_PWR_SetPowerMode(mode);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ pub async fn uart_task(
|
|||||||
}
|
}
|
||||||
// Outgoing data waiting in TX pipe
|
// Outgoing data waiting in TX pipe
|
||||||
Either::Second(n) => {
|
Either::Second(n) => {
|
||||||
unwrap!(uart.write(&tx_buf[..n]).await);
|
unwrap!(uart.write_all(&tx_buf[..n]).await);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield_now().await;
|
yield_now().await;
|
||||||
|
|||||||
47
semestralka_2_uart/src/hw_uart_pc/init.rs
Normal file
47
semestralka_2_uart/src/hw_uart_pc/init.rs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// src/hw_uart_pc/init.rs
|
||||||
|
|
||||||
|
use crate::config::{BAUD, PIPE_HW_TX, PIPE_HW_RX};
|
||||||
|
use crate::hw_uart_pc::driver::uart_task;
|
||||||
|
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};
|
||||||
|
use embassy_stm32::peripherals;
|
||||||
|
use embassy_stm32::bind_interrupts;
|
||||||
|
use embassy_executor::Spawner;
|
||||||
|
use embassy_hal_internal::Peri;
|
||||||
|
use embassy_stm32::peripherals::{USART1, PA9, PA10};
|
||||||
|
use defmt::info;
|
||||||
|
|
||||||
|
bind_interrupts!(struct Irqs {
|
||||||
|
USART1 => BufferedInterruptHandler<peripherals::USART1>;
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn init_hw_uart_to_pc(
|
||||||
|
usart1: Peri<'static, USART1>,
|
||||||
|
pa10: Peri<'static, PA10>,
|
||||||
|
pa9: Peri<'static, PA9>,
|
||||||
|
spawner: &Spawner,
|
||||||
|
) {
|
||||||
|
let mut cfg = UsartConfig::default();
|
||||||
|
cfg.baudrate = BAUD;
|
||||||
|
|
||||||
|
static TX_BUF: StaticCell<[u8; 256]> = StaticCell::new();
|
||||||
|
static RX_BUF: StaticCell<[u8; 256]> = StaticCell::new();
|
||||||
|
|
||||||
|
let uart = BufferedUart::new(
|
||||||
|
usart1,
|
||||||
|
pa10, // RX pin
|
||||||
|
pa9, // TX pin
|
||||||
|
TX_BUF.init([0; 256]),
|
||||||
|
RX_BUF.init([0; 256]),
|
||||||
|
Irqs,
|
||||||
|
cfg,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
spawner.spawn(uart_task(uart, &PIPE_HW_TX, &PIPE_HW_RX).unwrap());
|
||||||
|
spawner.spawn(uart_cmd_task().unwrap());
|
||||||
|
|
||||||
|
info!("USART1 initialized @ {} bps", BAUD);
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
// src/hw_uart_pc/mod.rs
|
// src/hw_uart_pc/mod.rs
|
||||||
|
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
pub mod usart1;
|
pub mod usart1;
|
||||||
pub mod safety;
|
pub mod safety;
|
||||||
|
pub mod init;
|
||||||
|
|||||||
@@ -6,3 +6,4 @@ pub mod hw_uart_pc;
|
|||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod sleep;
|
pub mod sleep;
|
||||||
pub mod wakeup;
|
pub mod wakeup;
|
||||||
|
pub mod logic;
|
||||||
|
|||||||
67
semestralka_2_uart/src/logic/handler.rs
Normal file
67
semestralka_2_uart/src/logic/handler.rs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// src/logic/handler.rs
|
||||||
|
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use embassy_stm32::peripherals;
|
||||||
|
use embassy_stm32::Peri;
|
||||||
|
|
||||||
|
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::logic::uart_cmd::{LowPowerCmd, StopMode, StopModeConfig};
|
||||||
|
|
||||||
|
use defmt::info;
|
||||||
|
|
||||||
|
pub async fn execute_low_power(
|
||||||
|
cmd: LowPowerCmd,
|
||||||
|
iwdg: &mut Option<Peri<'static, peripherals::IWDG>>
|
||||||
|
) {
|
||||||
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
|
||||||
|
match cmd {
|
||||||
|
LowPowerCmd::Standby8k => {
|
||||||
|
info!("Entering Standby with 8KB SRAM2 retention");
|
||||||
|
if let Some(wdg) = iwdg.take() {
|
||||||
|
init_watchdog_reset(wdg).await;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
standby::enter_standby_with_sram2_full();
|
||||||
|
}
|
||||||
|
LowPowerCmd::Standby => {
|
||||||
|
info!("Entering minimal Standby");
|
||||||
|
if let Some(wdg) = iwdg.take() {
|
||||||
|
init_watchdog_reset(wdg).await;
|
||||||
|
}
|
||||||
|
standby::enter_standby();
|
||||||
|
}
|
||||||
|
LowPowerCmd::Shutdown => {
|
||||||
|
info!("Entering Shutdown mode");
|
||||||
|
shutdown::enter_shutdown();
|
||||||
|
}
|
||||||
|
LowPowerCmd::StopMode(StopModeConfig { mode, entry }) => {
|
||||||
|
info!("Entering {:?} with {:?}", mode, entry);
|
||||||
|
match mode {
|
||||||
|
StopMode::Stop0 => enter_stop0(),
|
||||||
|
StopMode::Stop1 => enter_stop1(entry),
|
||||||
|
StopMode::Stop2 => enter_stop2(entry),
|
||||||
|
StopMode::Stop3 => {
|
||||||
|
if let Some(wdg) = iwdg.take() {
|
||||||
|
init_watchdog_reset(wdg).await;
|
||||||
|
}
|
||||||
|
enter_stop3(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,3 +2,7 @@
|
|||||||
|
|
||||||
pub mod standby;
|
pub mod standby;
|
||||||
pub mod shutdown;
|
pub mod shutdown;
|
||||||
|
pub mod stop;
|
||||||
|
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();
|
HAL_PWR_EnterSTANDBYMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
cortex_m::asm::udf(); // never happen marker
|
cortex_m::asm::udf();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn enter_standby_with_sram2_8kb() -> ! {
|
pub fn enter_standby_with_sram2_8kb() -> ! {
|
||||||
|
|||||||
69
semestralka_2_uart/src/sleep/stop.rs
Normal file
69
semestralka_2_uart/src/sleep/stop.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
// src/sleep/stop.rs
|
||||||
|
|
||||||
|
use cortex_m::Peripherals;
|
||||||
|
use cortex_m::asm;
|
||||||
|
|
||||||
|
/// Enter STOPx mode parameter
|
||||||
|
#[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_stop0() {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn rust_LL_PWR_SetPowerMode(mode: u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LL_PWR_STOP0_MODE: u32 = 0; //stm32u5xx_ll_pwr.h
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
rust_LL_PWR_SetPowerMode(LL_PWR_STOP0_MODE);
|
||||||
|
|
||||||
|
let mut core = Peripherals::steal();
|
||||||
|
core.SCB.set_sleepdeep();
|
||||||
|
asm::wfi();
|
||||||
|
core.SCB.clear_sleepdeep();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enter_stop1(entry: StopEntry) {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn HAL_PWREx_EnterSTOP1Mode(entry: u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
HAL_PWREx_EnterSTOP1Mode(entry.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enter_stop2(entry: StopEntry) {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn HAL_PWREx_EnterSTOP2Mode(entry: u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
HAL_PWREx_EnterSTOP2Mode(entry.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enter_stop3(entry: StopEntry) {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn HAL_PWREx_EnterSTOP3Mode(entry: u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
HAL_PWREx_EnterSTOP3Mode(entry.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
25
semestralka_2_uart/src/wakeup/gpio.rs
Normal file
25
semestralka_2_uart/src/wakeup/gpio.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// src/wakeup/gpio.rs
|
||||||
|
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_stm32::exti::ExtiInput;
|
||||||
|
use embassy_stm32::gpio::Pull;
|
||||||
|
use embassy_stm32::peripherals;
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use embassy_hal_internal::Peri;
|
||||||
|
|
||||||
|
/// 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!("EXTI wake input on PA0");
|
||||||
|
let mut btn = ExtiInput::new(pin, ch, Pull::Up);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
info!("Waiting for falling edge on PA0");
|
||||||
|
btn.wait_for_falling_edge().await;
|
||||||
|
info!("GPIO wake-up");
|
||||||
|
Timer::after(Duration::from_millis(50)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,13 +10,8 @@ use crate::sleep::standby;
|
|||||||
|
|
||||||
use crate::config::WATCHDOG_TIMEOUT_US;
|
use crate::config::WATCHDOG_TIMEOUT_US;
|
||||||
|
|
||||||
/// Clears system reset and standby flags after wakeup.
|
/// Call early in startup
|
||||||
///
|
///
|
||||||
/// Call early in startup to:
|
|
||||||
/// - Clear reset flags by setting `RMVF` in `RCC_CSR`.
|
|
||||||
/// - If `SBF` in `PWR_SR` is set (woke from Standby), clear it.
|
|
||||||
///
|
|
||||||
/// # Registers
|
|
||||||
/// - `RCC_CSR` — Reset and Clock Control / Status
|
/// - `RCC_CSR` — Reset and Clock Control / Status
|
||||||
/// - `PWR_SR` — Power Control / Status
|
/// - `PWR_SR` — Power Control / Status
|
||||||
pub fn clear_wakeup_flags() {
|
pub fn clear_wakeup_flags() {
|
||||||
@@ -37,13 +32,10 @@ pub fn clear_wakeup_flags() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initializes the Independent Watchdog (IWDG) timer.
|
/// Init Independent Watchdog (IWDG) timer.
|
||||||
/// Wakeup source: Can wake the system from Standby mode on timeout
|
/// Timeout value is configured in `WATCHDOG_TIMEOUT_US` from config.rs
|
||||||
///
|
pub async fn init_watchdog_reset(iwdg: Peri<'static, peripherals::IWDG>) {
|
||||||
/// # Timing
|
info!("Init watchdog after watchdog wake...");
|
||||||
/// - Timeout value is configured in `WATCHDOG_TIMEOUT_US` from config.rs
|
|
||||||
pub async fn init_watchdog_reset(iwdg: Peri<'_, peripherals::IWDG>) {
|
|
||||||
info!("Initializing watchdog after watchdog wake...");
|
|
||||||
let mut watchdog = IndependentWatchdog::new(iwdg, WATCHDOG_TIMEOUT_US);
|
let mut watchdog = IndependentWatchdog::new(iwdg, WATCHDOG_TIMEOUT_US);
|
||||||
watchdog.unleash();
|
watchdog.unleash();
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
// src/wakeup/mod.rs
|
// src/wakeup/mod.rs
|
||||||
|
|
||||||
pub mod iwdg;
|
pub mod iwdg;
|
||||||
|
pub mod gpio;
|
||||||
|
|||||||
Reference in New Issue
Block a user