feat(uart): fixes pin attach for any IDF 5.x (#11499)
* feat(uart): fixes pin attach for any IDF 5.x * fix(uart): commentary typo error Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix(uart): commentary typo error Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix(uart): commentary typo error Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix(uart): commentary style fix * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
This commit is contained in:
parent
01e4d5debb
commit
9d84c78cf2
1 changed files with 126 additions and 5 deletions
|
|
@ -295,6 +295,125 @@ static bool _uartDetachBus_RTS(void *busptr) {
|
||||||
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, bus->_rtsPin);
|
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, bus->_rtsPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _uartTrySetIomuxPin(uart_port_t uart_num, int io_num, uint32_t idx) {
|
||||||
|
// Store a pointer to the default pin, to optimize access to its fields.
|
||||||
|
const uart_periph_sig_t *upin = &uart_periph_signal[uart_num].pins[idx];
|
||||||
|
|
||||||
|
// In theory, if default_gpio is -1, iomux_func should also be -1, but let's be safe and test both.
|
||||||
|
if (upin->iomux_func == -1 || upin->default_gpio == -1 || upin->default_gpio != io_num) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign the correct function to the GPIO.
|
||||||
|
assert(upin->iomux_func != -1);
|
||||||
|
if (uart_num < SOC_UART_HP_NUM) {
|
||||||
|
gpio_iomux_out(io_num, upin->iomux_func, false);
|
||||||
|
// If the pin is input, we also have to redirect the signal, in order to bypass the GPIO matrix.
|
||||||
|
if (upin->input) {
|
||||||
|
gpio_iomux_in(io_num, upin->signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t _uartInternalSetPin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) {
|
||||||
|
// 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 routed 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) {
|
||||||
|
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
|
||||||
|
// In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason
|
||||||
|
// But TX IO in isolate state could write garbled data to the other end
|
||||||
|
// Therefore, we should disable the switch of the TX pin to sleep configuration
|
||||||
|
gpio_sleep_sel_dis(tx_io_num);
|
||||||
|
#endif
|
||||||
|
if (tx_rx_same_io || !_uartTrySetIomuxPin(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);
|
||||||
|
// output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected
|
||||||
|
// (output enabled too early may cause unnecessary level change at the pad)
|
||||||
|
}
|
||||||
|
#if SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||||
|
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_TX_PIN_IDX), 0, 0);
|
||||||
|
// output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rx_io_num >= 0) {
|
||||||
|
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
|
||||||
|
// In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason
|
||||||
|
// But RX IO in isolate state could receive garbled data into FIFO, which is not desired
|
||||||
|
// Therefore, we should disable the switch of the RX pin to sleep configuration
|
||||||
|
gpio_sleep_sel_dis(rx_io_num);
|
||||||
|
#endif
|
||||||
|
if (tx_rx_same_io || !_uartTrySetIomuxPin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) {
|
||||||
|
if (uart_num < SOC_UART_HP_NUM) {
|
||||||
|
gpio_input_enable(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_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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rts_io_num >= 0 && !_uartTrySetIomuxPin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) {
|
||||||
|
if (uart_num < SOC_UART_HP_NUM) {
|
||||||
|
gpio_func_sel(rts_io_num, PIN_FUNC_GPIO);
|
||||||
|
esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
|
||||||
|
// output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected
|
||||||
|
}
|
||||||
|
#if SOC_LP_GPIO_MATRIX_SUPPORTED
|
||||||
|
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_RTS_PIN_IDX), 0, 0);
|
||||||
|
// output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cts_io_num >= 0 && !_uartTrySetIomuxPin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) {
|
||||||
|
if (uart_num < SOC_UART_HP_NUM) {
|
||||||
|
gpio_pullup_en(cts_io_num);
|
||||||
|
gpio_input_enable(cts_io_num);
|
||||||
|
esp_rom_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0);
|
||||||
|
}
|
||||||
|
#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); // 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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
// Attach function for UART
|
// Attach function for UART
|
||||||
// connects the IO Pad, set Paripheral Manager and internal UART structure data
|
// connects the IO Pad, set Paripheral Manager and internal UART structure data
|
||||||
static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) {
|
static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) {
|
||||||
|
|
@ -307,7 +426,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
|
||||||
//log_v("attaching UART%d pins: prev,new RX(%d,%d) TX(%d,%d) CTS(%d,%d) RTS(%d,%d)", uart_num,
|
//log_v("attaching UART%d pins: prev,new RX(%d,%d) TX(%d,%d) CTS(%d,%d) RTS(%d,%d)", uart_num,
|
||||||
// uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10);
|
// uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10);
|
||||||
|
|
||||||
// IDF uart_set_pin() checks if the pin is used within LP UART and if it is a valid RTC IO pin
|
// IDF _uartInternalSetPin() checks if the pin is used within LP UART and if it is a valid RTC IO pin
|
||||||
// No need for Arduino Layer to check it again
|
// No need for Arduino Layer to check it again
|
||||||
bool retCode = true;
|
bool retCode = true;
|
||||||
if (rxPin >= 0) {
|
if (rxPin >= 0) {
|
||||||
|
|
@ -316,7 +435,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
|
||||||
perimanClearPinBus(rxPin);
|
perimanClearPinBus(rxPin);
|
||||||
}
|
}
|
||||||
// connect RX Pad
|
// connect RX Pad
|
||||||
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
bool ret = ESP_OK == _uartInternalSetPin(uart->num, UART_PIN_NO_CHANGE, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||||
#if SOC_UART_LP_NUM >= 1
|
#if SOC_UART_LP_NUM >= 1
|
||||||
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
|
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
|
||||||
ret &= lp_uart_config_io(uart->num, rxPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_RX_PIN_IDX);
|
ret &= lp_uart_config_io(uart->num, rxPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_RX_PIN_IDX);
|
||||||
|
|
@ -339,7 +458,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
|
||||||
perimanClearPinBus(txPin);
|
perimanClearPinBus(txPin);
|
||||||
}
|
}
|
||||||
// connect TX Pad
|
// connect TX Pad
|
||||||
bool ret = ESP_OK == uart_set_pin(uart->num, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
bool ret = ESP_OK == _uartInternalSetPin(uart->num, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||||
#if SOC_UART_LP_NUM >= 1
|
#if SOC_UART_LP_NUM >= 1
|
||||||
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
|
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
|
||||||
ret &= lp_uart_config_io(uart->num, txPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_TX_PIN_IDX);
|
ret &= lp_uart_config_io(uart->num, txPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_TX_PIN_IDX);
|
||||||
|
|
@ -362,7 +481,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
|
||||||
perimanClearPinBus(ctsPin);
|
perimanClearPinBus(ctsPin);
|
||||||
}
|
}
|
||||||
// connect CTS Pad
|
// connect CTS Pad
|
||||||
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, ctsPin);
|
bool ret = ESP_OK == _uartInternalSetPin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, ctsPin);
|
||||||
#if SOC_UART_LP_NUM >= 1
|
#if SOC_UART_LP_NUM >= 1
|
||||||
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
|
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
|
||||||
ret &= lp_uart_config_io(uart->num, ctsPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_CTS_PIN_IDX);
|
ret &= lp_uart_config_io(uart->num, ctsPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_CTS_PIN_IDX);
|
||||||
|
|
@ -385,7 +504,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
|
||||||
perimanClearPinBus(rtsPin);
|
perimanClearPinBus(rtsPin);
|
||||||
}
|
}
|
||||||
// connect RTS Pad
|
// connect RTS Pad
|
||||||
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin, UART_PIN_NO_CHANGE);
|
bool ret = ESP_OK == _uartInternalSetPin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin, UART_PIN_NO_CHANGE);
|
||||||
#if SOC_UART_LP_NUM >= 1
|
#if SOC_UART_LP_NUM >= 1
|
||||||
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
|
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
|
||||||
ret &= lp_uart_config_io(uart->num, rtsPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_RTS_PIN_IDX);
|
ret &= lp_uart_config_io(uart->num, rtsPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_RTS_PIN_IDX);
|
||||||
|
|
@ -1398,11 +1517,13 @@ void uart_internal_loopback(uint8_t uartNum, int8_t rxPin) {
|
||||||
log_e("UART%d is not supported for loopback or RX pin %d is invalid.", uartNum, rxPin);
|
log_e("UART%d is not supported for loopback or RX pin %d is invalid.", uartNum, rxPin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if 0 // leave this code here for future reference and need
|
||||||
// forces rxPin to use GPIO Matrix and setup the pin to receive UART TX Signal - IDF 5.4.1 Change with uart_release_pin()
|
// forces rxPin to use GPIO Matrix and setup the pin to receive UART TX Signal - IDF 5.4.1 Change with uart_release_pin()
|
||||||
gpio_func_sel((gpio_num_t)rxPin, PIN_FUNC_GPIO);
|
gpio_func_sel((gpio_num_t)rxPin, PIN_FUNC_GPIO);
|
||||||
gpio_pullup_en((gpio_num_t)rxPin);
|
gpio_pullup_en((gpio_num_t)rxPin);
|
||||||
gpio_input_enable((gpio_num_t)rxPin);
|
gpio_input_enable((gpio_num_t)rxPin);
|
||||||
esp_rom_gpio_connect_in_signal(rxPin, uart_periph_signal[uartNum].pins[SOC_UART_RX_PIN_IDX].signal, false);
|
esp_rom_gpio_connect_in_signal(rxPin, uart_periph_signal[uartNum].pins[SOC_UART_RX_PIN_IDX].signal, false);
|
||||||
|
#endif
|
||||||
esp_rom_gpio_connect_out_signal(rxPin, uart_periph_signal[uartNum].pins[SOC_UART_TX_PIN_IDX].signal, false, false);
|
esp_rom_gpio_connect_out_signal(rxPin, uart_periph_signal[uartNum].pins[SOC_UART_TX_PIN_IDX].signal, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue