Jelajahi Sumber

Merge branch 'bugfix/esp32c3_light_sleep_gpio_reset_issue_v4.3' into 'release/v4.3'

backport v4.3: add software workaround for esp32c3 gpio reset issue

See merge request espressif/esp-idf!12751
Jiang Jiang Jian 4 tahun lalu
induk
melakukan
1af5bc2f7d

+ 3 - 0
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
 #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);

+ 19 - 0
components/esp32c3/Kconfig

@@ -227,4 +227,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

+ 2 - 2
components/esp_pm/pm_impl.c

@@ -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
@@ -703,7 +703,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]));

+ 7 - 8
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);
 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.
- *  @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
 #endif
 
 
 #if CONFIG_MAC_BB_PD
 #if CONFIG_MAC_BB_PD

+ 4 - 8
components/esp_system/sleep_modes.c

@@ -405,9 +405,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);
@@ -416,13 +416,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++) {
     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) {

+ 10 - 0
components/esp_system/startup.c

@@ -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
@@ -408,6 +409,15 @@ 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