Просмотр исходного кода

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 лет назад
Родитель
Сommit
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
         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);

+ 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
             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

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

+ 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);
 
 /**
- *  @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

+ 4 - 8
components/esp_system/sleep_modes.c

@@ -405,9 +405,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);
@@ -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++) {
         if (GPIO_IS_VALID_GPIO(gpio_num)) {
             if (enable) {

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