diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 913edf8460..8bb5af2592 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -120,6 +120,18 @@ menu "Hardware Settings" console after deep sleep reset, try increasing this value. endmenu + menu "ESP_SLEEP_WORKAROUND" + # No visible menu/configs for workaround + visible if 0 + config ESP_SLEEP_SYSTIMER_STALL_WORKAROUND + bool "ESP32C3 SYSTIMER Stall Issue Workaround" + depends on IDF_TARGET_ESP32C3 + help + Its not able to stall ESP32C3 systimer in sleep. + To fix related RTOS TICK issue, select it to disable related systimer during sleep. + TODO: IDF-7036 + endmenu + menu "RTC Clock Config" orsource "./port/$IDF_TARGET/Kconfig.rtc" diff --git a/components/esp_hw_support/port/esp32c3/rtc_sleep.c b/components/esp_hw_support/port/esp32c3/rtc_sleep.c index 54372ce163..753787b2bf 100644 --- a/components/esp_hw_support/port/esp32c3/rtc_sleep.c +++ b/components/esp_hw_support/port/esp32c3/rtc_sleep.c @@ -23,6 +23,9 @@ #include "soc/regi2c_dig_reg.h" #include "soc/regi2c_lp_bias.h" #include "hal/efuse_hal.h" +#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND +#include "soc/systimer_reg.h" +#endif /** * Configure whether certain peripherals are powered down in deep sleep @@ -199,6 +202,17 @@ void rtc_sleep_set_wakeup_time(uint64_t t) WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32); } +#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND +void rtc_sleep_systimer_enable(bool en) +{ + if (en) { + REG_SET_BIT(SYSTIMER_CONF_REG, SYSTIMER_TIMER_UNIT1_WORK_EN); + } else { + REG_CLR_BIT(SYSTIMER_CONF_REG, SYSTIMER_TIMER_UNIT1_WORK_EN); + } +} +#endif + static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu); uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 811a293f10..0feb403bcd 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -519,6 +519,12 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) timer_wakeup_prepare(); } +#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND + if (!(pd_flags & RTC_SLEEP_PD_XTAL)) { + rtc_sleep_systimer_enable(false); + } +#endif + uint32_t result; if (deep_sleep) { #if !CONFIG_IDF_TARGET_ESP32H2 // IDF does not officially support esp32h2 in v5.0 @@ -552,6 +558,12 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) result = call_rtc_sleep_start(reject_triggers, config.lslp_mem_inf_fpu); } +#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND + if (!(pd_flags & RTC_SLEEP_PD_XTAL)) { + rtc_sleep_systimer_enable(true); + } +#endif + // Restore CPU frequency rtc_clk_cpu_freq_set_config(&cpu_freq_config); diff --git a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld index c97e5a392a..31e24b6314 100644 --- a/components/esp_rom/esp32c2/ld/esp32c2.rom.ld +++ b/components/esp_rom/esp32c2/ld/esp32c2.rom.ld @@ -1575,7 +1575,7 @@ pm_on_tbtt = 0x40001ba8; pm_process_tim = 0x40001bb0; /*pm_rx_beacon_process = 0x40001bb4;*/ pm_rx_data_process = 0x40001bb8; -pm_sleep = 0x40001bbc; +/*pm_sleep = 0x40001bbc;*/ pm_sleep_for = 0x40001bc0; pm_tbtt_process = 0x40001bc4; ppAMPDU2Normal = 0x40001bc8; diff --git a/components/freertos/Kconfig b/components/freertos/Kconfig index a97e5ad06e..f9dab9b4ea 100644 --- a/components/freertos/Kconfig +++ b/components/freertos/Kconfig @@ -400,6 +400,7 @@ menu "FreeRTOS" config FREERTOS_SYSTICK_USES_SYSTIMER bool default y if FREERTOS_CORETIMER_SYSTIMER_LVL1 || FREERTOS_CORETIMER_SYSTIMER_LVL3 + select ESP_SLEEP_SYSTIMER_STALL_WORKAROUND if IDF_TARGET_ESP32C3 config FREERTOS_SYSTICK_USES_CCOUNT bool diff --git a/components/soc/esp32c3/include/soc/rtc.h b/components/soc/esp32c3/include/soc/rtc.h index 0e10a3181e..128395ac32 100644 --- a/components/soc/esp32c3/include/soc/rtc.h +++ b/components/soc/esp32c3/include/soc/rtc.h @@ -650,6 +650,18 @@ void rtc_sleep_low_init(uint32_t slowclk_period); */ void rtc_sleep_set_wakeup_time(uint64_t t); +#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND +/** + * @brief Configure systimer for esp32c3 systimer stall issue workaround + * + * This function configures related systimer for esp32c3 systimer stall issue. + * Only apply workaround when xtal powered up. + * + * @param en enable systimer or not + */ +void rtc_sleep_systimer_enable(bool en); +#endif + #define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup #define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup #define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only)