From 6db48cff2574dab3d0e65d6bf76f6d2526c0daaf Mon Sep 17 00:00:00 2001 From: Armando Date: Wed, 9 Oct 2024 11:26:57 +0800 Subject: [PATCH] feat(sleep): support vad wakeup hp core --- .../include/esp_private/esp_pmu.h | 8 +++++++ .../include/esp_private/esp_sleep_internal.h | 1 + components/esp_hw_support/include/esp_sleep.h | 11 ++++++++++ .../esp_hw_support/port/esp32p4/pmu_sleep.c | 5 +++++ components/esp_hw_support/sleep_modes.c | 21 ++++++++++++++++++- .../hal/esp32p4/include/hal/clk_gate_ll.h | 13 ++++++++++++ .../esp32p4/include/soc/Kconfig.soc_caps.in | 8 +++++++ components/soc/esp32p4/include/soc/soc_caps.h | 2 ++ 8 files changed, 68 insertions(+), 1 deletion(-) diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index 5b48194607..6d347788a2 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -50,6 +50,7 @@ typedef enum { #define RTC_SLEEP_USE_ADC_TESEN_MONITOR BIT(17) #define RTC_SLEEP_NO_ULTRA_LOW BIT(18) //!< Avoid using ultra low power in deep sleep, in which RTCIO cannot be used as input, and RTCMEM can't work under high temperature #define RTC_SLEEP_XTAL_AS_RTC_FAST BIT(19) +#define RTC_SLEEP_LP_PERIPH_USE_XTAL BIT(20) #if SOC_PM_SUPPORT_EXT0_WAKEUP #define RTC_EXT0_TRIG_EN PMU_EXT0_WAKEUP_EN //!< EXT0 wakeup @@ -109,6 +110,12 @@ typedef enum { #define RTC_LP_CORE_TRIG_EN 0 #endif //SOC_LP_CORE_SUPPORTED +#if SOC_LP_VAD_SUPPORTED +#define RTC_LP_VAD_TRIG_EN PMU_LP_I2S_WAKEUP_EN //!< LP VAD wakeup +#else +#define RTC_LP_VAD_TRIG_EN 0 +#endif //SOC_LP_VAD_SUPPORTED + #define RTC_XTAL32K_DEAD_TRIG_EN 0 // TODO #define RTC_BROWNOUT_DET_TRIG_EN 0 // TODO @@ -127,6 +134,7 @@ typedef enum { RTC_TOUCH_TRIG_EN | \ RTC_XTAL32K_DEAD_TRIG_EN | \ RTC_USB_TRIG_EN | \ + RTC_LP_VAD_TRIG_EN | \ RTC_BROWNOUT_DET_TRIG_EN) diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index df9c2a79e2..7805b71495 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -38,6 +38,7 @@ typedef enum { ESP_SLEEP_ULTRA_LOW_MODE, //!< In ultra low mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT. ESP_SLEEP_RTC_FAST_USE_XTAL_MODE, //!< The mode in which the crystal is used as the RTC_FAST clock source, need keep XTAL on in HP_SLEEP mode when ULP is working. ESP_SLEEP_DIG_USE_XTAL_MODE, //!< The mode requested by digital peripherals to keep XTAL clock on during sleep (both HP_SLEEP and LP_SLEEP mode). (!!! Only valid for lightsleep, will override the XTAL domain config by esp_sleep_pd_config) + ESP_SLEEP_LP_USE_XTAL_MODE, //!< The mode requested by lp peripherals to keep XTAL clock on during sleep. Only valid for lightsleep. ESP_SLEEP_MODE_MAX, } esp_sleep_sub_mode_t; diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index de25aeb268..76233f1d62 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -118,6 +118,7 @@ typedef enum { ESP_SLEEP_WAKEUP_COCPU, //!< Wakeup caused by COCPU int ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG, //!< Wakeup caused by COCPU crash ESP_SLEEP_WAKEUP_BT, //!< Wakeup caused by BT (light sleep only) + ESP_SLEEP_WAKEUP_VAD, //!< Wakeup caused by VAD } esp_sleep_source_t; /** @@ -179,6 +180,16 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void); */ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us); +#if SOC_LP_VAD_SUPPORTED +/** + * @brief Enable wakeup by VAD + * + * @return + * - ESP_OK on success + */ +esp_err_t esp_sleep_enable_vad_wakeup(void); +#endif + #if SOC_TOUCH_SENSOR_SUPPORTED /** * @brief Enable wakeup by touch sensor diff --git a/components/esp_hw_support/port/esp32p4/pmu_sleep.c b/components/esp_hw_support/port/esp32p4/pmu_sleep.c index 97c112aa6b..b6be295d10 100644 --- a/components/esp_hw_support/port/esp32p4/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32p4/pmu_sleep.c @@ -29,6 +29,7 @@ #include "hal/pmu_hal.h" #include "hal/psram_ctrlr_ll.h" #include "hal/lp_sys_ll.h" +#include "hal/clk_gate_ll.h" #include "esp_private/esp_pmu.h" #include "pmu_param.h" #include "esp_rom_sys.h" @@ -202,6 +203,10 @@ const pmu_sleep_config_t* pmu_sleep_config_default( config->analog.hp_sys.analog.dbias = HP_CALI_ACTIVE_DBIAS_DEFAULT; } + if (sleep_flags & RTC_SLEEP_LP_PERIPH_USE_XTAL) { + _clk_gate_ll_xtal_to_lp_periph_en(true); + } + config->power = power_default; pmu_sleep_param_config_t param_default = PMU_SLEEP_PARAM_CONFIG_DEFAULT(sleep_flags); config->param = *pmu_sleep_param_config_default(¶m_default, &power_default, sleep_flags, adjustment, slowclk_period, fastclk_period); diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index ed81134542..b790ade738 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -222,7 +222,7 @@ typedef struct { } domain[ESP_PD_DOMAIN_MAX]; portMUX_TYPE lock; uint64_t sleep_duration; - uint32_t wakeup_triggers : 15; + uint32_t wakeup_triggers : 20; #if SOC_PM_SUPPORT_EXT1_WAKEUP uint32_t ext1_trigger_mode : 22; // 22 is the maximum RTCIO number in all chips uint32_t ext1_rtc_gpio_mask : 22; @@ -917,6 +917,12 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m sleep_flags |= RTC_SLEEP_XTAL_AS_RTC_FAST; } +#if SOC_LP_VAD_SUPPORTED + if (s_sleep_sub_mode_ref_cnt[ESP_SLEEP_LP_USE_XTAL_MODE] && !deep_sleep) { + sleep_flags |= RTC_SLEEP_LP_PERIPH_USE_XTAL; + } +#endif + #if CONFIG_ESP_SLEEP_DEBUG if (s_sleep_ctx != NULL) { s_sleep_ctx->sleep_flags = sleep_flags; @@ -1645,6 +1651,14 @@ esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us) return ESP_OK; } +#if SOC_LP_VAD_SUPPORTED +esp_err_t esp_sleep_enable_vad_wakeup(void) +{ + s_config.wakeup_triggers |= RTC_LP_VAD_TRIG_EN; + return esp_sleep_sub_mode_config(ESP_SLEEP_LP_USE_XTAL_MODE, true); +} +#endif + static esp_err_t timer_wakeup_prepare(int64_t sleep_duration) { if (sleep_duration < 0) { @@ -2165,6 +2179,10 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) #if SOC_LP_CORE_SUPPORTED } else if (wakeup_cause & RTC_LP_CORE_TRIG_EN) { return ESP_SLEEP_WAKEUP_ULP; +#endif +#if SOC_LP_VAD_SUPPORTED + } else if (wakeup_cause & RTC_LP_VAD_TRIG_EN) { + return ESP_SLEEP_WAKEUP_VAD; #endif } else { return ESP_SLEEP_WAKEUP_UNDEFINED; @@ -2229,6 +2247,7 @@ int32_t* esp_sleep_sub_mode_dump_config(FILE *stream) { [ESP_SLEEP_ULTRA_LOW_MODE] = "ESP_SLEEP_ULTRA_LOW_MODE", [ESP_SLEEP_RTC_FAST_USE_XTAL_MODE] = "ESP_SLEEP_RTC_FAST_USE_XTAL_MODE", [ESP_SLEEP_DIG_USE_XTAL_MODE] = "ESP_SLEEP_DIG_USE_XTAL_MODE", + [ESP_SLEEP_LP_USE_XTAL_MODE] = "ESP_SLEEP_LP_USE_XTAL_MODE", }[mode], s_sleep_sub_mode_ref_cnt[mode] ? "ENABLED" : "DISABLED", s_sleep_sub_mode_ref_cnt[mode]); diff --git a/components/hal/esp32p4/include/hal/clk_gate_ll.h b/components/hal/esp32p4/include/hal/clk_gate_ll.h index 8c5fc05cfb..9a49fd41e0 100644 --- a/components/hal/esp32p4/include/hal/clk_gate_ll.h +++ b/components/hal/esp32p4/include/hal/clk_gate_ll.h @@ -14,6 +14,7 @@ extern "C" { #include #include "esp_attr.h" #include "soc/hp_sys_clkrst_struct.h" +#include "soc/lp_clkrst_struct.h" /** * Enable or disable the clock gate for ref_20m. @@ -75,6 +76,18 @@ FORCE_INLINE_ATTR void _clk_gate_ll_ref_240m_clk_en(bool enable) /// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance #define clk_gate_ll_ref_240m_clk_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_ref_240m_clk_en(__VA_ARGS__) +/** + * Enable or disable the clock gate for xtal to lp periph + * @param enable Enable / disable + */ +FORCE_INLINE_ATTR void _clk_gate_ll_xtal_to_lp_periph_en(bool enable) +{ + LP_AON_CLKRST.lp_clk_en.xtal_clk_force_on = enable; +} +/// use a macro to wrap the function, force the caller to use it in a critical section +/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance +#define clk_gate_ll_xtal_to_lp_periph_en(...) (void)__DECLARE_RCC_ATOMIC_ENV; _clk_gate_ll_xtal_to_lp_periph_en(__VA_ARGS__) + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index eac76a74a3..ed47efb446 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1859,6 +1859,14 @@ config SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE bool default y +config SOC_SLEEP_SYSTIMER_STALL_WORKAROUND + bool + default y + +config SOC_SLEEP_TGWDT_STOP_WORKAROUND + bool + default y + config SOC_PSRAM_VDD_POWER_MPLL bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 16d2aa7643..bf411fb3b7 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -702,6 +702,8 @@ #define SOC_CPU_IN_TOP_DOMAIN (1) #define SOC_PM_PAU_REGDMA_UPDATE_CACHE_BEFORE_WAIT_COMPARE (1) +#define SOC_SLEEP_SYSTIMER_STALL_WORKAROUND 1 //TODO IDF-11381: replace with all xtal field clk gate control +#define SOC_SLEEP_TGWDT_STOP_WORKAROUND 1 //TODO IDF-11381: replace with all xtal field clk gate control /*-------------------------- PSRAM CAPS ----------------------------*/ #define SOC_PSRAM_VDD_POWER_MPLL (1)