Merge branch 'bugfix/gpio_esp32_workaround' into 'master'

fix(gpio): fix ESP32 GPIO sleep mode handling

Closes IDF-13626

See merge request espressif/esp-idf!40988
This commit is contained in:
Song Ruo Jing
2025-08-07 17:14:58 +08:00
27 changed files with 87 additions and 243 deletions
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,8 +18,7 @@ extern "C" {
* This file contains declarations of GPIO related functions in sleep modes.
*/
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
#if CONFIG_IDF_TARGET_ESP32
/**
* @brief Save GPIO pull-up and pull-down configuration information in the wake-up state
*
@@ -29,7 +28,7 @@ extern "C" {
* of all GPIO pull-up and pull-down resistors and disable the pull-up and
* pull-down resistors of GPIO before the system enters sleep.
*/
void gpio_sleep_mode_config_apply(void);
void esp_sleep_gpio_pupd_config_workaround_apply(void);
/**
* @brief Restore GPIO pull-up and pull-down configuration information in the wake-up state
@@ -37,9 +36,9 @@ void gpio_sleep_mode_config_apply(void);
* In light sleep mode, after the system wakes up, it needs to restore all GPIO
* pull-up and pull-down configurations before the last sleep.
*/
void gpio_sleep_mode_config_unapply(void);
void esp_sleep_gpio_pupd_config_workaround_unapply(void);
#endif // CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
#endif // CONFIG_IDF_TARGET_ESP32
/**
* @brief Call once in startup to disable the wakeup IO pins and release their holding state after waking up from Deep-sleep
+50 -7
View File
@@ -34,21 +34,64 @@
static const char *TAG = "sleep_gpio";
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
void gpio_sleep_mode_config_apply(void)
#if CONFIG_IDF_TARGET_ESP32
/* On ESP32, for IOs with RTC functionality, setting SLP_PU, SLP_PD couldn't change IO status
* from FUN_PU, FUN_PD to SLP_PU, SLP_PD at sleep.
*/
typedef struct gpio_slp_mode_cfg {
volatile uint32_t fun_pu;
volatile uint32_t fun_pd;
} gpio_slp_mode_cfg_t;
static DRAM_ATTR gpio_slp_mode_cfg_t gpio_cfg = {};
void esp_sleep_gpio_pupd_config_workaround_apply(void)
{
/* Record fun_pu and fun_pd state in bitmap */
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_pupd_config_apply(gpio_num);
int rtcio_num = rtc_io_num_map[gpio_num];
if (rtcio_num >= 0 && gpio_ll_sleep_sel_is_enabled(&GPIO, gpio_num)) {
if (rtcio_ll_is_pullup_enabled(rtcio_num)) {
gpio_cfg.fun_pu |= BIT(rtcio_num);
} else {
gpio_cfg.fun_pu &= ~BIT(rtcio_num);
}
if (rtcio_ll_is_pulldown_enabled(rtcio_num)) {
gpio_cfg.fun_pd |= BIT(rtcio_num);
} else {
gpio_cfg.fun_pd &= ~BIT(rtcio_num);
}
if (gpio_ll_sleep_pullup_is_enabled(&GPIO, gpio_num)) {
rtcio_ll_pullup_enable(rtcio_num);
} else {
rtcio_ll_pullup_disable(rtcio_num);
}
if (gpio_ll_sleep_pulldown_is_enabled(&GPIO, gpio_num)) {
rtcio_ll_pulldown_enable(rtcio_num);
} else {
rtcio_ll_pulldown_disable(rtcio_num);
}
}
}
}
IRAM_ATTR void gpio_sleep_mode_config_unapply(void)
void esp_sleep_gpio_pupd_config_workaround_unapply(void)
{
/* Restore fun_pu and fun_pd state from bitmap */
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_pupd_config_unapply(gpio_num);
int rtcio_num = rtc_io_num_map[gpio_num];
if (rtcio_num >= 0 && gpio_ll_sleep_sel_is_enabled(&GPIO, gpio_num)) {
if (gpio_cfg.fun_pu & BIT(rtcio_num)) {
rtcio_ll_pullup_enable(rtcio_num);
} else {
rtcio_ll_pullup_disable(rtcio_num);
}
if (gpio_cfg.fun_pd & BIT(rtcio_num)) {
rtcio_ll_pulldown_enable(rtcio_num);
} else {
rtcio_ll_pulldown_disable(rtcio_num);
}
}
}
}
+4 -4
View File
@@ -733,8 +733,8 @@ static SLEEP_FN_ATTR void misc_modules_sleep_prepare(uint32_t sleep_flags, bool
# endif
mac_bb_power_down_cb_execute();
#endif
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
gpio_sleep_mode_config_apply();
#if CONFIG_IDF_TARGET_ESP32
esp_sleep_gpio_pupd_config_workaround_apply();
#endif
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL
sleep_enable_cpu_retention();
@@ -801,8 +801,8 @@ static SLEEP_FN_ATTR void misc_modules_wake_prepare(uint32_t sleep_flags)
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_RTCCNTL
sleep_disable_cpu_retention();
#endif
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
gpio_sleep_mode_config_unapply();
#if CONFIG_IDF_TARGET_ESP32
esp_sleep_gpio_pupd_config_workaround_unapply();
#endif
#if CONFIG_MAC_BB_PD
mac_bb_power_up_cb_execute();