From 0244c6d6fc978b0e8e813df7fabf27b5a8dccbb8 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Fri, 24 Mar 2023 20:37:24 +0100 Subject: [PATCH] Feature/reset functionalities (#452) * add `software_reset`, `software_reset_cpu` and `rtc_get_wakeup_cause` * Add SOC wakeup symbols * Add SleepSource and WakeupReason enums and get_wakeup_cause() function * Add other SOC wakeups * fixups and fmt * address review comments * Update symbols in WakeupReason enum * fmt --------- Co-authored-by: Anthony Grondin <104731965+AnthonyGrondin@users.noreply.github.com> --- esp-hal-common/devices/esp32.toml | 6 +++ esp-hal-common/devices/esp32c2.toml | 6 +++ esp-hal-common/devices/esp32c3.toml | 6 +++ esp-hal-common/devices/esp32c6.toml | 8 +++ esp-hal-common/devices/esp32s2.toml | 9 ++++ esp-hal-common/devices/esp32s3.toml | 10 ++++ esp-hal-common/src/lib.rs | 1 + esp-hal-common/src/reset.rs | 81 ++++++++++++++++++++++++++++ esp-hal-common/src/rtc_cntl/mod.rs | 82 ++++++++++++++++++++++++++++- esp32-hal/ld/rom-functions.x | 3 ++ esp32c2-hal/ld/rom-functions.x | 3 ++ esp32c3-hal/ld/rom-functions.x | 3 ++ esp32c6-hal/ld/rom-functions.x | 3 ++ esp32s2-hal/ld/rom-functions.x | 3 ++ esp32s3-hal/ld/rom-functions.x | 5 +- 15 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 esp-hal-common/src/reset.rs diff --git a/esp-hal-common/devices/esp32.toml b/esp-hal-common/devices/esp32.toml index da1edc789..30c2b20a9 100644 --- a/esp-hal-common/devices/esp32.toml +++ b/esp-hal-common/devices/esp32.toml @@ -53,4 +53,10 @@ peripherals = [ "dac", "pdma", "radio", + + # Wakeup SOC based on ESP-IDF: + "pm_support_ext0_wakeup", + "pm_support_ext1_wakeup", + "pm_support_touch_sensor_wakeup", + "ulp_supported", ] diff --git a/esp-hal-common/devices/esp32c2.toml b/esp-hal-common/devices/esp32c2.toml index 3194eb63d..d5ee29e2a 100644 --- a/esp-hal-common/devices/esp32c2.toml +++ b/esp-hal-common/devices/esp32c2.toml @@ -34,4 +34,10 @@ peripherals = [ "adc", "gdma", "radio", + + # Wakeup SOC based on ESP-IDF: + "pm_support_wifi_wakeup", + "pm_support_bt_wakeup", + "uart_support_wakeup_int", + "gpio_support_deepsleep_wakeup", ] diff --git a/esp-hal-common/devices/esp32c3.toml b/esp-hal-common/devices/esp32c3.toml index 825822bdb..d8113ca0c 100644 --- a/esp-hal-common/devices/esp32c3.toml +++ b/esp-hal-common/devices/esp32c3.toml @@ -45,4 +45,10 @@ peripherals = [ "adc", "gdma", "radio", + + # Wakeup SOC based on ESP-IDF: + "pm_support_wifi_wakeup", + "pm_support_bt_wakeup", + "uart_support_wakeup_int", + "gpio_support_deepsleep_wakeup", ] diff --git a/esp-hal-common/devices/esp32c6.toml b/esp-hal-common/devices/esp32c6.toml index 79de77d57..e358102b7 100644 --- a/esp-hal-common/devices/esp32c6.toml +++ b/esp-hal-common/devices/esp32c6.toml @@ -73,4 +73,12 @@ peripherals = [ "large_intr_status", "plic", "radio", + + # Wakeup SOC based on ESP-IDF: + "pm_support_wifi_wakeup", + "pm_support_beacon_wakeup", + "pm_support_bt_wakeup", + "gpio_support_deepsleep_wakeup", + "uart_support_wakeup_int", + "pm_support_ext1_wakeup", ] diff --git a/esp-hal-common/devices/esp32s2.toml b/esp-hal-common/devices/esp32s2.toml index 75e0ce2e6..383062403 100644 --- a/esp-hal-common/devices/esp32s2.toml +++ b/esp-hal-common/devices/esp32s2.toml @@ -51,4 +51,13 @@ peripherals = [ "dac", "pdma", "radio", + + # Wakeup SOC based on ESP-IDF: + "pm_support_ext0_wakeup", + "pm_support_ext1_wakeup", + "pm_support_touch_sensor_wakeup", + "pm_support_wifi_wakeup", + "uart_support_wakeup_int", + "ulp_supported", + "riscv_coproc_supported", ] diff --git a/esp-hal-common/devices/esp32s3.toml b/esp-hal-common/devices/esp32s3.toml index f48020155..cfe5d9ea9 100644 --- a/esp-hal-common/devices/esp32s3.toml +++ b/esp-hal-common/devices/esp32s3.toml @@ -61,4 +61,14 @@ peripherals = [ "adc", "gdma", "radio", + + # Wakeup SOC based on ESP-IDF: + "pm_support_ext0_wakeup", + "pm_support_ext1_wakeup", + "pm_support_touch_sensor_wakeup", + "pm_support_wifi_wakeup", + "pm_support_bt_wakeup", + "uart_support_wakeup_int", + "ulp_supported", + "riscv_coproc_supported", ] diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index a3382bc07..499e20dc4 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -99,6 +99,7 @@ pub mod prelude; pub mod pulse_control; #[cfg(radio)] pub mod radio; +pub mod reset; #[cfg(rng)] pub mod rng; pub mod rom; diff --git a/esp-hal-common/src/reset.rs b/esp-hal-common/src/reset.rs new file mode 100644 index 000000000..3d81c5321 --- /dev/null +++ b/esp-hal-common/src/reset.rs @@ -0,0 +1,81 @@ +use crate::rtc_cntl::SocResetReason; + +pub enum SleepSource { + /// In case of deep sleep, reset was not caused by exit from deep sleep + Undefined = 0, + /// Not a wakeup cause, used to disable all wakeup sources with + /// esp_sleep_disable_wakeup_source + All, + /// Wakeup caused by external signal using RTC_IO + Ext0, + /// Wakeup caused by external signal using RTC_CNTL + Ext1, + /// Wakeup caused by timer + Timer, + /// Wakeup caused by touchpad + TouchPad, + /// Wakeup caused by ULP program + Ulp, + /// Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3) + Gpio, + /// Wakeup caused by UART (light sleep only) + Uart, + /// Wakeup caused by WIFI (light sleep only) + Wifi, + /// Wakeup caused by COCPU int + Cocpu, + /// Wakeup caused by COCPU crash + CocpuTrapTrig, + /// Wakeup caused by BT (light sleep only) + BT, +} + +#[allow(unused)] +pub(crate) enum WakeupReason { + NoSleep = 0, + #[cfg(pm_support_ext0_wakeup)] + /// EXT0 GPIO wakeup + ExtEvent0Trig = 1 << 0, + #[cfg(pm_support_ext1_wakeup)] + /// EXT1 GPIO wakeup + ExtEvent1Trig = 1 << 1, + /// GPIO wakeup (light sleep only) + GpioTrigEn = 1 << 2, + /// Timer wakeup + TimerTrigEn = 1 << 3, + #[cfg(pm_support_wifi_wakeup)] + /// MAC wakeup (light sleep only) + WifiTrigEn = 1 << 5, + /// UART0 wakeup (light sleep only) + Uart0TrigEn = 1 << 6, + /// UART1 wakeup (light sleep only) + Uart1TrigEn = 1 << 7, + #[cfg(pm_support_touch_sensor_wakeup)] + /// Touch wakeup + TouchTrigEn = 1 << 8, + #[cfg(ulp_supported)] + /// ULP wakeup + UlpTrigEn = 1 << 9, + #[cfg(pm_support_bt_wakeup)] + /// BT wakeup (light sleep only) + BtTrigEn = 1 << 10, + #[cfg(riscv_coproc_supported)] + CocpuTrigEn = 1 << 11, + #[cfg(riscv_coproc_supported)] + CocpuTrapTrigEn = 1 << 13, +} + +pub fn software_reset() { + unsafe { crate::rtc_cntl::software_reset() } +} +pub fn software_reset_cpu() { + unsafe { crate::rtc_cntl::software_reset_cpu() } +} + +pub fn get_reset_reason() -> Option { + crate::rtc_cntl::get_reset_reason(crate::get_core()) +} + +pub fn get_wakeup_cause() -> SleepSource { + crate::rtc_cntl::get_wakeup_cause() +} diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index b71a335f4..89252f50a 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -3,7 +3,7 @@ use embedded_hal::watchdog::{Watchdog, WatchdogDisable, WatchdogEnable}; use fugit::HertzU32; use fugit::MicrosDurationU64; -use self::rtc::SocResetReason; +pub use self::rtc::SocResetReason; #[cfg(not(esp32c6))] use crate::clock::{Clock, XtalClock}; #[cfg(not(esp32))] @@ -14,6 +14,7 @@ use crate::peripherals::LP_WDT; use crate::peripherals::{RTC_CNTL, TIMG0}; use crate::{ peripheral::{Peripheral, PeripheralRef}, + reset::{SleepSource, WakeupReason}, Cpu, }; @@ -37,6 +38,9 @@ extern "C" { #[allow(dead_code)] fn ets_delay_us(us: u32); fn rtc_get_reset_reason(cpu_num: u32) -> u32; + fn rtc_get_wakeup_cause() -> u32; + pub fn software_reset_cpu(); + pub fn software_reset(); } #[cfg(not(esp32c6))] @@ -748,3 +752,79 @@ pub fn get_reset_reason(cpu: Cpu) -> Option { reason } + +pub fn get_wakeup_cause() -> SleepSource { + // FIXME: check s_light_sleep_wakeup + // https://github.com/espressif/esp-idf/blob/afbdb0f3ef195ab51690a64e22bfb8a5cd487914/components/esp_hw_support/sleep_modes.c#L1394 + if get_reset_reason(Cpu::ProCpu).unwrap() != SocResetReason::CoreDeepSleep { + return SleepSource::Undefined; + } + + #[cfg(esp32c6)] + let wakeup_cause = unsafe { + (&*crate::peripherals::PMU::PTR) + .slp_wakeup_status0 + .read() + .wakeup_cause() + .bits() + }; + #[cfg(not(any(esp32, esp32c6)))] + let wakeup_cause = unsafe { + (&*RTC_CNTL::PTR) + .slp_wakeup_cause + .read() + .wakeup_cause() + .bits() + }; + #[cfg(esp32)] + let wakeup_cause = + unsafe { (&*RTC_CNTL::PTR).wakeup_state.read().wakeup_cause().bits() as u32 }; + + if (wakeup_cause & WakeupReason::TimerTrigEn as u32) == 0 { + return SleepSource::Timer; + } + if (wakeup_cause & WakeupReason::GpioTrigEn as u32) == 0 { + return SleepSource::Gpio; + } + if (wakeup_cause & (WakeupReason::Uart0TrigEn as u32 | WakeupReason::Uart1TrigEn as u32)) == 0 { + return SleepSource::Uart; + } + + #[cfg(pm_support_ext0_wakeup)] + if (wakeup_cause & WakeupReason::ExtEvent0Trig as u32) == 0 { + return SleepSource::Ext0; + } + #[cfg(pm_support_ext1_wakeup)] + if (wakeup_cause & WakeupReason::ExtEvent1Trig as u32) == 0 { + return SleepSource::Ext1; + } + + #[cfg(pm_support_touch_sensor_wakeup)] + if (wakeup_cause & WakeupReason::TouchTrigEn as u32) == 0 { + return SleepSource::TouchPad; + } + + #[cfg(ulp_supported)] + if (wakeup_cause & WakeupReason::UlpTrigEn as u32) == 0 { + return SleepSource::Ulp; + } + + #[cfg(pm_support_wifi_wakeup)] + if (wakeup_cause & WakeupReason::WifiTrigEn as u32) == 0 { + return SleepSource::Wifi; + } + + #[cfg(pm_support_bt_wakeup)] + if (wakeup_cause & WakeupReason::BtTrigEn as u32) == 0 { + return SleepSource::BT; + } + + #[cfg(riscv_coproc_supported)] + if (wakeup_cause & WakeupReason::CocpuTrigEn as u32) == 0 { + return SleepSource::Ulp; + } else if (wakeup_cause & WakeupReason::CocpuTrapTrigEn as u32) == 0 { + return SleepSource::CocpuTrapTrig; + } + + return SleepSource::Undefined; +} diff --git a/esp32-hal/ld/rom-functions.x b/esp32-hal/ld/rom-functions.x index 510ea2f24..e0e585cdb 100644 --- a/esp32-hal/ld/rom-functions.x +++ b/esp32-hal/ld/rom-functions.x @@ -3,3 +3,6 @@ PROVIDE(ets_update_cpu_frequency_rom = 0x40008550); PROVIDE(rom_i2c_writeReg = 0x400041a4); PROVIDE(rom_i2c_writeReg_Mask = 0x400041fc); PROVIDE(rtc_get_reset_reason = 0x400081d4); +PROVIDE(rtc_get_wakeup_cause = 0x400081f4); +PROVIDE(software_reset = 0x4000824c); +PROVIDE(software_reset_cpu = 0x40008264); diff --git a/esp32c2-hal/ld/rom-functions.x b/esp32c2-hal/ld/rom-functions.x index e028a6ad3..f349eac39 100644 --- a/esp32c2-hal/ld/rom-functions.x +++ b/esp32c2-hal/ld/rom-functions.x @@ -3,3 +3,6 @@ PROVIDE(ets_update_cpu_frequency_rom = 0x40000774); PROVIDE(rom_i2c_writeReg = 0x400022f4); PROVIDE(rom_i2c_writeReg_Mask = 0x400022fc); PROVIDE(rtc_get_reset_reason = 0x40000018); +PROVIDE(rtc_get_wakeup_cause = 0x40000020); +PROVIDE(software_reset = 0x40000088); +PROVIDE(software_reset_cpu = 0x4000008c); diff --git a/esp32c3-hal/ld/rom-functions.x b/esp32c3-hal/ld/rom-functions.x index 0c4c3555f..56d159e1b 100644 --- a/esp32c3-hal/ld/rom-functions.x +++ b/esp32c3-hal/ld/rom-functions.x @@ -10,3 +10,6 @@ PROVIDE(ets_update_cpu_frequency_rom = 0x40000588); PROVIDE(rom_i2c_writeReg = 0x4000195c); PROVIDE(rom_i2c_writeReg_Mask = 0x40001960); PROVIDE(rtc_get_reset_reason = 0x40000018); +PROVIDE(rtc_get_wakeup_cause = 0x40000024); +PROVIDE(software_reset = 0x40000090); +PROVIDE(software_reset_cpu = 0x40000094); diff --git a/esp32c6-hal/ld/rom-functions.x b/esp32c6-hal/ld/rom-functions.x index 60f3c1183..1fc840147 100644 --- a/esp32c6-hal/ld/rom-functions.x +++ b/esp32c6-hal/ld/rom-functions.x @@ -9,4 +9,7 @@ PROVIDE(cache_resume_icache = 0x4000069c); PROVIDE(ets_delay_us = 0x40000040); PROVIDE(ets_update_cpu_frequency_rom = 0x40000048); PROVIDE(rtc_get_reset_reason = 0x40000018); +PROVIDE(rtc_get_wakeup_cause = 0x40000020); ets_update_cpu_frequency = 0x40000048; +PROVIDE(software_reset = 0x40000090); +PROVIDE(software_reset_cpu = 0x40000094); diff --git a/esp32s2-hal/ld/rom-functions.x b/esp32s2-hal/ld/rom-functions.x index 7c566b6a3..23692826f 100644 --- a/esp32s2-hal/ld/rom-functions.x +++ b/esp32s2-hal/ld/rom-functions.x @@ -3,3 +3,6 @@ PROVIDE(ets_update_cpu_frequency_rom = 0x4000d8a4); PROVIDE(rom_i2c_writeReg = 0x4000a9a8); PROVIDE(rom_i2c_writeReg_Mask = 0x4000aa00); PROVIDE(rtc_get_reset_reason = 0x4000ff58); +PROVIDE(rtc_get_wakeup_cause = 0x4000ff7c); +PROVIDE(software_reset = 0x40010068); +PROVIDE(software_reset_cpu = 0x40010080); diff --git a/esp32s3-hal/ld/rom-functions.x b/esp32s3-hal/ld/rom-functions.x index 89b52e819..a6a15fcb8 100644 --- a/esp32s3-hal/ld/rom-functions.x +++ b/esp32s3-hal/ld/rom-functions.x @@ -3,4 +3,7 @@ PROVIDE(ets_update_cpu_frequency_rom = 0x40043164); PROVIDE(rom_i2c_writeReg = 0x40005d60); PROVIDE(rom_i2c_writeReg_Mask = 0x40005d6c); PROVIDE(rtc_get_reset_reason = 0x4000057c); -PROVIDE( rom_config_instruction_cache_mode = 0x40001a1c ); +PROVIDE(rom_config_instruction_cache_mode = 0x40001a1c); +PROVIDE(rtc_get_wakeup_cause = 0x400005a0); +PROVIDE(software_reset = 0x400006d8); +PROVIDE(software_reset_cpu = 0x400006e4);