Compare commits
5 Commits
9ab8f94f92
...
3ebbd97760
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ebbd97760 | ||
|
|
68d13ebbbc | ||
|
|
434e2b3d21 | ||
|
|
33543099c2 | ||
|
|
9be1d514fb |
@@ -13,12 +13,12 @@ async fn main(_spawner: Spawner) {
|
|||||||
let p = init(Config::default());
|
let p = init(Config::default());
|
||||||
|
|
||||||
let mut output_pin = Output::new(p.PA3, Level::Low, Speed::Low);
|
let mut output_pin = Output::new(p.PA3, Level::Low, Speed::Low);
|
||||||
let mut artificial_ground = Output::new(p.PB0, Level::Low, Speed::Low);
|
let mut _artificial_ground = Output::new(p.PB0, Level::Low, Speed::Low);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
output_pin.set_high();
|
output_pin.set_high();
|
||||||
Timer::after(Duration::from_millis(500)).await;
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
output_pin.set_low();
|
// output_pin.set_low();
|
||||||
Timer::after(Duration::from_millis(500)).await;
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use defmt::*;
|
use defmt::*;
|
||||||
use core::ptr::addr_of_mut;
|
|
||||||
use embassy_stm32::pac;
|
use embassy_stm32::pac;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_futures::yield_now;
|
use embassy_futures::yield_now;
|
||||||
@@ -12,7 +11,6 @@ use embassy_stm32::peripherals;
|
|||||||
use embassy_stm32::Config;
|
use embassy_stm32::Config;
|
||||||
use embassy_stm32::usart::{BufferedUart, Config as UsartConfig, BufferedInterruptHandler};
|
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_stm32::wdg::IndependentWatchdog;
|
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
|
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
@@ -20,38 +18,27 @@ use dma_gpio::config::{
|
|||||||
BAUD, PIPE_HW_RX, PIPE_HW_TX,
|
BAUD, PIPE_HW_RX, PIPE_HW_TX,
|
||||||
};
|
};
|
||||||
use dma_gpio::hw_uart_pc::{driver::uart_task, usart1};
|
use dma_gpio::hw_uart_pc::{driver::uart_task, usart1};
|
||||||
|
use dma_gpio::wakeup::iwdg::{clear_wakeup_flags, init_watchdog};
|
||||||
|
use dma_gpio::sleep::shutdown::enter_shutdown;
|
||||||
|
use dma_gpio::sleep::standby;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
bind_interrupts!(struct Irqs {
|
bind_interrupts!(struct Irqs {
|
||||||
USART1 => BufferedInterruptHandler<peripherals::USART1>;
|
USART1 => BufferedInterruptHandler<peripherals::USART1>;
|
||||||
});
|
});
|
||||||
|
|
||||||
unsafe extern "C" {
|
|
||||||
fn HAL_PWR_EnterSTANDBYMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
const PWR_FLAG_SBF: u32 = 1 << 1;
|
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
info!("boot");
|
info!("boot");
|
||||||
let mut config = Config::default();
|
let p = embassy_stm32::init(Config::default());
|
||||||
config.enable_debug_during_sleep = true;
|
|
||||||
let p = embassy_stm32::init(config);
|
|
||||||
let mut led = Output::new(p.PA3, Level::Low, Speed::Low);
|
let mut led = Output::new(p.PA3, Level::Low, Speed::Low);
|
||||||
let _led_ground = Output::new(p.PB0, Level::Low, Speed::Low);
|
let _led_ground = Output::new(p.PB0, Level::Low, Speed::Low);
|
||||||
info!("init m8");
|
info!("init m8");
|
||||||
|
|
||||||
// Clearing after the wakeup
|
clear_wakeup_flags();
|
||||||
let rcc = pac::RCC;
|
|
||||||
rcc.csr().write(|w| w.set_rmvf(true));
|
led.set_high();
|
||||||
|
info!("LED ON (MCU awake)");
|
||||||
// Check wake source
|
|
||||||
let pwr = pac::PWR;
|
|
||||||
if pwr.sr().read().sbf() {
|
|
||||||
info!("Woke from Standby via watchdog");
|
|
||||||
pwr.sr().write(|w| w.set_sbf(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
// HARDWARE UART to the PC
|
// HARDWARE UART to the PC
|
||||||
let mut cfg = UsartConfig::default();
|
let mut cfg = UsartConfig::default();
|
||||||
@@ -76,27 +63,17 @@ async fn main(spawner: Spawner) {
|
|||||||
info!("DBGMCU CR: dbg_stop={}, dbg_standby={}", cr.dbg_stop(), cr.dbg_standby());
|
info!("DBGMCU CR: dbg_stop={}, dbg_standby={}", cr.dbg_stop(), cr.dbg_standby());
|
||||||
|
|
||||||
// MAIN LOOP
|
// MAIN LOOP
|
||||||
info!("tick start");
|
|
||||||
led.set_high();
|
|
||||||
info!("LED IS HIGH");
|
|
||||||
Timer::after(Duration::from_millis(500)).await;
|
Timer::after(Duration::from_millis(500)).await;
|
||||||
led.set_low();
|
|
||||||
info!("LED IS LOW");
|
|
||||||
Timer::after(Duration::from_millis(500)).await;
|
|
||||||
led.set_high();
|
|
||||||
info!("LED IS HIGH");
|
|
||||||
|
|
||||||
info!("Iwdg init");
|
init_watchdog(p.IWDG).await;
|
||||||
let mut watchdog = IndependentWatchdog::new(p.IWDG, 2_000_000); // 2 seconds
|
|
||||||
watchdog.unleash();
|
|
||||||
Timer::after(Duration::from_millis(10)).await;
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
|
||||||
unsafe {
|
|
||||||
info!("Standby...");
|
|
||||||
HAL_PWR_EnterSTANDBYMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
info!("entering shutdown");
|
||||||
|
// enter_shutdown();
|
||||||
|
info!("shutdown");
|
||||||
|
standby::enter_standby_with_sram2_full();
|
||||||
cortex_m::asm::wfi();
|
cortex_m::asm::wfi();
|
||||||
|
yield_now().await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,5 +6,7 @@ pub const BAUD: u32 = 9_600;
|
|||||||
pub const PIPE_HW_TX_SIZE: usize = 1024;
|
pub const PIPE_HW_TX_SIZE: usize = 1024;
|
||||||
pub const PIPE_HW_RX_SIZE: usize = 1024;
|
pub const PIPE_HW_RX_SIZE: usize = 1024;
|
||||||
|
|
||||||
|
pub const WATCHDOG_TIMEOUT_US: u32 = 2_000_000; // 2 seconds
|
||||||
|
|
||||||
pub static PIPE_HW_TX: Pipe<CriticalSectionRawMutex, PIPE_HW_TX_SIZE> = Pipe::new();
|
pub static PIPE_HW_TX: Pipe<CriticalSectionRawMutex, PIPE_HW_TX_SIZE> = Pipe::new();
|
||||||
pub static PIPE_HW_RX: Pipe<CriticalSectionRawMutex, PIPE_HW_RX_SIZE> = Pipe::new();
|
pub static PIPE_HW_RX: Pipe<CriticalSectionRawMutex, PIPE_HW_RX_SIZE> = Pipe::new();
|
||||||
|
|||||||
@@ -4,3 +4,5 @@
|
|||||||
// pub use low_power::*;
|
// pub use low_power::*;
|
||||||
pub mod hw_uart_pc;
|
pub mod hw_uart_pc;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
pub mod sleep;
|
||||||
|
pub mod wakeup;
|
||||||
|
|||||||
4
semestralka_2/src/sleep/mod.rs
Normal file
4
semestralka_2/src/sleep/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// src/sleep/mod.rs
|
||||||
|
|
||||||
|
pub mod standby;
|
||||||
|
pub mod shutdown;
|
||||||
13
semestralka_2/src/sleep/shutdown.rs
Normal file
13
semestralka_2/src/sleep/shutdown.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// src/sleep/standby.rs
|
||||||
|
|
||||||
|
pub fn enter_shutdown() -> ! {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn HAL_PWREx_EnterSHUTDOWNMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
HAL_PWREx_EnterSHUTDOWNMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
cortex_m::asm::udf(); //panic
|
||||||
|
}
|
||||||
58
semestralka_2/src/sleep/standby.rs
Normal file
58
semestralka_2/src/sleep/standby.rs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// src/sleep/standby.rs
|
||||||
|
|
||||||
|
pub fn enter_standby() -> ! {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn HAL_PWR_EnterSTANDBYMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
HAL_PWR_EnterSTANDBYMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
cortex_m::asm::udf(); // never happen marker
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enter_standby_with_sram2_8kb() -> ! {
|
||||||
|
sram2_8kb_retention();
|
||||||
|
enter_standby();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enter_standby_with_sram2_full() -> ! {
|
||||||
|
sram2_full_retention();
|
||||||
|
enter_standby();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sram2_full_retention() {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn HAL_PWREx_EnableSRAM2ContentStandbyRetention(sram2_pages: u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// 0x60 = PWR_SRAM2_FULL_STANDBY = PWR_CR1_RRSB1 | PWR_CR1_RRSB2
|
||||||
|
// See: STM32U5xx HAL: stm32u5xx_hal_pwr_ex.h line 227
|
||||||
|
// PWR_CR1_RRSB1=0x20, PWR_CR1_RRSB2=0x40
|
||||||
|
HAL_PWREx_EnableSRAM2ContentStandbyRetention(0x60);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sram2_8kb_retention() {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn HAL_PWREx_EnableSRAM2ContentStandbyRetention(sram2_pages: u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
// 0x40 = PWR_SRAM2_PAGE1_STANDBY = PWR_CR1_RRSB2
|
||||||
|
// 8KB retention only
|
||||||
|
HAL_PWREx_EnableSRAM2ContentStandbyRetention(0x40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_sram2_full_retention() {
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn HAL_PWREx_DisableSRAM2ContentStandbyRetention(sram2_pages: u32);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
HAL_PWREx_DisableSRAM2ContentStandbyRetention(0x60);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
semestralka_2/src/wakeup/iwdg.rs
Normal file
50
semestralka_2/src/wakeup/iwdg.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
// src/wakeup/iwdg.rs
|
||||||
|
|
||||||
|
use defmt::info;
|
||||||
|
use embassy_stm32::peripherals;
|
||||||
|
use embassy_stm32::wdg::IndependentWatchdog;
|
||||||
|
use embassy_stm32::Peri;
|
||||||
|
use embassy_time::{Duration, Timer};
|
||||||
|
use embassy_stm32::pac;
|
||||||
|
use crate::sleep::standby;
|
||||||
|
|
||||||
|
use crate::config::WATCHDOG_TIMEOUT_US;
|
||||||
|
|
||||||
|
/// Clears system reset and standby flags after wakeup.
|
||||||
|
///
|
||||||
|
/// 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
|
||||||
|
/// - `PWR_SR` — Power Control / Status
|
||||||
|
pub fn clear_wakeup_flags() {
|
||||||
|
info!("Clearing wakeup flags...");
|
||||||
|
standby::disable_sram2_full_retention();
|
||||||
|
|
||||||
|
// Clear reset flags
|
||||||
|
// let rcc = unsafe { &*pac::RCC::ptr() };
|
||||||
|
let rcc = pac::RCC;
|
||||||
|
rcc.csr().write(|w| w.set_rmvf(true));
|
||||||
|
|
||||||
|
// Check and clear Standby wakeup flag
|
||||||
|
// let pwr = unsafe { &*pac::PWR::ptr() };
|
||||||
|
let pwr = pac::PWR;
|
||||||
|
if pwr.sr().read().sbf() {
|
||||||
|
info!("Woke from Standby mode");
|
||||||
|
pwr.sr().write(|w| w.set_sbf(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initializes the Independent Watchdog (IWDG) timer.
|
||||||
|
/// Wakeup source: Can wake the system from Standby mode on timeout
|
||||||
|
///
|
||||||
|
/// # Timing
|
||||||
|
/// - Timeout value is configured in `WATCHDOG_TIMEOUT_US` from config.rs
|
||||||
|
pub async fn init_watchdog(iwdg: Peri<'_, peripherals::IWDG>) {
|
||||||
|
info!("Initializing watchdog after watchdog wake...");
|
||||||
|
let mut watchdog = IndependentWatchdog::new(iwdg, WATCHDOG_TIMEOUT_US);
|
||||||
|
watchdog.unleash();
|
||||||
|
Timer::after(Duration::from_millis(10)).await;
|
||||||
|
}
|
||||||
3
semestralka_2/src/wakeup/mod.rs
Normal file
3
semestralka_2/src/wakeup/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// src/wakeup/mod.rs
|
||||||
|
|
||||||
|
pub mod iwdg;
|
||||||
Reference in New Issue
Block a user