mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-22 17:10:28 +00:00
fix(uart): allow same pin for tx and rx in uart_set_pin
Closes https://github.com/espressif/esp-idf/issues/14787
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -19,10 +19,10 @@
|
||||
#include "freertos/idf_additions.h"
|
||||
#include "esp_private/critical_section.h"
|
||||
#include "hal/uart_hal.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "soc/uart_periph.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "driver/uart_select.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#include "esp_private/uart_share_hw_ctrl.h"
|
||||
@@ -736,8 +736,12 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
|
||||
}
|
||||
#endif
|
||||
|
||||
// Since an IO cannot route peripheral signals via IOMUX and GPIO matrix at the same time,
|
||||
// if tx and rx share the same IO, both signals need to be route to IOs through GPIO matrix
|
||||
bool tx_rx_same_io = (tx_io_num == rx_io_num);
|
||||
|
||||
/* In the following statements, if the io_num is negative, no need to configure anything. */
|
||||
if (tx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) {
|
||||
if (tx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX))) {
|
||||
if (uart_num < SOC_UART_HP_NUM) {
|
||||
gpio_func_sel(tx_io_num, PIN_FUNC_GPIO);
|
||||
esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
|
||||
@@ -746,8 +750,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
|
||||
}
|
||||
#if SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||
else {
|
||||
rtc_gpio_init(tx_io_num);
|
||||
rtc_gpio_iomux_func_sel(tx_io_num, RTCIO_LL_PIN_FUNC);
|
||||
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_TX_PIN_IDX), 0, 0);
|
||||
// output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
|
||||
@@ -755,18 +758,19 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
|
||||
#endif
|
||||
}
|
||||
|
||||
if (rx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) {
|
||||
if (rx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX))) {
|
||||
if (uart_num < SOC_UART_HP_NUM) {
|
||||
gpio_func_sel(rx_io_num, PIN_FUNC_GPIO);
|
||||
gpio_set_pull_mode(rx_io_num, GPIO_PULLUP_ONLY); // This does not consider that RX signal can be read inverted by configuring the hardware (i.e. idle is at low level). However, it is only a weak pullup, the TX at the other end can always drive the line.
|
||||
gpio_set_direction(rx_io_num, GPIO_MODE_INPUT);
|
||||
gpio_ll_input_enable(&GPIO, rx_io_num);
|
||||
esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
|
||||
}
|
||||
#if SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||
else {
|
||||
rtc_gpio_set_direction(rx_io_num, RTC_GPIO_MODE_INPUT_ONLY);
|
||||
rtc_gpio_init(rx_io_num);
|
||||
rtc_gpio_iomux_func_sel(rx_io_num, RTCIO_LL_PIN_FUNC);
|
||||
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_RX_PIN_IDX), 0);
|
||||
}
|
||||
@@ -781,8 +785,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
|
||||
}
|
||||
#if SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||
else {
|
||||
rtc_gpio_init(rts_io_num);
|
||||
rtc_gpio_iomux_func_sel(rts_io_num, RTCIO_LL_PIN_FUNC);
|
||||
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_RTS_PIN_IDX), 0, 0);
|
||||
// output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
|
||||
}
|
||||
@@ -799,8 +802,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
|
||||
#if SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||
else {
|
||||
rtc_gpio_set_direction(cts_io_num, RTC_GPIO_MODE_INPUT_ONLY);
|
||||
rtc_gpio_init(cts_io_num);
|
||||
rtc_gpio_iomux_func_sel(cts_io_num, RTCIO_LL_PIN_FUNC);
|
||||
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_CTS_PIN_IDX), 0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user