From 8b369072f953c9fba463dba17791a9085bab4f3d Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Tue, 26 Dec 2023 20:50:52 +0800 Subject: [PATCH] fix(esp_hw_support/sleep): stop TG0/TG1 watchdog if XTAL not power down in lightsleep --- components/esp_hw_support/sleep_modes.c | 67 +++++++++++++++---- .../esp32c3/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32c3/include/soc/soc_caps.h | 2 + 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index e0cf2026a8..4be257586c 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -34,6 +34,11 @@ #include "hal/systimer_ll.h" #endif +#if SOC_SLEEP_TGWDT_STOP_WORKAROUND +#include "hal/mwdt_ll.h" +#include "hal/timer_ll.h" +#endif + #if SOC_PM_SUPPORT_PMU_MODEM_STATE #include "esp_private/pm_impl.h" #endif @@ -493,6 +498,52 @@ static void IRAM_ATTR resume_cache(void) { } } +#if SOC_SLEEP_TGWDT_STOP_WORKAROUND +static uint32_t s_stopped_tgwdt_bmap = 0; +#endif + +// Must be called from critical sections. +static void IRAM_ATTR suspend_timers(uint32_t pd_flags) { + if (!(pd_flags & RTC_SLEEP_PD_XTAL)) { +#if SOC_SLEEP_TGWDT_STOP_WORKAROUND + /* If timegroup implemented task watchdog or interrupt watchdog is running, we have to stop it. */ + for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) { + if (mwdt_ll_check_if_enabled(TIMER_LL_GET_HW(tg_num))) { + mwdt_ll_write_protect_disable(TIMER_LL_GET_HW(tg_num)); + mwdt_ll_disable(TIMER_LL_GET_HW(tg_num)); + mwdt_ll_write_protect_enable(TIMER_LL_GET_HW(tg_num)); + s_stopped_tgwdt_bmap |= BIT(tg_num); + } + } +#endif +#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND + for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) { + systimer_ll_enable_counter(&SYSTIMER, counter_id, false); + } +#endif + } +} + +// Must be called from critical sections. +static void IRAM_ATTR resume_timers(uint32_t pd_flags) { + if (!(pd_flags & RTC_SLEEP_PD_XTAL)) { +#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND + for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) { + systimer_ll_enable_counter(&SYSTIMER, counter_id, true); + } +#endif +#if SOC_SLEEP_TGWDT_STOP_WORKAROUND + for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) { + if (s_stopped_tgwdt_bmap & BIT(tg_num)) { + mwdt_ll_write_protect_disable(TIMER_LL_GET_HW(tg_num)); + mwdt_ll_enable(TIMER_LL_GET_HW(tg_num)); + mwdt_ll_write_protect_enable(TIMER_LL_GET_HW(tg_num)); + } + } +#endif + } +} + // [refactor-todo] provide target logic for body of uart functions below static void IRAM_ATTR flush_uarts(void) { @@ -912,13 +963,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers); #endif } else { -#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND - if (!(pd_flags & RTC_SLEEP_PD_XTAL)) { - for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) { - systimer_ll_enable_counter(&SYSTIMER, counter_id, false); - } - } -#endif + suspend_timers(pd_flags); /* Cache Suspend 1: will wait cache idle in cache suspend */ suspend_cache(); /* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode. @@ -983,13 +1028,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m #endif /* Cache Resume 1: Resume cache for continue running*/ resume_cache(); -#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND - if (!(pd_flags & RTC_SLEEP_PD_XTAL)) { - for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) { - systimer_ll_enable_counter(&SYSTIMER, counter_id, true); - } - } -#endif + resume_timers(pd_flags); } } #if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index 1956fe2a8a..e68c0211eb 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -623,6 +623,10 @@ config SOC_SLEEP_SYSTIMER_STALL_WORKAROUND bool default y +config SOC_SLEEP_TGWDT_STOP_WORKAROUND + bool + default y + config SOC_RTCIO_PIN_COUNT int default 0 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 80ddbcc239..03e25c655c 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -258,6 +258,8 @@ #define SOC_RTC_CNTL_CPU_PD_RETENTION_MEM_SIZE (SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM * (SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH >> 3)) #define SOC_SLEEP_SYSTIMER_STALL_WORKAROUND 1 +#define SOC_SLEEP_TGWDT_STOP_WORKAROUND 1 + /*-------------------------- RTCIO CAPS --------------------------------------*/ /* No dedicated RTCIO subsystem on ESP32-C3. RTC functions are still supported * for hold, wake & 32kHz crystal functions - via rtc_cntl_reg */