From 1090b496a1f41871ed9fb7950e40982118fed08e 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 fe8d96d55b..12a05558a5 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -30,6 +30,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 @@ -466,6 +471,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) { @@ -860,13 +911,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m #endif #endif // SOC_PM_SUPPORT_DEEPSLEEP_CHECK_STUB_ONLY } 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. @@ -905,13 +950,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 73457a5c52..e15c08276e 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -591,6 +591,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 86ed78d949..30e513c711 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 */