diff --git a/components/esp_driver_gpio/include/driver/lp_io.h b/components/esp_driver_gpio/include/driver/lp_io.h index aafc409248d..73fdbbe02cb 100644 --- a/components/esp_driver_gpio/include/driver/lp_io.h +++ b/components/esp_driver_gpio/include/driver/lp_io.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,6 +44,40 @@ esp_err_t lp_gpio_connect_in_signal(gpio_num_t gpio_num, uint32_t signal_idx, bo * - ESP_ERR_INVALID_ARG Parameter error */ esp_err_t lp_gpio_connect_out_signal(gpio_num_t gpio_num, uint32_t signal_idx, bool out_inv, bool out_en_inv); + +/** + * @brief Set LP IO pad input to a LP peripheral signal through the LP GPIO matrix + * + * @note There's no limitation on the number of signals that a RTC(LP) GPIO can connect with + * + * @param gpio_num GPIO number, especially, `LP_GPIO_MATRIX_CONST_ZERO_INPUT` means connect logic 0 to signal; + * `LP_GPIO_MATRIX_CONST_ONE_INPUT` means connect logic 1 to signal. + * @param signal_idx LP peripheral signal index (tagged as input attribute). + * One of the ``*_IN_IDX`` signals in ``soc/gpio_sig_map.h``. + * @param in_inv Whether the RTC(LP) IO input to be inverted or not. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO number error + */ +esp_err_t lp_gpio_matrix_input(gpio_num_t gpio_num, uint32_t signal_idx, bool in_inv); + +/** + * @brief Set LP peripheral output to an LP GPIO pad through the LP GPIO matrix + * + * @note There's no limitation on the number of LP IOs that a signal can connect with + * + * @param gpio_num GPIO number + * @param signal_idx LP peripheral signal index (tagged as input attribute), especially, `LP_SIG_GPIO_OUT_IDX` means disconnect RTC(LP) GPIO and other peripherals. Only the RTC GPIO driver can control the output level + * @param out_inv Whether to signal to be inverted or not. + * @param out_en_inv Whether the output enable control is inverted or not. + * + * @return + * - ESP_OK Success + * - ESP_ERR_INVALID_ARG GPIO number error + */ +esp_err_t lp_gpio_matrix_output(gpio_num_t gpio_num, uint32_t signal_idx, bool out_inv, bool out_en_inv); + #endif // SOC_LP_GPIO_MATRIX_SUPPORTED #ifdef __cplusplus diff --git a/components/esp_driver_gpio/src/rtc_io.c b/components/esp_driver_gpio/src/rtc_io.c index 6558fc14d9b..b312de316ad 100644 --- a/components/esp_driver_gpio/src/rtc_io.c +++ b/components/esp_driver_gpio/src/rtc_io.c @@ -216,7 +216,7 @@ esp_err_t rtc_gpio_iomux_output(gpio_num_t gpio_num, int func) } #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) +esp_err_t lp_gpio_matrix_input(gpio_num_t gpio_num, uint32_t signal_idx, bool inv) { uint32_t io_num; if (gpio_num == LP_GPIO_MATRIX_CONST_ZERO_INPUT || gpio_num == LP_GPIO_MATRIX_CONST_ONE_INPUT) { @@ -229,12 +229,35 @@ esp_err_t lp_gpio_connect_in_signal(gpio_num_t gpio_num, uint32_t signal_idx, bo return ESP_OK; } -esp_err_t lp_gpio_connect_out_signal(gpio_num_t gpio_num, uint32_t signal_idx, bool out_inv, bool out_en_inv) +esp_err_t lp_gpio_matrix_output(gpio_num_t gpio_num, uint32_t signal_idx, bool out_inv, bool out_en_inv) { ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "LP_IO number error"); rtcio_hal_matrix_out(rtc_io_number_get(gpio_num), signal_idx, out_inv, out_en_inv); return ESP_OK; } + +esp_err_t lp_gpio_connect_in_signal(gpio_num_t gpio_num, uint32_t signal_idx, bool inv) +{ + uint32_t io_num; + if (gpio_num == LP_GPIO_MATRIX_CONST_ZERO_INPUT || gpio_num == LP_GPIO_MATRIX_CONST_ONE_INPUT) { + io_num = gpio_num; + } else { + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "LP_IO number error"); + io_num = rtc_io_number_get(gpio_num); + } + rtcio_ll_set_input_signal_matrix_source(io_num, signal_idx, inv); + return ESP_OK; +} + +esp_err_t lp_gpio_connect_out_signal(gpio_num_t gpio_num, uint32_t signal_idx, bool out_inv, bool out_en_inv) +{ + ESP_RETURN_ON_FALSE(rtc_gpio_is_valid_gpio(gpio_num), ESP_ERR_INVALID_ARG, RTCIO_TAG, "LP_IO number error"); + uint32_t rtcio_num = rtc_io_number_get(gpio_num); + rtcio_ll_set_output_signal_matrix_source(rtcio_num, signal_idx, out_inv); + rtcio_ll_set_output_enable_ctrl(rtcio_num, true, out_en_inv); + return ESP_OK; +} + #endif // SOC_LP_GPIO_MATRIX_SUPPORTED #endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 69e89ae23de..3b7a097e5f5 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -264,7 +264,7 @@ static bool uart_module_enable(uart_port_t uart_num) // Workaround: Set RX signal to high to avoid false RX BRK_DET interrupt raised after register reset if (uart_context[uart_num].rx_io_num == -1) { // if RX pin is already configured, then workaround not needed, skip #if SOC_LP_GPIO_MATRIX_SUPPORTED - lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_RX), false); + rtcio_ll_set_input_signal_matrix_source(LP_GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_RX), false); #else // the signal is directly connected to its LP IO pin, the only way is to enable its pullup uint32_t io_num = uart_periph_signal[uart_num].pins[SOC_UART_PERIPH_SIGNAL_RX].default_gpio; @@ -782,7 +782,7 @@ static void uart_release_pin(uart_port_t uart_num, bool release_tx, bool release #if (SOC_UART_LP_NUM >= 1) else { #if SOC_LP_GPIO_MATRIX_SUPPORTED - lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_RX), false); + lp_gpio_matrix_input(LP_GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_RX), false); #endif rtc_gpio_deinit(uart_context[uart_num].rx_io_num); } @@ -814,7 +814,7 @@ static void uart_release_pin(uart_port_t uart_num, bool release_tx, bool release #if (SOC_UART_LP_NUM >= 1) else { #if SOC_LP_GPIO_MATRIX_SUPPORTED - lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_CTS), false); + lp_gpio_matrix_input(LP_GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_CTS), false); #endif rtc_gpio_deinit(uart_context[uart_num].cts_io_num); } @@ -843,7 +843,7 @@ static void uart_release_pin(uart_port_t uart_num, bool release_tx, bool release #if (SOC_UART_LP_NUM >= 1) else { #if SOC_LP_GPIO_MATRIX_SUPPORTED - lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_DSR), false); + lp_gpio_matrix_input(LP_GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_DSR), false); #endif rtc_gpio_deinit(uart_context[uart_num].dsr_io_num); } @@ -928,8 +928,8 @@ esp_err_t _uart_set_pin6(uart_port_t uart_num, int tx_io_num, int rx_io_num, int #if SOC_LP_GPIO_MATRIX_SUPPORTED && (SOC_UART_LP_NUM >= 1) else { rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin - lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_TX), 0, 0); - // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected + lp_gpio_matrix_output(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_TX), 0, 0); + // output enable is set inside lp_gpio_matrix_output func after the signal is connected } #endif } @@ -950,13 +950,10 @@ esp_err_t _uart_set_pin6(uart_port_t uart_num, int tx_io_num, int rx_io_num, int } #if SOC_LP_GPIO_MATRIX_SUPPORTED && (SOC_UART_LP_NUM >= 1) else { - rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY); - rtc_gpio_set_direction(rx_io_num, mode); if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin } - - lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_RX), 0); + lp_gpio_matrix_input(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_RX), 0); } #endif } @@ -969,8 +966,8 @@ esp_err_t _uart_set_pin6(uart_port_t uart_num, int tx_io_num, int rx_io_num, int #if SOC_LP_GPIO_MATRIX_SUPPORTED && (SOC_UART_LP_NUM >= 1) else { rtc_gpio_init(rts_io_num); // set as a LP_GPIO pin - lp_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_RTS), 0, 0); - // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected + lp_gpio_matrix_output(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_RTS), 0, 0); + // output enable is set inside lp_gpio_matrix_output func after the signal is connected } #endif } @@ -982,9 +979,8 @@ esp_err_t _uart_set_pin6(uart_port_t uart_num, int tx_io_num, int rx_io_num, int } #if SOC_LP_GPIO_MATRIX_SUPPORTED && (SOC_UART_LP_NUM >= 1) else { - rtc_gpio_set_direction(cts_io_num, RTC_GPIO_MODE_INPUT_ONLY); rtc_gpio_init(cts_io_num); // set as a LP_GPIO pin - lp_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_CTS), 0); + lp_gpio_matrix_input(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_CTS), 0); } #endif } @@ -996,8 +992,8 @@ esp_err_t _uart_set_pin6(uart_port_t uart_num, int tx_io_num, int rx_io_num, int #if SOC_LP_GPIO_MATRIX_SUPPORTED && (SOC_UART_LP_NUM >= 1) else { rtc_gpio_init(dtr_io_num); // set as a LP_GPIO pin - lp_gpio_connect_out_signal(dtr_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_DTR), 0, 0); - // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected + lp_gpio_matrix_output(dtr_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_DTR), 0, 0); + // output enable is set inside lp_gpio_matrix_output func after the signal is connected } #endif } @@ -1009,9 +1005,8 @@ esp_err_t _uart_set_pin6(uart_port_t uart_num, int tx_io_num, int rx_io_num, int } #if SOC_LP_GPIO_MATRIX_SUPPORTED && (SOC_UART_LP_NUM >= 1) else { - rtc_gpio_set_direction(dsr_io_num, RTC_GPIO_MODE_INPUT_ONLY); rtc_gpio_init(dsr_io_num); // set as a LP_GPIO pin - lp_gpio_connect_in_signal(dsr_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_DSR), 0); + lp_gpio_matrix_input(dsr_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_DSR), 0); } #endif } 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 7c3aeef15c7..b6a270edea0 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 @@ -533,10 +533,9 @@ TEST_CASE("uart int state restored after flush", "[uart]") // This means RX IO should also only use LP_GPIO matrix to connect the RX signal // In case the selected RX IO is the LP UART IOMUX IO, and the IO has been configured to IOMUX function in the driver // Do the following: - TEST_ESP_OK(rtc_gpio_iomux_func_sel(uart_rx, RTCIO_LL_PIN_FUNC)); const int uart_rx_signal = uart_periph_signal[uart_num].pins[SOC_UART_PERIPH_SIGNAL_RX].signal; - TEST_ESP_OK(lp_gpio_connect_in_signal(uart_rx, uart_rx_signal, false)); - TEST_ESP_OK(lp_gpio_connect_out_signal(uart_rx, uart_tx_signal, false, false)); + TEST_ESP_OK(lp_gpio_matrix_input(uart_rx, uart_rx_signal, false)); + TEST_ESP_OK(lp_gpio_matrix_output(uart_rx, uart_tx_signal, false, false)); #else // The only way is to use loop back feature TEST_ESP_OK(uart_set_loop_back(uart_num, true)); @@ -710,25 +709,27 @@ IRAM_ATTR static void uart_signal_inject_glitch_task(void *param) uart_port_param_t *port_param = (uart_port_param_t *)param; uart_port_t uart_num = port_param->port_num; uint32_t tx_pin = port_param->tx_pin_num; + uint32_t tx_signal = UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_TX); // while sending, frequently disconnect from UART TX signal and set level to high to create glitches gpio_ll_set_level(&GPIO, tx_pin, 1); + gpio_ll_output_enable(&GPIO, tx_pin); #if SOC_UART_LP_NUM > 0 && SOC_LP_GPIO_MATRIX_SUPPORTED uint32_t rtc_gpio_num = rtc_io_number_get(tx_pin); rtcio_ll_set_level(rtc_gpio_num, 1); + rtcio_ll_output_enable(rtc_gpio_num); #endif while (1) { // make sure the glitch is always less than 6us portDISABLE_INTERRUPTS(); if (uart_num < SOC_UART_HP_NUM) { - esp_rom_gpio_connect_out_signal(tx_pin, SIG_GPIO_OUT_IDX, false, false); - gpio_ll_set_output_enable_ctrl(&GPIO, tx_pin, false, false); - esp_rom_gpio_connect_out_signal(tx_pin, UART_PERIPH_SIGNAL(uart_num, SOC_UART_PERIPH_SIGNAL_TX), false, false); + gpio_ll_set_output_signal_matrix_source(&GPIO, tx_pin, SIG_GPIO_OUT_IDX, false); + // // When IO is set to GPIO use, its output control is only controlled by the GPIO_ENABLE_REG only + gpio_ll_set_output_signal_matrix_source(&GPIO, tx_pin, tx_signal, false); #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); - 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); + rtcio_ll_set_output_signal_matrix_source(rtc_gpio_num, LP_SIG_GPIO_OUT_IDX, false); + rtcio_ll_set_output_signal_matrix_source(rtc_gpio_num, tx_signal, false); #endif } portENABLE_INTERRUPTS(); diff --git a/components/esp_hal_gpio/esp32/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32/include/hal/gpio_ll.h index 8797fbc5fb4..19c64d9433d 100644 --- a/components/esp_hal_gpio/esp32/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32/include/hal/gpio_ll.h @@ -755,6 +755,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->func_out_sel_cfg[gpio_num].func_sel = signal_idx; diff --git a/components/esp_hal_gpio/esp32c2/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c2/include/hal/gpio_ll.h index 0b720bf20f0..a7a77719287 100644 --- a/components/esp_hal_gpio/esp32c2/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c2/include/hal/gpio_ll.h @@ -561,6 +561,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->func_out_sel_cfg[gpio_num], out_sel, signal_idx); diff --git a/components/esp_hal_gpio/esp32c3/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c3/include/hal/gpio_ll.h index d4455f0a468..f12998e91d1 100644 --- a/components/esp_hal_gpio/esp32c3/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c3/include/hal/gpio_ll.h @@ -558,6 +558,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->func_out_sel_cfg[gpio_num], out_sel, signal_idx); diff --git a/components/esp_hal_gpio/esp32c5/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c5/include/hal/gpio_ll.h index 1abf8a4927c..a271fb14df6 100644 --- a/components/esp_hal_gpio/esp32c5/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c5/include/hal/gpio_ll.h @@ -545,6 +545,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->func_out_sel_cfg[gpio_num].out_sel = signal_idx; diff --git a/components/esp_hal_gpio/esp32c6/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c6/include/hal/gpio_ll.h index 701d20e2250..d22a4f47a93 100644 --- a/components/esp_hal_gpio/esp32c6/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c6/include/hal/gpio_ll.h @@ -509,6 +509,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->func_out_sel_cfg[gpio_num], out_sel, signal_idx); diff --git a/components/esp_hal_gpio/esp32c61/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c61/include/hal/gpio_ll.h index 4b4b2596916..62eac10d626 100644 --- a/components/esp_hal_gpio/esp32c61/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c61/include/hal/gpio_ll.h @@ -545,6 +545,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->funcn_out_sel_cfg[gpio_num].funcn_out_sel = signal_idx; diff --git a/components/esp_hal_gpio/esp32h2/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32h2/include/hal/gpio_ll.h index 283926d0213..99646d16508 100644 --- a/components/esp_hal_gpio/esp32h2/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32h2/include/hal/gpio_ll.h @@ -555,6 +555,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->func_out_sel_cfg[gpio_num], out_sel, signal_idx); diff --git a/components/esp_hal_gpio/esp32h21/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32h21/include/hal/gpio_ll.h index 22a7535ae53..fb05f818a42 100644 --- a/components/esp_hal_gpio/esp32h21/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32h21/include/hal/gpio_ll.h @@ -536,6 +536,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->funcn_out_sel_cfg[gpio_num].funcn_out_sel = signal_idx; diff --git a/components/esp_hal_gpio/esp32h4/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32h4/include/hal/gpio_ll.h index beffbc5b64a..32ca031cb58 100644 --- a/components/esp_hal_gpio/esp32h4/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32h4/include/hal/gpio_ll.h @@ -554,6 +554,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->funcn_out_sel_cfg[gpio_num].out_sel = signal_idx; diff --git a/components/esp_hal_gpio/esp32p4/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32p4/include/hal/gpio_ll.h index 995df508567..d344761cb07 100644 --- a/components/esp_hal_gpio/esp32p4/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32p4/include/hal/gpio_ll.h @@ -671,6 +671,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->func_out_sel_cfg[gpio_num].out_sel = signal_idx; 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 045c182ebfb..d61d6116d73 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 @@ -58,59 +58,39 @@ static inline void _rtcio_ll_enable_io_clock(bool enable) #define rtcio_ll_enable_io_clock(...) _rtcio_ll_enable_io_clock(__VA_ARGS__) /** - * @brief Select RTC GPIO input to a signal. + * @brief Configure peripheral signal input whether to bypass LP_GPIO matrix. * - * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). * @param signal_idx LP peripheral signal index. - * @param inv True to invert input signal; False then no invert. + * @param from_gpio_matrix True if not to bypass LP_GPIO matrix, otherwise False. */ -static inline void rtcio_ll_matrix_in(int rtcio_num, uint32_t signal_idx, bool inv) -{ - lp_gpio_func_in_sel_cfg_reg_t reg; - reg.func_in_sel = rtcio_num; - reg.in_inv_sel = inv; - reg.sig_in_sel = 1; // Signal should not bypass LP_GPIO matrix - LP_GPIO.func_in_sel_cfg[signal_idx].val = reg.val; -} - -/** - * @brief Select signal output to a RTC GPIO. - * - * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). - * @param signal_idx LP peripheral signal index. - * @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, uint32_t signal_idx, bool out_inv, bool oen_inv) -{ - lp_gpio_func_out_sel_cfg_reg_t reg; - 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. - */ + * @brief Connect a LP GPIO input with a LP peripheral signal, which tagged as input attribute. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param signal_idx LP peripheral signal index. + * @param inv True to invert input signal; False then no invert. + */ +static inline void rtcio_ll_set_input_signal_matrix_source(int rtcio_num, uint32_t signal_idx, bool inv) +{ + lp_gpio_func_in_sel_cfg_reg_t reg; + reg.func_in_sel = rtcio_num; + reg.in_inv_sel = inv; + LP_GPIO.func_in_sel_cfg[signal_idx].val = reg.val; + rtcio_ll_set_input_signal_from(signal_idx, true); // Signal should not bypass LP_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) { @@ -118,6 +98,22 @@ static inline void rtcio_ll_set_output_enable_ctrl(int rtcio_num, bool ctrl_by_p LP_GPIO.func_out_sel_cfg[rtcio_num].oe_sel = !ctrl_by_periph; } +/** + * @brief Connect a LP peripheral signal which tagged as output attribute with a LP GPIO. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param signal_idx LP peripheral signal index. + * @param out_inv True to invert output signal; False then no invert. + */ +__attribute__((always_inline)) +static inline void rtcio_ll_set_output_signal_matrix_source(int rtcio_num, uint32_t signal_idx, bool out_inv) +{ + lp_gpio_func_out_sel_cfg_reg_t reg; + reg.func_out_sel = signal_idx; + reg.out_inv_sel = out_inv; + LP_GPIO.func_out_sel_cfg[rtcio_num].val = reg.val; +} + /** * @brief Select a RTC IOMUX function for the RTC IO * diff --git a/components/esp_hal_gpio/esp32s2/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32s2/include/hal/gpio_ll.h index f6139c13325..d33ffad972e 100644 --- a/components/esp_hal_gpio/esp32s2/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32s2/include/hal/gpio_ll.h @@ -576,6 +576,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->func_out_sel_cfg[gpio_num].func_sel = signal_idx; diff --git a/components/esp_hal_gpio/esp32s3/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32s3/include/hal/gpio_ll.h index e345424e0bf..33d508ad564 100644 --- a/components/esp_hal_gpio/esp32s3/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32s3/include/hal/gpio_ll.h @@ -578,6 +578,7 @@ static inline void gpio_ll_set_output_enable_ctrl(gpio_dev_t *hw, uint8_t gpio_n * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->func_out_sel_cfg[gpio_num].func_sel = signal_idx; diff --git a/components/esp_hal_gpio/esp32s31/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32s31/include/hal/gpio_ll.h index 801094b70d8..0237313723f 100644 --- a/components/esp_hal_gpio/esp32s31/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32s31/include/hal/gpio_ll.h @@ -94,6 +94,7 @@ static inline void gpio_ll_pullup_en(gpio_dev_t *hw, uint32_t gpio_num) * @param signal_idx Peripheral signal index (tagged as output attribute). Particularly, `SIG_GPIO_OUT_IDX` means disconnect GPIO and other peripherals. Only the GPIO driver can control the output level. * @param out_inv True if the signal output needs to be inverted, otherwise False. */ +__attribute__((always_inline)) static inline void gpio_ll_set_output_signal_matrix_source(gpio_dev_t *hw, uint32_t gpio_num, uint32_t signal_idx, bool out_inv) { hw->func_out_sel_cfg[gpio_num].out_sel = signal_idx; 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 419add797fb..407ee0e3a45 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 @@ -435,59 +435,39 @@ static inline void rtcio_ll_clear_interrupt_status(void) } /** - * @brief Select RTC GPIO input to a signal. + * @brief Configure peripheral signal input whether to bypass LP_GPIO matrix. * - * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). - * @param signal_idx LP peripheral input signal index (0 .. IN_SIGNAL_MAX - 1). - * @param inv True to invert input signal; False then no invert. + * @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_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; - reg.funca_in_inv_sel = inv; - reg.siga_in_sel = 1; // Signal should not bypass LP_GPIO matrix - LP_GPIO.funca_in_sel_cfg[signal_idx].val = reg.val; -} - -/** - * @brief Select signal output to a RTC GPIO - * - * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). - * @param signal_idx Peripheral output signal index (0 .. OUT_SIGNAL_MAX - 1). - * @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, 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. - */ + * @brief Connect a LP GPIO input with a LP peripheral signal, which tagged as input attribute. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @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_set_input_signal_matrix_source(int rtcio_num, uint32_t signal_idx, bool inv) +{ + lp_gpio_funca_in_sel_cfg_reg_t reg; + reg.funca_in_sel = rtcio_num; + reg.funca_in_inv_sel = inv; + LP_GPIO.funca_in_sel_cfg[signal_idx].val = reg.val; + rtcio_ll_set_input_signal_from(signal_idx, true); // Signal should not bypass LP_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) { @@ -495,6 +475,22 @@ static inline void rtcio_ll_set_output_enable_ctrl(int rtcio_num, bool ctrl_by_p LP_GPIO.funcn_out_sel_cfg[rtcio_num].funcn_oe_sel = !ctrl_by_periph; } +/** + * @brief Connect a LP peripheral signal which tagged as output attribute with a LP GPIO. + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param signal_idx Peripheral output signal index (0 .. OUT_SIGNAL_MAX - 1). + * @param out_inv True to invert output signal; False then no invert. + */ +__attribute__((always_inline)) +static inline void rtcio_ll_set_output_signal_matrix_source(int rtcio_num, uint32_t signal_idx, bool out_inv) +{ + lp_gpio_funcn_out_sel_cfg_reg_t reg; + reg.funcn_out_sel = signal_idx; + reg.funcn_out_inv_sel = out_inv; + LP_GPIO.funcn_out_sel_cfg[rtcio_num].val = reg.val; +} + #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 fe95a41c94b..b86dfa9c13f 100644 --- a/components/esp_hal_gpio/include/hal/rtc_io_hal.h +++ b/components/esp_hal_gpio/include/hal/rtc_io_hal.h @@ -203,23 +203,23 @@ void rtcio_hal_iomux_output(int rtcio_num, int func); #if SOC_LP_GPIO_MATRIX_SUPPORTED /** - * Select RTC GPIO input to a signal + * @brief Set pad input to a LP peripheral signal through the LP GPIO matrix * * @param rtcio_num The index of rtcio. 0 ~ SOC_RTCIO_PIN_COUNT. * @param signal_idx LP peripheral signal index. * @param inv True to invert input signal; False then no invert. */ -#define rtcio_hal_matrix_in(rtcio_num, signal_idx, inv) rtcio_ll_matrix_in(rtcio_num, signal_idx, inv) +void rtcio_hal_matrix_in(int rtcio_num, uint32_t signal_idx, bool inv); /** - * Select signal output to a RTC GPIO + * @brief Set LP peripheral output to an RTC IO pad through the LP GPIO matrix * * @param rtcio_num The index of rtcio. 0 ~ SOC_RTCIO_PIN_COUNT. * @param signal_idx LP peripheral signal index. * @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. */ -#define rtcio_hal_matrix_out(rtcio_num, signal_idx, out_inv, oen_inv) rtcio_ll_matrix_out(rtcio_num, signal_idx, out_inv, oen_inv) +void rtcio_hal_matrix_out(int rtcio_num, uint32_t signal_idx, bool out_inv, bool oen_inv); #endif // SOC_LP_GPIO_MATRIX_SUPPORTED #endif // SOC_RTCIO_INPUT_OUTPUT_SUPPORTED diff --git a/components/esp_hal_gpio/rtc_io_hal.c b/components/esp_hal_gpio/rtc_io_hal.c index 74fe537f1b7..e37660e7a5a 100644 --- a/components/esp_hal_gpio/rtc_io_hal.c +++ b/components/esp_hal_gpio/rtc_io_hal.c @@ -100,4 +100,21 @@ void rtcio_hal_iomux_output(int rtcio_num, int func) // as long as the func sel is not RTC IO, the oe can only be controlled by the peripheral } +#if SOC_LP_GPIO_MATRIX_SUPPORTED +void rtcio_hal_matrix_in(int rtcio_num, uint32_t signal_idx, bool inv) +{ + if (rtcio_num < SOC_RTCIO_PIN_COUNT) { + rtcio_ll_input_enable(rtcio_num); + } + rtcio_ll_set_input_signal_matrix_source(rtcio_num, signal_idx, inv); +} + +void rtcio_hal_matrix_out(int rtcio_num, uint32_t signal_idx, bool out_inv, bool oen_inv) +{ + rtcio_ll_iomux_func_sel(rtcio_num, RTCIO_LL_PIN_FUNC); + rtcio_ll_set_output_signal_matrix_source(rtcio_num, signal_idx, out_inv); + rtcio_ll_set_output_enable_ctrl(rtcio_num, true, oen_inv); // output is enabled at the end to avoid undesired level change +} +#endif // SOC_LP_GPIO_MATRIX_SUPPORTED + #endif //SOC_RTCIO_INPUT_OUTPUT_SUPPORTED