From b3bc27972eaaab5dba20f0f53d6e4c6b1c7192dd Mon Sep 17 00:00:00 2001 From: Li Shuai Date: Thu, 11 Mar 2021 19:25:54 +0800 Subject: [PATCH] light sleep: add software workaround for esp32c3 gpio reset issue --- components/driver/gpio.c | 3 +++ components/esp32c3/Kconfig | 19 +++++++++++++++++++ components/esp_pm/pm_impl.c | 4 ++-- components/esp_system/include/esp_sleep.h | 15 +++++++-------- components/esp_system/sleep_modes.c | 12 ++++-------- components/esp_system/startup.c | 9 +++++++++ 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/components/driver/gpio.c b/components/driver/gpio.c index 7d2fabb22b..d29803621f 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -562,6 +562,9 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type) #endif portENTER_CRITICAL(&gpio_context.gpio_spinlock); gpio_hal_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type); +#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND + gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num); +#endif portEXIT_CRITICAL(&gpio_context.gpio_spinlock); } else { ESP_LOGE(GPIO_TAG, "GPIO wakeup only supports level mode, but edge mode set. gpio_num:%u", gpio_num); diff --git a/components/esp32c3/Kconfig b/components/esp32c3/Kconfig index 59454e541a..cc5f3c10d2 100644 --- a/components/esp32c3/Kconfig +++ b/components/esp32c3/Kconfig @@ -201,4 +201,23 @@ menu "ESP32C3-Specific" If enabled, this disables the linking of binary libraries in the application build. Note that after enabling this Wi-Fi/Bluetooth will not work. + config ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND + bool "light sleep GPIO reset workaround" + default y + select PM_SLP_DISABLE_GPIO if FREERTOS_USE_TICKLESS_IDLE + help + ESP32C3 will reset at wake-up if GPIO is received a small electrostatic pulse during + light sleep, with specific condition + + - GPIO needs to be configured as input-mode only + - The pin receives a small electrostatic pulse, and reset occurs when the pulse + voltage is higher than 6 V + + For GPIO set to input mode only, it is not a good practice to leave it open/floating, + The hardware design needs to controlled it with determined supply or ground voltage + is necessary. + + This option provides a software workaround for this issue. Configure to isolate all + GPIO pins in sleep state. + endmenu # ESP32C3-Specific diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index bc2c4f335a..6405823362 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -304,7 +304,7 @@ esp_err_t esp_pm_configure(const void* vconfig) portEXIT_CRITICAL(&s_switch_lock); #if CONFIG_PM_SLP_DISABLE_GPIO && SOC_GPIO_SUPPORT_SLP_SWITCH - esp_sleep_gpio_status_switch_configure(config->light_sleep_enable); + esp_sleep_enable_gpio_switch(config->light_sleep_enable); #endif #if CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU && SOC_PM_SUPPORT_CPU_PD @@ -705,7 +705,7 @@ void esp_pm_impl_init(void) #endif #if CONFIG_PM_SLP_DISABLE_GPIO && SOC_GPIO_SUPPORT_SLP_SWITCH - esp_sleep_gpio_status_init(); + esp_sleep_config_gpio_isolate(); #endif ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "rtos0", &s_rtos_lock_handle[0])); diff --git a/components/esp_system/include/esp_sleep.h b/components/esp_system/include/esp_sleep.h index 68360a76e2..f7f5c2323e 100644 --- a/components/esp_system/include/esp_sleep.h +++ b/components/esp_system/include/esp_sleep.h @@ -434,24 +434,23 @@ esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void); void esp_default_wake_deep_sleep(void); /** - * @brief Disable logging from the ROM code after deep sleep. + * @brief Disable logging from the ROM code after deep sleep. * - * Using LSB of RTC_STORE4. + * Using LSB of RTC_STORE4. */ void esp_deep_sleep_disable_rom_logging(void); #if SOC_GPIO_SUPPORT_SLP_SWITCH /** - * @brief Disable all GPIO pins at slept status. - * + * @brief Configure to isolate all GPIO pins in sleep state */ -void esp_sleep_gpio_status_init(void); +void esp_sleep_config_gpio_isolate(void); /** - * @brief Configure GPIO pins status switching between slept status and waked status. - * @param enable decide whether to switch status or not + * @brief Enable or disable GPIO pins status switching between slept status and waked status. + * @param enable decide whether to switch status or not */ -void esp_sleep_gpio_status_switch_configure(bool enable); +void esp_sleep_enable_gpio_switch(bool enable); #endif #if CONFIG_MAC_BB_PD diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index 4dae2dd1a3..e8f7c0cb3e 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -410,9 +410,9 @@ static inline void gpio_sleep_mode_config_unapply(void) } #endif -void esp_sleep_gpio_status_init(void) +void esp_sleep_config_gpio_isolate(void) { - ESP_LOGI(TAG, "Init to disable all pins at light sleep"); + ESP_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state"); for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { if (GPIO_IS_VALID_GPIO(gpio_num)) { gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE); @@ -421,13 +421,9 @@ void esp_sleep_gpio_status_init(void) } } -void esp_sleep_gpio_status_switch_configure(bool enable) +void esp_sleep_enable_gpio_switch(bool enable) { - if (enable) { - ESP_LOGI(TAG, "Light sleep enabled, start GPIO status switching"); - } else { - ESP_LOGI(TAG, "Light sleep disabled, stop GPIO status switching"); - } + ESP_LOGI(TAG, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable"); for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { if (GPIO_IS_VALID_GPIO(gpio_num)) { if (enable) { diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 4d398733dc..044391351f 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -40,6 +40,7 @@ #include "esp_efuse.h" #include "esp_flash_encrypt.h" #include "esp_secure_boot.h" +#include "esp_sleep.h" /***********************************************/ // Headers for other components init functions @@ -413,6 +414,14 @@ IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0)) { esp_timer_init(); +#if CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND && !CONFIG_PM_SLP_DISABLE_GPIO + // Configure to isolate (disable the Input/Output/Pullup/Pulldown + // function of the pin) all GPIO pins in sleep state + esp_sleep_config_gpio_isolate(); + // Enable automatic switching of GPIO configuration + esp_sleep_enable_gpio_switch(true); +#endif + #if defined(CONFIG_PM_ENABLE) esp_pm_impl_init(); #endif