diff --git a/components/esp_driver_gpio/include/driver/rtc_io.h b/components/esp_driver_gpio/include/driver/rtc_io.h index b26cf20f14..53e595105b 100644 --- a/components/esp_driver_gpio/include/driver/rtc_io.h +++ b/components/esp_driver_gpio/include/driver/rtc_io.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_hw_support/include/esp_private/sleep_gpio.h b/components/esp_hw_support/include/esp_private/sleep_gpio.h index 0278aba6a0..7f292b5738 100644 --- a/components/esp_hw_support/include/esp_private/sleep_gpio.h +++ b/components/esp_hw_support/include/esp_private/sleep_gpio.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,12 +39,6 @@ void esp_sleep_gpio_pupd_config_workaround_apply(void); void esp_sleep_gpio_pupd_config_workaround_unapply(void); #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 - */ -void esp_deep_sleep_wakeup_io_reset(void); - #ifdef __cplusplus } #endif diff --git a/components/esp_hw_support/include/esp_sleep.h b/components/esp_hw_support/include/esp_sleep.h index cefe69e44e..f82c2d505b 100644 --- a/components/esp_hw_support/include/esp_sleep.h +++ b/components/esp_hw_support/include/esp_sleep.h @@ -594,15 +594,27 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void); #if SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP /** - * @brief Get the bit mask of GPIOs which caused wakeup (gpio) + * @brief Get the bit mask of RTC IO which caused wakeup (GPIO wakeup source). * * If wakeup was caused by another source, this function will return 0. + * Each bit corresponds to an RTC IO. + * Use esp_sleep_wakeup_io_bit2num() to convert a bit index to GPIO number. * - * @return bit mask, if GPIOn caused wakeup, BIT(n) will be set + * @return bit mask of RTC IO that caused wakeup */ uint64_t esp_sleep_get_gpio_wakeup_status(void); #endif //SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP +/** + * @brief Convert RTC IO status bit index to GPIO number. + * + * Used to interpret the bit mask returned by esp_sleep_get_gpio_wakeup_status(). + * + * @param bit RTC IO bit index (0 to SOC_RTCIO_PIN_COUNT-1). + * @return GPIO number, or GPIO_NUM_NC if bit is invalid or has no corresponding GPIO. + */ +gpio_num_t esp_sleep_wakeup_io_bit2num(uint32_t bit); + /** * @brief Configure power domain options for sleep mode * diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 8184fe0374..739449fc14 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -231,7 +231,7 @@ IRAM_ATTR void esp_sleep_isolate_digital_gpio(void) #endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP #if SOC_DEEP_SLEEP_SUPPORTED -void esp_deep_sleep_wakeup_io_reset(void) +static void esp_deep_sleep_wakeup_io_reset(void) { #if SOC_PM_SUPPORT_EXT1_WAKEUP uint32_t rtc_io_mask = rtc_hal_ext1_get_wakeup_pins(); @@ -287,6 +287,29 @@ ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, SECONDARY, BIT(0), 105) return ESP_OK; } +/** + * @brief Convert RTC IO status bit number to GPIO number (for sleep wakeup status translation). + * + * @param bit RTC IO intr status bit index (0 to SOC_RTCIO_PIN_COUNT-1). + * @return GPIO number, or GPIO_NUM_NC if bit is invalid or has no corresponding GPIO. + */ +gpio_num_t esp_sleep_wakeup_io_bit2num(uint32_t bit) +{ +#if SOC_RTCIO_PIN_COUNT > 0 + if (bit >= SOC_RTCIO_PIN_COUNT) { + return GPIO_NUM_NC; + } + for (int gpio = 0; gpio < SOC_GPIO_PIN_COUNT; gpio++) { + if (rtc_io_num_map[gpio] == (int8_t)bit) { + return (gpio_num_t)gpio; + } + } +#elif (SOC_RTCIO_PIN_COUNT == 0) + return (gpio_num_t)bit; +#endif + return GPIO_NUM_NC; +} + void esp_sleep_gpio_include(void) { // Linker hook function, exists to make the linker examine this file diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 8515a1d9a3..a332ae92dc 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -95,11 +95,14 @@ #include "esp_private/esp_task_wdt.h" #include "esp_private/sar_periph_ctrl.h" +#if SOC_PM_SUPPORT_EXT1_WAKEUP && SOC_RTCIO_PIN_COUNT > 0 +#include "esp_private/sleep_gpio.h" +#endif + #ifdef CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/cache.h" #include "esp32/rom/rtc.h" #include "esp_private/gpio.h" -#include "esp_private/sleep_gpio.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/rom/rtc.h" #include "soc/extmem_reg.h" @@ -2225,15 +2228,13 @@ uint64_t esp_sleep_get_ext1_wakeup_status(void) uint32_t status = rtc_hal_ext1_get_wakeup_status(); // Translate bit map of RTC IO numbers into the bit map of GPIO numbers uint64_t gpio_mask = 0; - for (int gpio = 0; gpio < SOC_GPIO_PIN_COUNT; ++gpio) { - if (!esp_sleep_is_valid_wakeup_gpio(gpio)) { - continue; + while (status) { + int rtc_pin = __builtin_ctz(status); + gpio_num_t gpio = esp_sleep_wakeup_io_bit2num(rtc_pin); + if (gpio != GPIO_NUM_NC) { + gpio_mask |= 1ULL << gpio; } - int rtc_pin = rtc_io_number_get(gpio); - if ((status & BIT(rtc_pin)) == 0) { - continue; - } - gpio_mask |= 1ULL << gpio; + status &= ~BIT(rtc_pin); } return gpio_mask; } diff --git a/components/esp_hw_support/test_apps/wakeup_tests/main/src/io_wakeup_cmd.c b/components/esp_hw_support/test_apps/wakeup_tests/main/src/io_wakeup_cmd.c index b8de418da2..e516c4d49b 100644 --- a/components/esp_hw_support/test_apps/wakeup_tests/main/src/io_wakeup_cmd.c +++ b/components/esp_hw_support/test_apps/wakeup_tests/main/src/io_wakeup_cmd.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -8,7 +8,6 @@ #include "unity_test_utils.h" #include "test_utils.h" #include "esp_sleep.h" -#include "driver/rtc_io.h" #include "driver/gpio.h" #include "hal/gpio_ll.h" #include "esp_console.h" @@ -384,9 +383,9 @@ static int process_get_wakeup_cause(int argc, char **argv) if (causes & BIT(ESP_SLEEP_WAKEUP_GPIO)) { if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { #if SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP - uint64_t wakeup_pin_mask = esp_sleep_get_gpio_wakeup_status(); - if (wakeup_pin_mask != 0) { - int pin = __builtin_ffsll(wakeup_pin_mask) - 1; + uint64_t wakeup_channel_mask = esp_sleep_get_gpio_wakeup_status(); + if (wakeup_channel_mask != 0) { + int pin = esp_sleep_wakeup_io_bit2num((uint32_t)__builtin_ctzll(wakeup_channel_mask)); printf("Wake up from GPIO at IO%d\n", pin); } else { printf("Wake up from GPIO triggered, but unknown wake-up IO\n"); diff --git a/examples/system/deep_sleep/main/deep_sleep_example_main.c b/examples/system/deep_sleep/main/deep_sleep_example_main.c index ead52b5b0b..0affbeacf1 100644 --- a/examples/system/deep_sleep/main/deep_sleep_example_main.c +++ b/examples/system/deep_sleep/main/deep_sleep_example_main.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -68,9 +68,9 @@ static void deep_sleep_task(void *args) } #if CONFIG_EXAMPLE_GPIO_WAKEUP if (causes & BIT(ESP_SLEEP_WAKEUP_GPIO)) { - uint64_t wakeup_pin_mask = esp_sleep_get_gpio_wakeup_status(); - if (wakeup_pin_mask != 0) { - int pin = __builtin_ffsll(wakeup_pin_mask) - 1; + uint64_t wakeup_channel_mask = esp_sleep_get_gpio_wakeup_status(); + if (wakeup_channel_mask != 0) { + int pin = esp_sleep_wakeup_io_bit2num((uint32_t)__builtin_ctzll(wakeup_channel_mask)); printf("Wake up from GPIO %d\n", pin); } else { printf("Wake up from GPIO\n"); @@ -86,7 +86,7 @@ static void deep_sleep_task(void *args) if (causes & BIT(ESP_SLEEP_WAKEUP_EXT1)) { uint64_t wakeup_pin_mask = esp_sleep_get_ext1_wakeup_status(); if (wakeup_pin_mask != 0) { - int pin = __builtin_ffsll(wakeup_pin_mask) - 1; + int pin = __builtin_ctzll(wakeup_pin_mask); printf("Wake up from GPIO %d\n", pin); } else { printf("Wake up from GPIO\n");