light sleep: add software workaround for esp32c3 gpio reset issue

This commit is contained in:
Li Shuai 2021-03-11 19:25:54 +08:00
parent aff0235e47
commit b3bc27972e
6 changed files with 44 additions and 18 deletions

View File

@ -562,6 +562,9 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
#endif #endif
portENTER_CRITICAL(&gpio_context.gpio_spinlock); portENTER_CRITICAL(&gpio_context.gpio_spinlock);
gpio_hal_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type); 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); portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
} else { } else {
ESP_LOGE(GPIO_TAG, "GPIO wakeup only supports level mode, but edge mode set. gpio_num:%u", gpio_num); ESP_LOGE(GPIO_TAG, "GPIO wakeup only supports level mode, but edge mode set. gpio_num:%u", gpio_num);

View File

@ -201,4 +201,23 @@ menu "ESP32C3-Specific"
If enabled, this disables the linking of binary libraries in the application build. Note If enabled, this disables the linking of binary libraries in the application build. Note
that after enabling this Wi-Fi/Bluetooth will not work. 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 endmenu # ESP32C3-Specific

View File

@ -304,7 +304,7 @@ esp_err_t esp_pm_configure(const void* vconfig)
portEXIT_CRITICAL(&s_switch_lock); portEXIT_CRITICAL(&s_switch_lock);
#if CONFIG_PM_SLP_DISABLE_GPIO && SOC_GPIO_SUPPORT_SLP_SWITCH #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 #endif
#if CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU && SOC_PM_SUPPORT_CPU_PD #if CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU && SOC_PM_SUPPORT_CPU_PD
@ -705,7 +705,7 @@ void esp_pm_impl_init(void)
#endif #endif
#if CONFIG_PM_SLP_DISABLE_GPIO && SOC_GPIO_SUPPORT_SLP_SWITCH #if CONFIG_PM_SLP_DISABLE_GPIO && SOC_GPIO_SUPPORT_SLP_SWITCH
esp_sleep_gpio_status_init(); esp_sleep_config_gpio_isolate();
#endif #endif
ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "rtos0", ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, "rtos0",
&s_rtos_lock_handle[0])); &s_rtos_lock_handle[0]));

View File

@ -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); 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); void esp_deep_sleep_disable_rom_logging(void);
#if SOC_GPIO_SUPPORT_SLP_SWITCH #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. * @brief Enable or disable GPIO pins status switching between slept status and waked status.
* @param enable decide whether to switch status or not * @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 #endif
#if CONFIG_MAC_BB_PD #if CONFIG_MAC_BB_PD

View File

@ -410,9 +410,9 @@ static inline void gpio_sleep_mode_config_unapply(void)
} }
#endif #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++) { for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) { if (GPIO_IS_VALID_GPIO(gpio_num)) {
gpio_sleep_set_direction(gpio_num, GPIO_MODE_DISABLE); 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, "%s automatic switching of GPIO sleep configuration", enable ? "Enable" : "Disable");
ESP_LOGI(TAG, "Light sleep enabled, start GPIO status switching");
} else {
ESP_LOGI(TAG, "Light sleep disabled, stop GPIO status switching");
}
for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) { for (gpio_num_t gpio_num = GPIO_NUM_0; gpio_num < GPIO_NUM_MAX; gpio_num++) {
if (GPIO_IS_VALID_GPIO(gpio_num)) { if (GPIO_IS_VALID_GPIO(gpio_num)) {
if (enable) { if (enable) {

View File

@ -40,6 +40,7 @@
#include "esp_efuse.h" #include "esp_efuse.h"
#include "esp_flash_encrypt.h" #include "esp_flash_encrypt.h"
#include "esp_secure_boot.h" #include "esp_secure_boot.h"
#include "esp_sleep.h"
/***********************************************/ /***********************************************/
// Headers for other components init functions // Headers for other components init functions
@ -413,6 +414,14 @@ IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0))
{ {
esp_timer_init(); 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) #if defined(CONFIG_PM_ENABLE)
esp_pm_impl_init(); esp_pm_impl_init();
#endif #endif