standby from C HAL is working

This commit is contained in:
Priec
2025-12-03 13:05:13 +01:00
parent 60d1ae9a45
commit 9ab8f94f92

View File

@@ -9,8 +9,10 @@ use embassy_executor::Spawner;
use embassy_futures::yield_now; use embassy_futures::yield_now;
use embassy_stm32::bind_interrupts; use embassy_stm32::bind_interrupts;
use embassy_stm32::peripherals; use embassy_stm32::peripherals;
use embassy_stm32::usart::{BufferedUart, Config, BufferedInterruptHandler}; use embassy_stm32::Config;
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;
@@ -25,52 +27,34 @@ bind_interrupts!(struct Irqs {
}); });
unsafe extern "C" { unsafe extern "C" {
fn HAL_Init();
fn HAL_PWR_EnterSTANDBYMode(); fn HAL_PWR_EnterSTANDBYMode();
fn HAL_IWDG_Init(handle: *mut ());
fn HAL_IWDG_Refresh(handle: *mut ());
fn __HAL_PWR_GET_FLAG(flag: u32) -> u32;
fn __HAL_PWR_CLEAR_FLAG(flag: u32);
} }
const PWR_FLAG_SBF: u32 = 1 << 1; const PWR_FLAG_SBF: u32 = 1 << 1;
#[repr(C)]
struct IWDG_InitTypeDef {
prescaler: u32,
reload: u32,
window: u32,
ewi: u32,
}
#[repr(C)]
struct IWDG_HandleTypeDef {
instance: *mut u32,
init: IWDG_InitTypeDef,
}
const IWDG_PRESCALER_256: u32 = 0x06; // prescaler divider
const IWDG_BASE: u32 = 0x4000_3000; // IWDG base address (STM32U5)
static mut IWDG_HANDLE: IWDG_HandleTypeDef = IWDG_HandleTypeDef {
instance: IWDG_BASE as *mut u32,
init: IWDG_InitTypeDef {
prescaler: IWDG_PRESCALER_256,
reload: 125, // ~1s timeout with 32kHz LSI
window: 0xFFF, // disabled window
ewi: 0, // no early wake-up interrupt
},
};
#[embassy_executor::main] #[embassy_executor::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
info!("boot"); info!("boot");
let p = embassy_stm32::init(Default::default()); let mut config = Config::default();
let mut led = Output::new(p.PB0, Level::Low, Speed::Low); config.enable_debug_during_sleep = true;
let p = embassy_stm32::init(config);
let mut led = Output::new(p.PA3, 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
let rcc = pac::RCC;
rcc.csr().write(|w| w.set_rmvf(true));
// 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 = Config::default(); let mut cfg = UsartConfig::default();
cfg.baudrate = BAUD; cfg.baudrate = BAUD;
static TX_BUF: StaticCell<[u8; 256]> = StaticCell::new(); static TX_BUF: StaticCell<[u8; 256]> = StaticCell::new();
static RX_BUF: StaticCell<[u8; 256]> = StaticCell::new(); static RX_BUF: StaticCell<[u8; 256]> = StaticCell::new();
@@ -87,42 +71,32 @@ async fn main(spawner: Spawner) {
spawner.spawn(uart_task(uart, &PIPE_HW_TX, &PIPE_HW_RX).unwrap()); spawner.spawn(uart_task(uart, &PIPE_HW_TX, &PIPE_HW_RX).unwrap());
// END OF HARDWARE UART to the PC // END OF HARDWARE UART to the PC
let pwr = pac::PWR; let dbg = pac::DBGMCU;
let cr = dbg.cr().read();
info!("DBGMCU CR: dbg_stop={}, dbg_standby={}", cr.dbg_stop(), cr.dbg_standby());
let from_standby = pwr.sr().read().sbf(); // MAIN LOOP
if from_standby { info!("tick start");
info!("Wake from Standby"); led.set_high();
pwr.sr().write(|w| w.set_sbf(true)); info!("LED IS HIGH");
} Timer::after(Duration::from_millis(500)).await;
let rcc = pac::RCC; led.set_low();
let csr = rcc.csr().read(); info!("LED IS LOW");
if csr.iwdgrstf() { Timer::after(Duration::from_millis(500)).await;
info!("Reset source: IWDG"); led.set_high();
} info!("LED IS HIGH");
rcc.csr().write(|w| w.set_rmvf(true)); // clear reset flags
info!("Iwdg 1 init"); info!("Iwdg init");
let mut watchdog = IndependentWatchdog::new(p.IWDG, 2_000_000); // 2 seconds
watchdog.unleash();
Timer::after(Duration::from_millis(10)).await;
unsafe { unsafe {
HAL_IWDG_Init(addr_of_mut!(IWDG_HANDLE) as *mut ()); info!("Standby...");
HAL_PWR_EnterSTANDBYMode();
} }
info!("Iwdg 2 init");
loop { loop {
info!("tick start"); cortex_m::asm::wfi();
led.set_high();
info!("LED IS HIGH");
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");
unsafe {
info!("Standby...");
led.set_low();
HAL_IWDG_Refresh(addr_of_mut!(IWDG_HANDLE) as *mut ());
HAL_PWR_EnterSTANDBYMode();
}
yield_now().await;
} }
} }