enable deepsleep and gpio1 + timer wake

This commit is contained in:
2025-09-26 22:07:48 +02:00
parent 7fc8d0c882
commit 76f59b093d
7 changed files with 79 additions and 82 deletions

View File

@@ -21,14 +21,14 @@ use embassy_executor::Spawner;
use embassy_net::udp::UdpSocket;
use embassy_net::{DhcpConfig, Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::mutex::Mutex;
use embassy_sync::mutex::{Mutex, MutexGuard};
use embassy_time::{Duration, Timer};
use embedded_storage::nor_flash::ReadNorFlash;
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
use esp_bootloader_esp_idf::partitions::FlashRegion;
use esp_hal::gpio::Input;
use esp_hal::gpio::{Input, InputConfig, Pull, RtcPinWithResistors};
use esp_hal::rng::Rng;
use esp_hal::rtc_cntl::sleep::RtcSleepConfig;
use esp_hal::rtc_cntl::{sleep::{TimerWakeupSource, WakeupLevel}, Rtc};
use esp_hal::system::software_reset;
use esp_println::println;
use esp_storage::FlashStorage;
@@ -113,6 +113,9 @@ pub struct Esp<'a> {
pub boot_button: Input<'a>,
// RTC-capable GPIO used as external wake source (store the raw peripheral)
pub wake_gpio1: esp_hal::peripherals::GPIO1<'static>,
pub ota: Ota<'static, FlashStorage>,
pub ota_next: &'static mut FlashRegion<'static, FlashStorage>,
}
@@ -409,14 +412,12 @@ impl Esp<'_> {
spawner.spawn(run_dhcp(stack.clone(), gw_ip_addr_str)).ok();
loop {
println!("waiting for wifi ap link up");
if stack.is_link_up() {
break;
}
Timer::after(Duration::from_millis(500)).await;
}
while !stack.is_config_up() {
println!("waiting for wifi ap config up");
Timer::after(Duration::from_millis(100)).await
}
println!("Connect to the AP `${ssid}` and point your browser to http://{gw_ip_addr_str}/");
@@ -481,92 +482,79 @@ impl Esp<'_> {
spawner.spawn(net_task(runner)).ok();
self.controller.lock().await.start_async().await?;
let timeout = TIME_ACCESS.get().await.current_time_us() + max_wait as u64 * 1000;
let timeout = {
let guard = TIME_ACCESS.get().await.lock().await;
guard.current_time_us()
} + max_wait as u64 * 1000;
loop {
let state = esp_wifi::wifi::sta_state();
println!("waiting wifi sta ready {:?}", state);
match state {
WifiState::StaStarted => {
self.controller.lock().await.connect()?;
break;
}
WifiState::StaConnected => {}
WifiState::StaDisconnected => {}
WifiState::StaStopped => {}
WifiState::ApStarted => {}
WifiState::ApStopped => {}
WifiState::Invalid => {}
_ => {}
}
if TIME_ACCESS.get().await.current_time_us() > timeout {
if { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } > timeout {
bail!("Timeout waiting for wifi sta ready")
}
Timer::after(Duration::from_millis(500)).await;
}
let timeout = TIME_ACCESS.get().await.current_time_us() + max_wait as u64 * 1000;
let timeout = { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } + max_wait as u64 * 1000;
loop {
let state = esp_wifi::wifi::sta_state();
println!("waiting wifi sta connected {:?}", state);
match state {
WifiState::StaStarted => {}
WifiState::StaConnected => {
break;
}
WifiState::StaDisconnected => {}
WifiState::StaStopped => {}
WifiState::ApStarted => {}
WifiState::ApStopped => {}
WifiState::Invalid => {}
_ => {}
}
if TIME_ACCESS.get().await.current_time_us() > timeout {
if { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } > timeout {
bail!("Timeout waiting for wifi sta connected")
}
Timer::after(Duration::from_millis(500)).await;
}
let timeout = TIME_ACCESS.get().await.current_time_us() + max_wait as u64 * 1000;
let timeout = { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } + max_wait as u64 * 1000;
while !stack.is_link_up() {
if TIME_ACCESS.get().await.current_time_us() > timeout {
if { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } > timeout {
bail!("Timeout waiting for wifi link up")
}
println!("waiting for wifi link up");
Timer::after(Duration::from_millis(500)).await;
}
let timeout = TIME_ACCESS.get().await.current_time_us() + max_wait as u64 * 1000;
let timeout = { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } + max_wait as u64 * 1000;
while !stack.is_config_up() {
if TIME_ACCESS.get().await.current_time_us() > timeout {
if { let guard = TIME_ACCESS.get().await.lock().await; guard.current_time_us() } > timeout {
bail!("Timeout waiting for wifi config up")
}
println!("waiting for wifi config up");
Timer::after(Duration::from_millis(100)).await
}
Ok(stack.clone())
}
pub async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
RtcSleepConfig::deep();
pub fn deep_sleep(&mut self, duration_in_ms: u64, mut rtc: MutexGuard<CriticalSectionRawMutex, Rtc>) -> ! {
// Configure and enter deep sleep using esp-hal. Also keep prior behavior where
// duration_in_ms == 0 triggers an immediate reset.
let cur = self.ota.current_ota_state().unwrap();
//we made it till here, so fine
if cur == OtaImageState::PendingVerify {
self.ota
.set_current_ota_state(OtaImageState::Valid)
.expect("Could not set image to valid");
// Mark the current OTA image as valid if we reached here while in pending verify.
if let Ok(cur) = self.ota.current_ota_state() {
if cur == OtaImageState::PendingVerify {
self.ota
.set_current_ota_state(OtaImageState::Valid)
.expect("Could not set image to valid");
}
}
//unsafe {
// //allow early wakeup by pressing the boot button
if duration_in_ms == 0 {
software_reset();
} else {
loop {
info!("todo deepsleep")
}
// //configure gpio 1 to wakeup on low, reused boot button for this
// esp_sleep_enable_ext1_wakeup(
// 0b10u64,
// esp_sleep_ext1_wakeup_mode_t_ESP_EXT1_WAKEUP_ANY_LOW,
// );
// esp_deep_sleep(duration_in_ms);
let timer = TimerWakeupSource::new(core::time::Duration::from_millis(duration_in_ms));
let mut wake_pins: [(&mut dyn RtcPinWithResistors, WakeupLevel); 1] = [(&mut self.wake_gpio1, WakeupLevel::Low)];
let ext1 = esp_hal::rtc_cntl::sleep::Ext1WakeupSource::new(&mut wake_pins);
rtc.sleep_deep(&[&timer, &ext1]);
}
//};
// We should never reach here because sleep_deep never returns, but just in case, reset.
software_reset();
}
pub(crate) async fn load_config(&mut self) -> FatResult<PlantControllerConfig> {