From eef2153dd034decd019baf99cd03effb9c43fde8 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Mon, 13 Apr 2026 16:32:21 +0800 Subject: [PATCH] refactor(rtcio): split rtcio/gpio switch with rtc iomux func sel func This allows rtc_gpio_deinit to always switch the pad back to GPIO, regardless of lp io clock enabled or not, so that gpio_config can always switch the IO back to GPIO use after wakeup from deep sleep. --- components/esp_driver_gpio/src/rtc_io.c | 12 ++++-- .../esp32/include/hal/rtc_io_ll.h | 2 - .../esp32c5/include/hal/rtc_io_ll.h | 2 - .../esp32c6/include/hal/rtc_io_ll.h | 26 ++++++------ .../esp32c61/include/hal/rtc_io_ll.h | 26 ++++++------ .../esp32h4/include/hal/rtc_io_ll.h | 26 ++++++------ .../esp32p4/include/hal/rtc_io_ll.h | 40 +++++++++---------- .../esp32s2/include/hal/rtc_io_ll.h | 24 +++++------ .../esp32s3/include/hal/rtc_io_ll.h | 2 - components/esp_hw_support/sleep_modes.c | 3 ++ .../lp_core/include/ulp_lp_core_gpio.h | 1 + 11 files changed, 79 insertions(+), 85 deletions(-) diff --git a/components/esp_driver_gpio/src/rtc_io.c b/components/esp_driver_gpio/src/rtc_io.c index f0742674c88..6558fc14d9b 100644 --- a/components/esp_driver_gpio/src/rtc_io.c +++ b/components/esp_driver_gpio/src/rtc_io.c @@ -54,7 +54,13 @@ esp_err_t rtc_gpio_init(gpio_num_t gpio_num) #if SOC_LP_IO_CLOCK_IS_INDEPENDENT io_mux_enable_lp_io_clock(gpio_num, true); #endif - rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_LL_FUNC_RTC); + int rtcio_num = rtc_io_number_get(gpio_num); + // Select the pad as RTC GPIO + rtcio_hal_function_select(rtcio_num, RTCIO_LL_FUNC_RTC); +#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED + // Select LP GPIO function + rtcio_hal_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); +#endif RTCIO_EXIT_CRITICAL(); return ESP_OK; @@ -64,9 +70,9 @@ esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num) { ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); RTCIO_ENTER_CRITICAL(); + // Select the pad as Digital GPIO (this is usually in AON domain, not relying on lp io clock) + rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_LL_FUNC_DIGITAL); if (io_mux_is_lp_io_in_use(gpio_num)) { - // Select GPIO as Digital GPIO - rtcio_hal_function_select(rtc_io_number_get(gpio_num), RTCIO_LL_FUNC_DIGITAL); #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED // Disable any configuration of the RTC IO that may affect the GPIO behavior rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED); 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 6c4863ea3ac..32f38b9ef7c 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 @@ -60,8 +60,6 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) if (func == RTCIO_LL_FUNC_RTC) { // 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module. SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux)); - //0:RTC FUNCTION 1,2,3:Reserved - rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); } else if (func == RTCIO_LL_FUNC_DIGITAL) { CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux)); } diff --git a/components/esp_hal_gpio/esp32c5/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32c5/include/hal/rtc_io_ll.h index b31218e3955..5856fead2d1 100644 --- a/components/esp_hal_gpio/esp32c5/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32c5/include/hal/rtc_io_ll.h @@ -90,8 +90,6 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel); sel_mask |= BIT(rtcio_num); HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel, sel_mask); - // LP_GPIO is FUNC 1 - rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); } else if (func == RTCIO_LL_FUNC_DIGITAL) { // Clear the bit to use digital GPIO module uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel); diff --git a/components/esp_hal_gpio/esp32c6/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32c6/include/hal/rtc_io_ll.h index 34049ee3b55..a1551cd865f 100644 --- a/components/esp_hal_gpio/esp32c6/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32c6/include/hal/rtc_io_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -42,17 +42,6 @@ typedef enum { RTCIO_LL_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */ } rtcio_ll_out_mode_t; -/** - * @brief Select a RTC IOMUX function for the RTC IO - * - * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). - * @param func Function to assign to the pin - */ -static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) -{ - LP_IO.gpio[rtcio_num].mcu_sel = func; -} - /** * @brief Enable/Disable LP_IO peripheral clock. * @@ -71,6 +60,17 @@ static inline void _rtcio_ll_enable_io_clock(bool enable) _rtcio_ll_enable_io_clock(__VA_ARGS__); \ } while(0) +/** + * @brief Select a RTC IOMUX function for the RTC IO + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param func Function to assign to the pin + */ +static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) +{ + LP_IO.gpio[rtcio_num].mcu_sel = func; +} + /** * @brief Select the rtcio function. * @@ -88,8 +88,6 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel); sel_mask |= BIT(rtcio_num); HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel, sel_mask); - //0:RTC FUNCTION 1,2,3:Reserved - rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); } else if (func == RTCIO_LL_FUNC_DIGITAL) { // Clear the bit to use digital GPIO module uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel); diff --git a/components/esp_hal_gpio/esp32c61/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32c61/include/hal/rtc_io_ll.h index 5107a152621..2a7228ce0ca 100644 --- a/components/esp_hal_gpio/esp32c61/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32c61/include/hal/rtc_io_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -43,17 +43,6 @@ typedef enum { RTCIO_LL_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */ } rtcio_ll_out_mode_t; -/** - * @brief Select a RTC IOMUX function for the RTC IO - * - * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). - * @param func Function to assign to the pin - */ -static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) -{ - LP_IO_MUX.gpion[rtcio_num].gpion_mcu_sel = func; -} - /** * @brief Enable/Disable LP_GPIO peripheral clock. * @@ -72,6 +61,17 @@ static inline void _rtcio_ll_enable_io_clock(bool enable) _rtcio_ll_enable_io_clock(__VA_ARGS__); \ } while(0) +/** + * @brief Select a RTC IOMUX function for the RTC IO + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param func Function to assign to the pin + */ +static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) +{ + LP_IO_MUX.gpion[rtcio_num].gpion_mcu_sel = func; +} + /** * @brief Select the rtcio function. * @@ -89,8 +89,6 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel); sel_mask |= BIT(rtcio_num); HAL_FORCE_MODIFY_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel, sel_mask); - // LP_GPIO is FUNC 1 - rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); } else if (func == RTCIO_LL_FUNC_DIGITAL) { // Clear the bit to use digital GPIO module uint32_t sel_mask = HAL_FORCE_READ_U32_REG_FIELD(LP_AON.gpio_mux, gpio_mux_sel); diff --git a/components/esp_hal_gpio/esp32h4/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32h4/include/hal/rtc_io_ll.h index d2f31815ad7..64dc83cad6a 100644 --- a/components/esp_hal_gpio/esp32h4/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32h4/include/hal/rtc_io_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -43,17 +43,6 @@ typedef enum { RTCIO_LL_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */ } rtcio_ll_out_mode_t; -/** - * @brief Select a RTC IOMUX function for the RTC IO - * - * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). - * @param func Function to assign to the pin - */ -static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) -{ - LP_IO_MUX.gpion[rtcio_num].gpion_mcu_sel = func; -} - /** * @brief Enable/Disable LP_GPIO peripheral clock. * @@ -72,6 +61,17 @@ static inline void _rtcio_ll_enable_io_clock(bool enable) _rtcio_ll_enable_io_clock(__VA_ARGS__); \ } while(0) +/** + * @brief Select a RTC IOMUX function for the RTC IO + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param func Function to assign to the pin + */ +static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) +{ + LP_IO_MUX.gpion[rtcio_num].gpion_mcu_sel = func; +} + /** * @brief Select the rtcio function. * @@ -89,8 +89,6 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) uint32_t sel_mask = LP_AON.gpio_mux.gpio_mux_sel; sel_mask |= BIT(rtcio_num); LP_AON.gpio_mux.gpio_mux_sel = sel_mask; - // LP_GPIO is FUNC 1 - rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); } else if (func == RTCIO_LL_FUNC_DIGITAL) { // Clear the bit to use digital GPIO module uint32_t sel_mask = LP_AON.gpio_mux.gpio_mux_sel; diff --git a/components/esp_hal_gpio/esp32p4/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32p4/include/hal/rtc_io_ll.h index 2ce54ffabf8..f8d1e68cc9c 100644 --- a/components/esp_hal_gpio/esp32p4/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32p4/include/hal/rtc_io_ll.h @@ -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: Apache-2.0 */ @@ -43,6 +43,24 @@ typedef enum { RTCIO_LL_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */ } rtcio_ll_out_mode_t; +/** + * @brief Enable/Disable LP_GPIO peripheral clock. + * + * @param enable true to enable the clock / false to disable the clock + */ +static inline void _rtcio_ll_enable_io_clock(bool enable) +{ + LP_GPIO.clk_en.reg_clk_en = enable; + while (LP_GPIO.clk_en.reg_clk_en != enable) { + ; + } +} + +#define rtcio_ll_enable_io_clock(...) do { \ + (void)__DECLARE_RCC_ATOMIC_ENV; \ + _rtcio_ll_enable_io_clock(__VA_ARGS__); \ +} while(0) + /** * @brief Select RTC GPIO input to a signal. * @@ -119,24 +137,6 @@ static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) } } -/** - * @brief Enable/Disable LP_GPIO peripheral clock. - * - * @param enable true to enable the clock / false to disable the clock - */ -static inline void _rtcio_ll_enable_io_clock(bool enable) -{ - LP_GPIO.clk_en.reg_clk_en = enable; - while (LP_GPIO.clk_en.reg_clk_en != enable) { - ; - } -} - -#define rtcio_ll_enable_io_clock(...) do { \ - (void)__DECLARE_RCC_ATOMIC_ENV; \ - _rtcio_ll_enable_io_clock(__VA_ARGS__); \ - } while(0) - /** * @brief Select the lp_gpio/hp_gpio function to control the pad. * @@ -152,8 +152,6 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) if (func == RTCIO_LL_FUNC_RTC) { // 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module. LP_IOMUX.pad[rtcio_num].mux_sel = 1; - // LP_GPIO is FUNC 1 - rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); } else if (func == RTCIO_LL_FUNC_DIGITAL) { // Clear the bit to use digital GPIO module LP_IOMUX.pad[rtcio_num].mux_sel = 0; 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 8ee834fa5b0..9bf9bacbd84 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 */ @@ -40,6 +40,16 @@ typedef enum { RTCIO_LL_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */ } rtcio_ll_out_mode_t; +/** + * @brief Enable/Disable LP IOMUX clock. + * + * @param enable true to enable the clock / false to disable the clock + */ +static inline void rtcio_ll_enable_io_clock(bool enable) +{ + SENS.sar_io_mux_conf.iomux_clk_gate_en = enable; +} + /** * @brief Select a RTC IOMUX function for the RTC IO * @@ -51,16 +61,6 @@ static inline void rtcio_ll_iomux_func_sel(int rtcio_num, int func) SET_PERI_REG_BITS(rtc_io_desc[rtcio_num].reg, 0x3, func, rtc_io_desc[rtcio_num].func); } -/** - * @brief Enable/Disable LP IOMUX clock. - * - * @param enable true to enable the clock / false to disable the clock - */ -static inline void rtcio_ll_enable_io_clock(bool enable) -{ - SENS.sar_io_mux_conf.iomux_clk_gate_en = enable; -} - /** * @brief Select the rtcio function. * @@ -73,8 +73,6 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) if (func == RTCIO_LL_FUNC_RTC) { // 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module. SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux)); - //0:RTC FUNCTION 1,2,3:Reserved - rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); } else if (func == RTCIO_LL_FUNC_DIGITAL) { CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux)); } 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 65ea59a43ae..86c89dcacec 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 @@ -81,8 +81,6 @@ static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func) } // 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module. SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux)); - //0:RTC FUNCTION 1,2,3:Reserved - rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); } else if (func == RTCIO_LL_FUNC_DIGITAL) { CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux)); // USB Serial JTAG pad re-enable won't be done here (it requires both DM and DP pins not in rtc function) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 1b51c8ddfd4..27e7b022eac 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1914,6 +1914,7 @@ static void ext0_wakeup_prepare(void) #endif rtcio_hal_ext0_set_wakeup_pin(rtc_gpio_num, s_config.ext0_trigger_level); rtcio_hal_function_select(rtc_gpio_num, RTCIO_LL_FUNC_RTC); + rtcio_hal_iomux_func_sel(rtc_gpio_num, RTCIO_LL_PIN_FUNC); rtcio_hal_input_enable(rtc_gpio_num); } @@ -2050,6 +2051,8 @@ static void ext1_wakeup_prepare(void) #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED // Route pad to RTC rtcio_hal_function_select(rtc_pin, RTCIO_LL_FUNC_RTC); + // Select LP GPIO function + rtcio_hal_iomux_func_sel(rtc_pin, RTCIO_LL_PIN_FUNC); // set input enable in sleep mode rtcio_hal_input_enable(rtc_pin); #if SOC_PM_SUPPORT_RTC_PERIPH_PD diff --git a/components/ulp/lp_core/lp_core/include/ulp_lp_core_gpio.h b/components/ulp/lp_core/lp_core/include/ulp_lp_core_gpio.h index 57dd63fedc3..1c2baafb1a0 100644 --- a/components/ulp/lp_core/lp_core/include/ulp_lp_core_gpio.h +++ b/components/ulp/lp_core/lp_core/include/ulp_lp_core_gpio.h @@ -62,6 +62,7 @@ static inline void ulp_lp_core_gpio_init(lp_io_num_t lp_io_num) _rtcio_ll_enable_io_clock(true); #endif rtcio_ll_function_select(lp_io_num, RTCIO_LL_FUNC_RTC); + rtcio_ll_iomux_func_sel(lp_io_num, RTCIO_LL_PIN_FUNC); } /**