diff --git a/components/esp_driver_gpio/include/driver/rtc_io.h b/components/esp_driver_gpio/include/driver/rtc_io.h index 53e595105b..42294a8c05 100644 --- a/components/esp_driver_gpio/include/driver/rtc_io.h +++ b/components/esp_driver_gpio/include/driver/rtc_io.h @@ -208,6 +208,31 @@ esp_err_t rtc_gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t* s */ esp_err_t rtc_gpio_iomux_func_sel(gpio_num_t gpio_num, int func); +/** + * @brief Set pad input to an LP peripheral signal through the LP(RTC) IOMUX. + * + * @param gpio_num GPIO number + * @param func The index number of the LP(RTC) IOMUX function to be selected for the pin + * @param signal_idx Peripheral signal index to input. One of the ``*_IN_IDX`` signals in ``soc/lp_gpio_sig_map.h``. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO number error + */ +esp_err_t rtc_gpio_iomux_input(gpio_num_t gpio_num, int func, uint32_t signal_idx); + +/** + * @brief Set LP peripheral output to an RTC IO pad through the LP(RTC) IOMUX. + * + * @param gpio_num GPIO number + * @param func The index number of the LP(RTC) IOMUX function to be selected for the pin + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO number error + */ +esp_err_t rtc_gpio_iomux_output(gpio_num_t gpio_num, int func); + #endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED #if SOC_RTCIO_HOLD_SUPPORTED diff --git a/components/esp_driver_gpio/src/rtc_io.c b/components/esp_driver_gpio/src/rtc_io.c index 48926b0bcb..f0742674c8 100644 --- a/components/esp_driver_gpio/src/rtc_io.c +++ b/components/esp_driver_gpio/src/rtc_io.c @@ -191,6 +191,24 @@ esp_err_t rtc_gpio_iomux_func_sel(gpio_num_t gpio_num, int func) return ESP_OK; } +esp_err_t rtc_gpio_iomux_input(gpio_num_t gpio_num, int func, uint32_t signal_idx) +{ + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); + RTCIO_ENTER_CRITICAL(); + rtcio_hal_iomux_input(rtc_io_number_get(gpio_num), func, signal_idx); + RTCIO_EXIT_CRITICAL(); + return ESP_OK; +} + +esp_err_t rtc_gpio_iomux_output(gpio_num_t gpio_num, int func) +{ + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "RTCIO number error"); + RTCIO_ENTER_CRITICAL(); + rtcio_hal_iomux_output(rtc_io_number_get(gpio_num), func); + RTCIO_EXIT_CRITICAL(); + return ESP_OK; +} + #if SOC_LP_GPIO_MATRIX_SUPPORTED esp_err_t lp_gpio_connect_in_signal(gpio_num_t gpio_num, uint32_t signal_idx, bool inv) { diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 6e24273be5..e6ce90bb83 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -732,13 +732,12 @@ static bool uart_try_set_iomux_pin(uart_port_t uart_num, int io_num, uint32_t id } #if (SOC_UART_LP_NUM >= 1) && (SOC_RTCIO_PIN_COUNT >= 1) else { - if (upin->input) { - rtc_gpio_set_direction(io_num, RTC_GPIO_MODE_INPUT_ONLY); - } else { - rtc_gpio_set_direction(io_num, RTC_GPIO_MODE_OUTPUT_ONLY); - } rtc_gpio_init(io_num); - rtc_gpio_iomux_func_sel(io_num, upin->iomux_func); + if (upin->input) { + rtc_gpio_iomux_input(io_num, upin->iomux_func, upin->signal); + } else { + rtc_gpio_iomux_output(io_num, upin->iomux_func); + } // undo the workaround done in uart_module_enable for RX pin #if !SOC_LP_GPIO_MATRIX_SUPPORTED if (upin->input) { diff --git a/components/esp_driver_uart/test_apps/uart/main/test_uart.c b/components/esp_driver_uart/test_apps/uart/main/test_uart.c index de9c2a0045..7c3aeef15c 100644 --- a/components/esp_driver_uart/test_apps/uart/main/test_uart.c +++ b/components/esp_driver_uart/test_apps/uart/main/test_uart.c @@ -727,7 +727,7 @@ IRAM_ATTR static void uart_signal_inject_glitch_task(void *param) #if SOC_UART_LP_NUM > 0 && SOC_LP_GPIO_MATRIX_SUPPORTED } else { rtcio_ll_matrix_out(rtc_gpio_num, LP_SIG_GPIO_OUT_IDX, false, false); - LP_GPIO.func_out_sel_cfg[rtc_gpio_num].oe_sel = 1; + rtcio_ll_set_output_enable_ctrl(rtc_gpio_num, false, false); rtcio_ll_matrix_out(rtc_gpio_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_TX), false, false); #endif } 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 a76abbcd4f..c057601135 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 @@ -73,11 +73,37 @@ static inline void rtcio_ll_matrix_out(int rtcio_num, uint32_t signal_idx, bool reg.func_out_sel = signal_idx; reg.out_inv_sel = out_inv; reg.oe_inv_sel = oen_inv; + reg.oe_sel = 0; // output enable signal controlled by peripheral LP_GPIO.func_out_sel_cfg[rtcio_num].val = reg.val; HAL_FORCE_MODIFY_U32_REG_FIELD(LP_GPIO.enable_w1ts, reg_gpio_enable_data_w1ts, BIT(rtcio_num)); } +/** + * @brief Configure peripheral signal input whether to bypass LP_GPIO matrix. + * + * @param signal_idx LP peripheral signal index. + * @param from_gpio_matrix True if not to bypass LP_GPIO matrix, otherwise False. + */ +static inline void rtcio_ll_set_input_signal_from(uint32_t signal_idx, bool from_gpio_matrix) +{ + LP_GPIO.func_in_sel_cfg[signal_idx].sig_in_sel = from_gpio_matrix; +} + +/** + * @brief Configure the source of output enable signal for the pad (only takes effect if func sel is selected to be LP_GPIO). + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param ctrl_by_periph True if use output enable signal from peripheral, false if force the output enable signal to be sourced from bit n of LP_GPIO_ENABLE_REG + * @param oen_inv True if the output enable needs to be inverted, otherwise False. + */ +__attribute__((always_inline)) +static inline void rtcio_ll_set_output_enable_ctrl(int rtcio_num, bool ctrl_by_periph, bool oen_inv) +{ + LP_GPIO.func_out_sel_cfg[rtcio_num].oe_inv_sel = oen_inv; // control valid only when using lp gpio matrix to route signal to the LP IO + LP_GPIO.func_out_sel_cfg[rtcio_num].oe_sel = !ctrl_by_periph; +} + /** * @brief Select a RTC IOMUX function for the RTC IO * diff --git a/components/esp_hal_gpio/esp32s31/include/hal/rtc_io_ll.h b/components/esp_hal_gpio/esp32s31/include/hal/rtc_io_ll.h index ba5e35eba8..262e3cc7b5 100644 --- a/components/esp_hal_gpio/esp32s31/include/hal/rtc_io_ll.h +++ b/components/esp_hal_gpio/esp32s31/include/hal/rtc_io_ll.h @@ -71,11 +71,7 @@ static inline void _rtcio_ll_enable_io_clock(bool enable) ; } } - -static inline void rtcio_ll_enable_io_clock(bool enable) -{ - _rtcio_ll_enable_io_clock(enable); -} +#define rtcio_ll_enable_io_clock(...) _rtcio_ll_enable_io_clock(__VA_ARGS__) /** * @brief Select the rtcio function. @@ -446,7 +442,7 @@ static inline void rtcio_ll_clear_interrupt_status(void) * @param signal_idx LP peripheral input signal index (0 .. IN_SIGNAL_MAX - 1). * @param inv True to invert input signal; False then no invert. */ -static inline void rtcio_ll_matrix_in(int rtcio_num, int signal_idx, bool inv) +static inline void rtcio_ll_matrix_in(int rtcio_num, uint32_t signal_idx, bool inv) { lp_gpio_funca_in_sel_cfg_reg_t reg; reg.funca_in_sel = rtcio_num; @@ -463,17 +459,43 @@ static inline void rtcio_ll_matrix_in(int rtcio_num, int signal_idx, bool inv) * @param out_inv True to invert output signal; False then no invert. * @param oen_inv True to invert output enable signal; False then no invert. */ -static inline void rtcio_ll_matrix_out(int rtcio_num, int signal_idx, bool out_inv, bool oen_inv) +static inline void rtcio_ll_matrix_out(int rtcio_num, uint32_t signal_idx, bool out_inv, bool oen_inv) { lp_gpio_funcn_out_sel_cfg_reg_t reg; reg.funcn_out_sel = signal_idx; reg.funcn_out_inv_sel = out_inv; reg.funcn_oe_inv_sel = oen_inv; + reg.funcn_oe_sel = 0; // output enable signal controlled by peripheral LP_GPIO.funcn_out_sel_cfg[rtcio_num].val = reg.val; HAL_FORCE_MODIFY_U32_REG_FIELD(LP_GPIO.enable_w1ts, enable_w1ts, BIT(rtcio_num)); } +/** + * @brief Configure peripheral signal input whether to bypass LP_GPIO matrix. + * + * @param signal_idx LP peripheral signal index. + * @param from_gpio_matrix True if not to bypass LP_GPIO matrix, otherwise False. + */ +static inline void rtcio_ll_set_input_signal_from(uint32_t signal_idx, bool from_gpio_matrix) +{ + LP_GPIO.funca_in_sel_cfg[signal_idx].siga_in_sel = from_gpio_matrix; +} + +/** + * @brief Configure the source of output enable signal for the pad (only takes effect if func sel is selected to be LP_GPIO). + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param ctrl_by_periph True if use output enable signal from peripheral, false if force the output enable signal to be sourced from bit n of LP_GPIO_ENABLE_REG + * @param oen_inv True if the output enable needs to be inverted, otherwise False. + */ +__attribute__((always_inline)) +static inline void rtcio_ll_set_output_enable_ctrl(int rtcio_num, bool ctrl_by_periph, bool oen_inv) +{ + LP_GPIO.funcn_out_sel_cfg[rtcio_num].funcn_oe_inv_sel = oen_inv; // control valid only when using lp gpio matrix to route signal to the LP IO + LP_GPIO.funcn_out_sel_cfg[rtcio_num].funcn_oe_sel = !ctrl_by_periph; +} + #ifdef __cplusplus } #endif diff --git a/components/esp_hal_gpio/include/hal/rtc_io_hal.h b/components/esp_hal_gpio/include/hal/rtc_io_hal.h index e9fe1f22b9..fe95a41c94 100644 --- a/components/esp_hal_gpio/include/hal/rtc_io_hal.h +++ b/components/esp_hal_gpio/include/hal/rtc_io_hal.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 */ @@ -184,6 +184,23 @@ void rtcio_hal_set_direction_in_sleep(int rtcio_num, rtc_gpio_mode_t mode); */ #define rtcio_hal_iomux_func_sel(rtcio_num, func) rtcio_ll_iomux_func_sel(rtcio_num, func) +/** + * @brief Set pad input to an LP peripheral signal through the LP(RTC) IOMUX + * + * @param rtcio_num The index of rtcio. 0 ~ SOC_RTCIO_PIN_COUNT. + * @param func The index number of the IOMUX function to be selected for the pin. + * @param signal_idx Peripheral signal index to input. One of the ``*_IN_IDX`` signals in ``soc/lp_gpio_sig_map.h``. + */ +void rtcio_hal_iomux_input(int rtcio_num, int func, uint32_t signal_idx); + +/** + * @brief Set LP peripheral output to an RTC IO pad through the LP(RTC) IOMUX + * + * @param rtcio_num The index of rtcio. 0 ~ SOC_RTCIO_PIN_COUNT. + * @param func The index number of the LP(RTC) IOMUX function to be selected for the pin + */ +void rtcio_hal_iomux_output(int rtcio_num, int func); + #if SOC_LP_GPIO_MATRIX_SUPPORTED /** * Select RTC GPIO input to a signal diff --git a/components/esp_hal_gpio/rtc_io_hal.c b/components/esp_hal_gpio/rtc_io_hal.c index 2d38e7d3bb..74fe537f1b 100644 --- a/components/esp_hal_gpio/rtc_io_hal.c +++ b/components/esp_hal_gpio/rtc_io_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,4 +85,19 @@ void rtcio_hal_isolate(int rtcio_num) rtcio_ll_input_disable(rtcio_num); } +void rtcio_hal_iomux_input(int rtcio_num, int func, uint32_t signal_idx) +{ + rtcio_ll_input_enable(rtcio_num); + rtcio_ll_iomux_func_sel(rtcio_num, func); +#if SOC_LP_GPIO_MATRIX_SUPPORTED + rtcio_ll_set_input_signal_from(signal_idx, false); +#endif +} + +void rtcio_hal_iomux_output(int rtcio_num, int func) +{ + rtcio_ll_iomux_func_sel(rtcio_num, func); + // as long as the func sel is not RTC IO, the oe can only be controlled by the peripheral +} + #endif //SOC_RTCIO_INPUT_OUTPUT_SUPPORTED