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_driver_gpio/src/gpio.c b/components/esp_driver_gpio/src/gpio.c index 11eca7aee0..51db4a0079 100644 --- a/components/esp_driver_gpio/src/gpio.c +++ b/components/esp_driver_gpio/src/gpio.c @@ -777,7 +777,6 @@ esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *stren esp_err_t gpio_hold_en(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Only output-capable GPIO support this function", ESP_ERR_NOT_SUPPORTED); int ret = ESP_OK; if (rtc_gpio_is_valid_gpio(gpio_num)) { @@ -785,6 +784,7 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num) ret = rtc_gpio_hold_en(gpio_num); #endif } else if (GPIO_HOLD_MASK[gpio_num]) { + GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Only output-capable GPIO support this function", ESP_ERR_NOT_SUPPORTED); portENTER_CRITICAL(&gpio_context.gpio_spinlock); gpio_hal_hold_en(gpio_context.gpio_hal, gpio_num); portEXIT_CRITICAL(&gpio_context.gpio_spinlock); @@ -797,7 +797,6 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num) esp_err_t gpio_hold_dis(gpio_num_t gpio_num) { - GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Only output-capable GPIO support this function", ESP_ERR_NOT_SUPPORTED); int ret = ESP_OK; if (rtc_gpio_is_valid_gpio(gpio_num)) { @@ -805,6 +804,7 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num) ret = rtc_gpio_hold_dis(gpio_num); #endif } else if (GPIO_HOLD_MASK[gpio_num]) { + GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Only output-capable GPIO support this function", ESP_ERR_NOT_SUPPORTED); portENTER_CRITICAL(&gpio_context.gpio_spinlock); gpio_hal_hold_dis(gpio_context.gpio_hal, gpio_num); portEXIT_CRITICAL(&gpio_context.gpio_spinlock); diff --git a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c index 4abca5361d..3d39f2dfbe 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c +++ b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -247,7 +247,7 @@ TEST_CASE("RTCIO_interrupt_test", "[rtcio]") TEST_ESP_OK(rtc_gpio_init(test_io)); TEST_ESP_OK(rtc_gpio_set_direction(test_io, RTC_GPIO_MODE_INPUT_OUTPUT)); TEST_ESP_OK(rtc_gpio_set_level(test_io, 0)); - rtcio_ll_intr_enable(test_io, GPIO_INTR_HIGH_LEVEL); + rtcio_ll_intr_enable(rtc_io_idx, GPIO_INTR_HIGH_LEVEL); int cnt = 0; while (cnt < TEST_COUNT) { @@ -260,7 +260,7 @@ TEST_CASE("RTCIO_interrupt_test", "[rtcio]") } TEST_ESP_OK(rtc_gpio_set_level(test_io, 0)); - rtcio_ll_intr_enable(test_io, GPIO_INTR_POSEDGE); + rtcio_ll_intr_enable(rtc_io_idx, GPIO_INTR_POSEDGE); cnt = 0; while (cnt < TEST_COUNT) { TEST_ESP_OK(rtc_gpio_set_level(test_io, 1)); @@ -272,7 +272,7 @@ TEST_CASE("RTCIO_interrupt_test", "[rtcio]") vTaskDelay(100 / portTICK_PERIOD_MS); } - rtcio_ll_intr_enable(test_io, GPIO_INTR_DISABLE); + rtcio_ll_intr_enable(rtc_io_idx, GPIO_INTR_DISABLE); TEST_ESP_OK(rtc_gpio_deinit(test_io)); } #endif //SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT > 0) diff --git a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h index 5b07231356..90bdc06b8e 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h +++ b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h @@ -37,6 +37,7 @@ const int s_test_map[TEST_GPIO_PIN_COUNT] = { GPIO_NUM_38, //GPIO38 GPIO_NUM_39, //GPIO39 }; +#define TEST_RTCIO_INTR_PIN_INDEX 5 // IO25 #define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5 // IO25 #elif defined CONFIG_IDF_TARGET_ESP32S2 // Has no input-only rtcio pins, all pins support pull-up/down @@ -66,6 +67,7 @@ const int s_test_map[TEST_GPIO_PIN_COUNT] = { GPIO_NUM_20, //GPIO20 GPIO_NUM_21, //GPIO21 }; +#define TEST_RTCIO_INTR_PIN_INDEX 5 // IO6 #define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5 // IO6 #elif defined CONFIG_IDF_TARGET_ESP32S3 // Has no input-only rtcio pins, all pins support pull-up/down @@ -95,6 +97,7 @@ const int s_test_map[TEST_GPIO_PIN_COUNT] = { GPIO_NUM_20, //GPIO20 GPIO_NUM_21, //GPIO21 }; +#define TEST_RTCIO_INTR_PIN_INDEX 5 // IO6 #define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5 // IO6 #elif CONFIG_IDF_TARGET_ESP32C6 // Has no input-only rtcio pins, all pins support pull-up/down diff --git a/components/esp_hal_gpio/esp32/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32/include/hal/rtc_io_ll.h index 6c4863ea3a..463e2d8a0b 100644 --- a/components/esp_hal_gpio/esp32/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32/include/hal/rtc_io_ll.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 */ @@ -330,6 +330,17 @@ static inline void rtcio_ll_wakeup_disable(int rtcio_num) RTCIO.pin[rtcio_num].int_type = 0; } +/** + * Enable interrupt function and set interrupt type for RTC IO. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param type Interrupt type (disable, edge, or level). Matches gpio_int_type_t encoding. + */ +static inline void rtcio_ll_intr_enable(int rtcio_num, gpio_int_type_t type) +{ + RTCIO.pin[rtcio_num].int_type = type; +} + /** * Enable rtc io output in deep sleep. * @@ -407,6 +418,36 @@ static inline void rtcio_ll_ext0_set_wakeup_pin(int rtcio_num, int level) SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, level, RTC_CNTL_EXT_WAKEUP0_LV_S); } +/** + * @brief Get the status of whether an IO is used for sleep wake-up. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @return True if the pin is enabled to wake up from deep-sleep + */ +static inline bool rtcio_ll_wakeup_is_enabled(int rtcio_num) +{ + HAL_ASSERT(rtcio_num >= 0 && rtcio_num < SOC_RTCIO_PIN_COUNT && "io does not support deep sleep wake-up function"); + return RTCIO.pin[rtcio_num].wakeup_enable; +} + +/** + * @brief Get the rtc io interrupt status + * + * @return bit 0~17 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT. + */ +static inline uint32_t rtcio_ll_get_interrupt_status(void) +{ + return RTCIO.status.status; +} + +/** + * @brief Clear all LP IO pads status + */ +static inline void rtcio_ll_clear_interrupt_status(void) +{ + RTCIO.status_w1tc.w1tc = 0x3FFFF; // Clear all 18 RTCIO pins +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_gpio/esp32s2/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32s2/include/hal/rtc_io_ll.h index 8ee834fa5b..17ff0a31eb 100644 --- a/components/esp_hal_gpio/esp32s2/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32s2/include/hal/rtc_io_ll.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 */ @@ -335,6 +335,17 @@ static inline void rtcio_ll_wakeup_disable(int rtcio_num) RTCIO.pin[rtcio_num].int_type = 0; } +/** + * Enable interrupt function and set interrupt type for RTC IO. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param type Interrupt type (disable, edge, or level). Matches gpio_int_type_t encoding. + */ +static inline void rtcio_ll_intr_enable(int rtcio_num, gpio_int_type_t type) +{ + RTCIO.pin[rtcio_num].int_type = type; +} + /** * Enable rtc io output in deep sleep. * @@ -412,6 +423,36 @@ static inline void rtcio_ll_ext0_set_wakeup_pin(int rtcio_num, int level) SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, level, RTC_CNTL_EXT_WAKEUP0_LV_S); } +/** + * @brief Get the status of whether an IO is used for sleep wake-up. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @return True if the pin is enabled to wake up from deep-sleep + */ +static inline bool rtcio_ll_wakeup_is_enabled(int rtcio_num) +{ + HAL_ASSERT(rtcio_num >= 0 && rtcio_num < SOC_RTCIO_PIN_COUNT && "io does not support deep sleep wake-up function"); + return RTCIO.pin[rtcio_num].wakeup_enable; +} + +/** + * @brief Get the rtc io interrupt status + * + * @return bit 0~21 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT. + */ +static inline uint32_t rtcio_ll_get_interrupt_status(void) +{ + return RTCIO.status.status; +} + +/** + * @brief Clear all LP IO pads status + */ +static inline void rtcio_ll_clear_interrupt_status(void) +{ + RTCIO.status_w1tc.w1tc = 0x3FFFFF; // Clear all 22 RTCIO pins +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_gpio/esp32s3/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32s3/include/hal/rtc_io_ll.h index 65ea59a43a..c6d6dc0212 100644 --- a/components/esp_hal_gpio/esp32s3/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32s3/include/hal/rtc_io_ll.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 */ @@ -363,6 +363,17 @@ static inline void rtcio_ll_wakeup_disable(int rtcio_num) RTCIO.pin[rtcio_num].int_type = 0; } +/** + * Enable interrupt function and set interrupt type for RTC IO. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param type Interrupt type (disable, edge, or level). Matches gpio_int_type_t encoding. + */ +static inline void rtcio_ll_intr_enable(int rtcio_num, gpio_int_type_t type) +{ + RTCIO.pin[rtcio_num].int_type = type; +} + /** * Enable rtc io output in deep sleep. * @@ -440,6 +451,36 @@ static inline void rtcio_ll_ext0_set_wakeup_pin(int rtcio_num, int level) SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1, level, RTC_CNTL_EXT_WAKEUP0_LV_S); } +/** + * @brief Get the status of whether an IO is used for sleep wake-up. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @return True if the pin is enabled to wake up from deep-sleep + */ +static inline bool rtcio_ll_wakeup_is_enabled(int rtcio_num) +{ + HAL_ASSERT(rtcio_num >= 0 && rtcio_num < SOC_RTCIO_PIN_COUNT && "io does not support deep sleep wake-up function"); + return RTCIO.pin[rtcio_num].wakeup_enable; +} + +/** + * @brief Get the rtc io interrupt status + * + * @return bit 0~21 corresponding to 0 ~ SOC_RTCIO_PIN_COUNT. + */ +static inline uint32_t rtcio_ll_get_interrupt_status(void) +{ + return RTCIO.status.status; +} + +/** + * @brief Clear all LP IO pads status + */ +static inline void rtcio_ll_clear_interrupt_status(void) +{ + RTCIO.status_w1tc.w1tc = 0x3FFFFF; // Clear all 22 RTCIO pins +} + #ifdef __cplusplus } #endif 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 4d01436d8d..b609eae148 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -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 */ @@ -10,6 +10,7 @@ #include #include "esp_attr.h" +#include "esp_system.h" #include "esp_sleep.h" #include "esp_log.h" #include "esp_memory_utils.h" @@ -97,6 +98,7 @@ void esp_sleep_gpio_pupd_config_workaround_unapply(void) } #endif +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO void esp_sleep_config_gpio_isolate(void) { ESP_EARLY_LOGI(TAG, "Configure to isolate all GPIO pins in sleep state"); @@ -169,6 +171,7 @@ void esp_sleep_enable_gpio_switch(bool enable) } } } +#endif #if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP IRAM_ATTR void esp_sleep_isolate_digital_gpio(void) @@ -228,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(); @@ -247,37 +250,67 @@ void esp_deep_sleep_wakeup_io_reset(void) #endif #if SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP - uint32_t dl_io_mask = SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK; + uint64_t dslp_io_mask = SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK; gpio_hal_context_t gpio_hal = { .dev = GPIO_HAL_GET_HW(GPIO_PORT_0) }; - while (dl_io_mask) { - int gpio_num = __builtin_ffs(dl_io_mask) - 1; + while (dslp_io_mask) { + int gpio_num = __builtin_ctzll(dslp_io_mask); bool wakeup_io_enabled = gpio_hal_wakeup_is_enabled_on_hp_periph_powerdown_sleep(&gpio_hal, gpio_num); if (wakeup_io_enabled) { // Disable the wakeup before releasing hold, such that wakeup status can reflect the correct wakeup pin gpio_hal_wakeup_disable_on_hp_periph_powerdown_sleep(&gpio_hal, gpio_num); gpio_hal_hold_dis(&gpio_hal, gpio_num); } - dl_io_mask &= ~BIT(gpio_num); + dslp_io_mask &= dslp_io_mask - 1; } #endif } #endif -#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, SECONDARY, BIT(0), 105) { +#if SOC_DEEP_SLEEP_SUPPORTED + // Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins + if (esp_reset_reason() == ESP_RST_DEEPSLEEP) { + esp_deep_sleep_wakeup_io_reset(); + } +#endif //#if SOC_DEEP_SLEEP_SUPPORTED + +#if CONFIG_ESP_SLEEP_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 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 } -#endif diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 2223ba6775..e1599cf94b 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -97,11 +97,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" @@ -292,8 +295,8 @@ typedef struct { uint32_t ext0_rtc_gpio_num : 5; #endif #if SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP - uint32_t gpio_wakeup_mask : SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT; - uint32_t gpio_trigger_mode : SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT; + uint64_t gpio_wakeup_mask; + uint64_t gpio_trigger_mode; #endif uint32_t sleep_time_adjustment; uint32_t ccount_ticks_record; @@ -1029,9 +1032,6 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment; - // Sleep UART prepare - sleep_uart_prepare(sleep_flags, deep_sleep); - #if CONFIG_ESP_PHY_ENABLED && SOC_DEEP_SLEEP_SUPPORTED // Do deep-sleep PHY related callback, which need to be executed when the PLL clock is exists. // For light-sleep, PHY state is managed by the upper layer of the wifi/bt protocol stack. @@ -1040,22 +1040,12 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl } #endif -#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP - uint32_t xtal_freq = rtc_clk_xtal_freq_get(); - esp_clk_utils_mspi_speed_mode_sync_before_cpu_freq_switching(xtal_freq, xtal_freq); -#endif - #if SOC_PM_RETENTION_SW_TRIGGER_REGDMA if (!deep_sleep && (sleep_flags & PMU_SLEEP_PD_TOP)) { sleep_retention_do_system_retention(true); } #endif - // Save current frequency and switch to XTAL - rtc_cpu_freq_config_t cpu_freq_config; - rtc_clk_cpu_freq_get_config(&cpu_freq_config); - rtc_clk_cpu_freq_set_xtal_for_sleep(); - #if SOC_PM_SUPPORT_EXT0_WAKEUP // Configure pins for external wakeup if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) { @@ -1076,6 +1066,19 @@ static esp_err_t SLEEP_FN_ATTR esp_sleep_start(uint32_t sleep_flags, uint32_t cl } #endif + // Sleep UART prepare + sleep_uart_prepare(sleep_flags, deep_sleep); + +#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP + uint32_t xtal_freq = rtc_clk_xtal_freq_get(); + esp_clk_utils_mspi_speed_mode_sync_before_cpu_freq_switching(xtal_freq, xtal_freq); +#endif + + // Save current frequency and switch to XTAL + rtc_cpu_freq_config_t cpu_freq_config; + rtc_clk_cpu_freq_get_config(&cpu_freq_config); + rtc_clk_cpu_freq_set_xtal_for_sleep(); + #if CONFIG_ULP_COPROC_ENABLED // Enable ULP wakeup #if CONFIG_ULP_COPROC_TYPE_FSM @@ -2239,15 +2242,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; } @@ -2265,26 +2266,29 @@ uint64_t esp_sleep_get_gpio_wakeup_status(void) static void esp_sleep_gpio_wakeup_prepare_on_hp_periph_powerdown(void) { - uint32_t valid_wake_io_mask = SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK; - for (gpio_num_t gpio_idx = __builtin_ctz(valid_wake_io_mask); valid_wake_io_mask >> gpio_idx; gpio_idx++) { - if ((s_config.gpio_wakeup_mask & BIT64(gpio_idx)) == 0) { - continue; - } + uint64_t valid_wake_io_mask = s_config.gpio_wakeup_mask & SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK; + while (valid_wake_io_mask) { + int gpio_idx = __builtin_ctzll(valid_wake_io_mask); #if SOC_LP_IO_CLOCK_IS_INDEPENDENT // To suppress build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused)); rtcio_ll_enable_io_clock(true); #endif #if CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS - if (s_config.gpio_trigger_mode & BIT(gpio_idx)) { - ESP_ERROR_CHECK(gpio_pullup_dis(gpio_idx)); - ESP_ERROR_CHECK(gpio_pulldown_en(gpio_idx)); + if (GPIO_IS_VALID_OUTPUT_GPIO(gpio_idx)) { + if (s_config.gpio_trigger_mode & BIT(gpio_idx)) { + gpio_pullup_dis(gpio_idx); + gpio_pulldown_en(gpio_idx); + } else { + gpio_pullup_en(gpio_idx); + gpio_pulldown_dis(gpio_idx); + } } else { - ESP_ERROR_CHECK(gpio_pullup_en(gpio_idx)); - ESP_ERROR_CHECK(gpio_pulldown_dis(gpio_idx)); + ESP_EARLY_LOGE(TAG, "GPIO%d not support internal PU/PD", gpio_idx); } #endif ESP_ERROR_CHECK(gpio_hold_en(gpio_idx)); + valid_wake_io_mask &= valid_wake_io_mask - 1; } // Clear state from previous wakeup rtc_hal_gpio_clear_wakeup_status(); @@ -2311,19 +2315,17 @@ esp_err_t esp_sleep_enable_gpio_wakeup_on_hp_periph_powerdown(uint64_t gpio_pin_ } } } - - for (gpio_num_t gpio_idx = __builtin_ctzll(gpio_pin_mask); gpio_pin_mask >> gpio_idx; gpio_idx++) { - if ((gpio_pin_mask & BIT64(gpio_idx)) == 0) { - continue; - } + while (gpio_pin_mask) { + int gpio_idx = __builtin_ctzll(gpio_pin_mask); err = gpio_wakeup_enable_on_hp_periph_powerdown_sleep(gpio_idx, intr_type); if (err != ESP_OK) return err; - s_config.gpio_wakeup_mask |= BIT(gpio_idx); + s_config.gpio_wakeup_mask |= BIT64(gpio_idx); if (mode == ESP_GPIO_WAKEUP_GPIO_HIGH) { - s_config.gpio_trigger_mode |= BIT(gpio_idx); + s_config.gpio_trigger_mode |= BIT64(gpio_idx); } else { - s_config.gpio_trigger_mode &= ~BIT(gpio_idx); + s_config.gpio_trigger_mode &= ~BIT64(gpio_idx); } + gpio_pin_mask &= gpio_pin_mask - 1; } s_config.wakeup_triggers |= RTC_GPIO_TRIG_EN; return err; diff --git a/components/esp_hw_support/test_apps/.build-test-rules.yml b/components/esp_hw_support/test_apps/.build-test-rules.yml index eacac23ec6..07c2caf2a3 100644 --- a/components/esp_hw_support/test_apps/.build-test-rules.yml +++ b/components/esp_hw_support/test_apps/.build-test-rules.yml @@ -55,6 +55,6 @@ components/esp_hw_support/test_apps/wakeup_tests: enable: - if: SOC_DEEP_SLEEP_SUPPORTED == 1 and SOC_LIGHT_SLEEP_SUPPORTED == 1 disable_test: - - if: IDF_TARGET in ["esp32c61", "esp32h21", "esp32h4"] + - if: IDF_TARGET in ["esp32h21", "esp32h4"] temporary: true reason: lack of runners 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/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py b/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py index c7469393f1..c0898b3e61 100644 --- a/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py +++ b/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py @@ -1,10 +1,11 @@ -# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: CC0-1.0 from time import sleep import pytest from pytest_embedded_idf.dut import IdfDut from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets TEST_CONFIGS = [ pytest.param('default'), @@ -26,7 +27,7 @@ available_gpio_nums = { } available_rtcio_nums = { - 'esp32': [36, 37, 38, 39, 34, 35, 4, 0, 2, 15, 13, 12, 14, 27], + 'esp32': [36, 37, 38, 39, 34, 35, 25, 26, 33, 32, 4, 0, 2, 15, 13, 12, 14, 27], 'esp32s2': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 'esp32s3': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], 'esp32c2': [0, 1, 2, 3, 4, 5], @@ -42,11 +43,7 @@ available_rtcio_nums = { @pytest.mark.generic_multi_device @pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) -@idf_parametrize( - 'target', - ['esp32', 'esp32s2', 'esp32s3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32c5'], - indirect=['target'], -) +@idf_parametrize('target', soc_filtered_targets('SOC_PM_SUPPORT_EXT1_WAKEUP == 1'), indirect=['target']) def test_ext1_deepsleep(dut: tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] @@ -97,7 +94,7 @@ def test_ext1_deepsleep(dut: tuple[IdfDut, IdfDut]) -> None: @pytest.mark.generic_multi_device @pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) -@idf_parametrize('target', ['esp32c2', 'esp32c3', 'esp32c6', 'esp32p4', 'esp32c5'], indirect=['target']) +@idf_parametrize('target', soc_filtered_targets('SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP == 1'), indirect=['target']) def test_rtcio_deepsleep(dut: tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] @@ -143,7 +140,6 @@ def test_rtcio_deepsleep(dut: tuple[IdfDut, IdfDut]) -> None: @pytest.mark.parametrize('count', [2], indirect=True) @pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) @idf_parametrize('target', ['supported_targets'], indirect=['target']) -@pytest.mark.temp_skip_ci(targets=['esp32c61'], reason='p4 rev3 migration') def test_gpio_wakeup_enable_lightsleep(dut: tuple[IdfDut, IdfDut]) -> None: wakee = dut[0] waker = dut[1] diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 48baeacc20..edc11e48f9 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -848,13 +848,6 @@ NOINLINE_ATTR static void system_early_init(const soc_reset_reason_t *rst_reas) #endif // CONFIG_ESP_CONSOLE_UART #endif // !CONFIG_IDF_ENV_FPGA -#if SOC_DEEP_SLEEP_SUPPORTED - // Need to unhold the IOs that were hold right before entering deep sleep, which are used as wakeup pins - if (rst_reas[0] == RESET_REASON_CORE_DEEP_SLEEP) { - esp_deep_sleep_wakeup_io_reset(); - } -#endif //#if SOC_DEEP_SLEEP_SUPPORTED - #if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP esp_cache_err_int_init(); #endif diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 99d7c4a8fe..72ddd5ad3d 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -343,6 +343,14 @@ config SOC_GPIO_PIN_COUNT int default 40 +config SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP + bool + default y + +config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK + int + default 0 + config SOC_GPIO_VALID_GPIO_MASK hex default 0xFFFFFFFFFF diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 2c1fe8d1f0..d2186f9b3b 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -183,6 +183,10 @@ #define SOC_GPIO_PORT (1U) #define SOC_GPIO_PIN_COUNT 40 +#define SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP (1) +#define SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP +#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT2 | BIT4 | BIT12 | BIT13 | BIT14 | BIT15 | BIT25 | BIT26 | BIT27 | BIT32 | BIT33 | BIT34 | BIT35 | BIT36 | BIT37 | BIT38 | BIT39) + // 0~39 valid except 24, 28~31 #define SOC_GPIO_VALID_GPIO_MASK (0xFFFFFFFFFFULL & ~(0ULL | BIT24 | BIT28 | BIT29 | BIT30 | BIT31)) // GPIO >= 34 are input only diff --git a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in index f2f7ac12c1..08ebfaad78 100644 --- a/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c2/include/soc/Kconfig.soc_caps.in @@ -315,10 +315,6 @@ config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK int default 0 -config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT - int - default 6 - config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x00000000001FFFC0 diff --git a/components/soc/esp32c2/include/soc/soc_caps.h b/components/soc/esp32c2/include/soc/soc_caps.h index bbba57d35f..ce98f980e4 100644 --- a/components/soc/esp32c2/include/soc/soc_caps.h +++ b/components/soc/esp32c2/include/soc/soc_caps.h @@ -142,7 +142,6 @@ #define SOC_GPIO_OUT_RANGE_MAX 20 #define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5) -#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT (6) // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_6~GPIO_NUM_20) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x00000000001FFFC0ULL diff --git a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in index a4a1bb88b7..cb49e3e24f 100644 --- a/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c3/include/soc/Kconfig.soc_caps.in @@ -411,10 +411,6 @@ config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK int default 0 -config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT - int - default 6 - config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x00000000003FFFC0 diff --git a/components/soc/esp32c3/include/soc/soc_caps.h b/components/soc/esp32c3/include/soc/soc_caps.h index 5c5a85e206..a38b5e325e 100644 --- a/components/soc/esp32c3/include/soc/soc_caps.h +++ b/components/soc/esp32c3/include/soc/soc_caps.h @@ -181,7 +181,6 @@ #define SOC_GPIO_OUT_RANGE_MAX 21 #define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5) -#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT (6) // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_6~GPIO_NUM_21) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x00000000003FFFC0ULL diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index fdc61100b5..22682bd8ac 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -591,10 +591,6 @@ config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK int default 0 -config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT - int - default 7 - config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x0000000001FFFF80 diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index b24184a6b0..7d7bb81c30 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -236,7 +236,6 @@ #define SOC_GPIO_OUT_RANGE_MAX 28 #define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6) -#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT (7) // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_7~GPIO_NUM_28) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x0000000001FFFF80ULL diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 43bd99bfdb..070e40dbbc 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -507,10 +507,6 @@ config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK int default 0 -config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT - int - default 8 - config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x000000007FFFFF00 diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 989fe492d4..f74db01843 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -209,7 +209,6 @@ #define SOC_GPIO_OUT_RANGE_MAX 30 #define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7) -#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT (8) // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_8~GPIO_NUM_30) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x000000007FFFFF00ULL diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 3f3598fc79..e1f7086f4f 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -463,10 +463,6 @@ config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK int default 0 -config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT - int - default 7 - config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x3FFFFF80 diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index 9e0361519e..58811805e5 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -192,7 +192,6 @@ #define SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP (1) #define SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP #define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6) -#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT (7) // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_7~GPIO_NUM_29) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x3FFFFF80ULL diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 58f6d3306b..363d5ac20f 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -415,10 +415,6 @@ config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK int default 0 -config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT - int - default 6 - config SOC_GPIO_SUPPORT_FORCE_HOLD bool default y diff --git a/components/soc/esp32h4/include/soc/soc_caps.h b/components/soc/esp32h4/include/soc/soc_caps.h index e15ab7b421..4fc870e4d4 100644 --- a/components/soc/esp32h4/include/soc/soc_caps.h +++ b/components/soc/esp32h4/include/soc/soc_caps.h @@ -227,7 +227,6 @@ #define SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP (1) #define SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP #define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5) -#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT (6) // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_6~GPIO_NUM_39) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK (SOC_GPIO_VALID_GPIO_MASK & ~((1ULL<<6) - 1)) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index eaef20b298..af67e2732f 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -715,10 +715,6 @@ config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK int default 0 -config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT - int - default 16 - config SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK hex default 0x007FFFFFFFFF0000 diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 59312c730e..1e2a7e25e5 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -270,7 +270,6 @@ #define SOC_GPIO_OUT_RANGE_MAX 54 #define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | 0xFFFF) -#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_PIN_CNT (16) // digital I/O pad powered by VDD3P3_CPU or VDD_SPI(GPIO_NUM_16~GPIO_NUM_54) #define SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x007FFFFFFFFF0000ULL diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 7025efc9bc..4c75950dad 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -435,6 +435,14 @@ config SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS bool default y +config SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP + bool + default y + +config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK + int + default 0 + config SOC_DEDIC_GPIO_HAS_INTERRUPT bool default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 721c016e62..085a8592f4 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -204,6 +204,11 @@ * (e.g., spinlocks) when accessed from multiple cores or threads. */ #define SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS 1 +// GPIO0~21 on ESP32-S2 can support chip deep sleep wakeup +#define SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP (1) +#define SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP +#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | BIT13 | BIT14 | BIT15 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21) + /*-------------------------- Dedicated GPIO CAPS ---------------------------------------*/ #define SOC_DEDIC_GPIO_HAS_INTERRUPT (1) /*!< Dedicated GPIO has its own interrupt source */ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index fea28af6aa..2f5699f9bb 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -483,6 +483,14 @@ config SOC_GPIO_CLOCKOUT_CHANNEL_NUM int default 3 +config SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP + bool + default y + +config SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK + int + default 0 + config SOC_I2C_NUM int default 2 diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index c4240e242d..ae2d6d9f70 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -201,6 +201,11 @@ #define SOC_GPIO_CLOCKOUT_BY_IO_MUX (1) #define SOC_GPIO_CLOCKOUT_CHANNEL_NUM (3) +// GPIO0~21 on ESP32-S3 can support chip deep sleep wakeup +#define SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP (1) +#define SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP SOC_GPIO_SUPPORT_HP_PERIPH_PD_SLEEP_WAKEUP +#define SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK (0ULL | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | BIT8 | BIT9 | BIT10 | BIT11 | BIT12 | BIT13 | BIT14 | BIT15 | BIT16 | BIT17 | BIT18 | BIT19 | BIT20 | BIT21) + /*-------------------------- I2C CAPS ----------------------------------------*/ #define SOC_I2C_NUM (2U) #define SOC_HP_I2C_NUM (2U) diff --git a/examples/system/deep_sleep/main/Kconfig.projbuild b/examples/system/deep_sleep/main/Kconfig.projbuild index d58be0fd32..0fd23a8a7e 100644 --- a/examples/system/deep_sleep/main/Kconfig.projbuild +++ b/examples/system/deep_sleep/main/Kconfig.projbuild @@ -261,11 +261,18 @@ menu "Example Configuration" config EXAMPLE_GPIO_WAKEUP_PIN int "Enable wakeup from GPIO" + default 2 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 default 0 + range 0 39 if IDF_TARGET_ESP32 + range 0 21 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 range 0 7 if IDF_TARGET_ESP32C6 range 0 6 if IDF_TARGET_ESP32C61 || IDF_TARGET_ESP32C5 range 0 15 if IDF_TARGET_ESP32P4 range 0 5 + help + Only GPIOs which have RTC functionality (pads that powered by VDD3P3_RTC) can be used, + You need to ensure that the set IO can be configured as a GPIO wake-up source, + refer SOC_GPIO_HP_PERIPH_PD_SLEEP_WAKEABLE_MASK in soc_caps.h. config EXAMPLE_GPIO_WAKEUP_HIGH_LEVEL bool "Enable GPIO high-level wakeup" 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"); diff --git a/examples/system/deep_sleep/main/gpio_wakeup.c b/examples/system/deep_sleep/main/gpio_wakeup.c index fd9f889b00..31ddeead43 100644 --- a/examples/system/deep_sleep/main/gpio_wakeup.c +++ b/examples/system/deep_sleep/main/gpio_wakeup.c @@ -20,8 +20,10 @@ void example_deep_sleep_register_gpio_wakeup(void) { const gpio_config_t config = { - .pin_bit_mask = BIT(DEFAULT_WAKEUP_PIN), + .pin_bit_mask = BIT64(DEFAULT_WAKEUP_PIN), .mode = GPIO_MODE_INPUT, + .pull_up_en = !DEFAULT_WAKEUP_LEVEL, + .pull_down_en = DEFAULT_WAKEUP_LEVEL }; ESP_ERROR_CHECK(gpio_config(&config));