From fe6abc2b05e9d4f390415d4cc346d826f200c6d4 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Wed, 26 Oct 2022 14:09:44 -0300 Subject: [PATCH] fixes UART pin detach on end() --- cores/esp32/HardwareSerial.cpp | 22 ++++++++++++++--- cores/esp32/HardwareSerial.h | 1 + cores/esp32/esp32-hal-uart.c | 44 +++++++++++++++++++++++++++++++--- cores/esp32/esp32-hal-uart.h | 5 ++-- 4 files changed, 64 insertions(+), 8 deletions(-) diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 0fc16f4cf76..049c24a74d5 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -145,6 +145,10 @@ _eventTask(NULL) #if !CONFIG_DISABLE_HAL_LOCKS ,_lock(NULL) #endif +,_rxPin(-1) +,_txPin(-1) +,_ctsPin(-1) +,_rtsPin(-1) { #if !CONFIG_DISABLE_HAL_LOCKS if(_lock == NULL){ @@ -384,7 +388,8 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in // Set UART RX timeout uartSetRxTimeout(_uart, _rxTimeout); - + _rxPin = rxPin; + _txPin = txPin; HSERIAL_MUTEX_UNLOCK(); } @@ -403,6 +408,8 @@ void HardwareSerial::end(bool fullyTerminate) if (uartGetDebug() == _uart_nr) { uartSetDebug(0); } + uartDetachPins(_uart, _rxPin, _txPin, _ctsPin, _rtsPin); + _rxPin = _txPin = _ctsPin = _rtsPin = -1; } delay(10); uartEnd(_uart); @@ -507,10 +514,19 @@ void HardwareSerial::setRxInvert(bool invert) void HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) { if(_uart == NULL) { - log_e("setPins() shall be called after begin() - nothing done"); + log_e("setPins() shall be called after begin() - nothing done\n"); return; } - uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin); + + // uartSetPins() checks if pins are valid for each function and for the SoC + if (uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin)) { + _txPin = _txPin >= 0 ? txPin : _txPin; + _rxPin = _rxPin >= 0 ? rxPin : _rxPin; + _rtsPin = _rtsPin >= 0 ? rtsPin : _rtsPin; + _ctsPin = _ctsPin >= 0 ? ctsPin : _ctsPin; + } else { + log_e("Error when setting Serial port Pins. Invalid Pin.\n"); + } } // Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before) diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index c6f36f792d9..0c673c1483f 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -176,6 +176,7 @@ class HardwareSerial: public Stream #if !CONFIG_DISABLE_HAL_LOCKS SemaphoreHandle_t _lock; #endif + int8_t _rxPin, _txPin, _ctsPin, _rtsPin; void _createEventTask(void *args); void _destroyEventTask(void); diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 0f229747315..e4b24a112f5 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -23,6 +23,9 @@ #include "soc/soc_caps.h" #include "soc/uart_struct.h" +#include "hal/gpio_hal.h" +#include "esp_rom_gpio.h" + static int s_uart_debug_nr = 0; struct uart_struct_t { @@ -69,6 +72,40 @@ static uart_t _uart_bus_array[] = { #endif +// IDF UART has no detach function. As consequence, after ending a UART, the previous pins continue +// to work as RX/TX. It can be verified by changing the UART pins and writing to the UART. Output can +// be seen in the previous pins and new pins as well. +// Valid pin UART_PIN_NO_CHANGE is defined to (-1) +// Negative Pin Number will keep it unmodified, thus this function can detach individual pins +void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) +{ + if(uart == NULL) { + return; + } + + UART_MUTEX_LOCK(); + if (txPin >= 0) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[txPin], PIN_FUNC_GPIO); + esp_rom_gpio_connect_out_signal(txPin, SIG_GPIO_OUT_IDX, false, false); + } + + if (rxPin >= 0) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rxPin], PIN_FUNC_GPIO); + esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_RX_PIN_IDX), false); + } + + if (rtsPin >= 0) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rtsPin], PIN_FUNC_GPIO); + esp_rom_gpio_connect_out_signal(rtsPin, SIG_GPIO_OUT_IDX, false, false); + } + + if (ctsPin >= 0) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctsPin], PIN_FUNC_GPIO); + esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_CTS_PIN_IDX), false); + } + UART_MUTEX_UNLOCK(); +} + // solves issue https://github.com/espressif/arduino-esp32/issues/6032 // baudrate must be multiplied when CPU Frequency is lower than APB 80MHz uint32_t _get_effective_baudrate(uint32_t baudrate) @@ -108,15 +145,16 @@ bool uartIsDriverInstalled(uart_t* uart) // Valid pin UART_PIN_NO_CHANGE is defined to (-1) // Negative Pin Number will keep it unmodified, thus this function can set individual pins -void uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) +bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) { if(uart == NULL) { - return; + return false; } UART_MUTEX_LOCK(); // IDF uart_set_pin() will issue necessary Error Message and take care of all GPIO Number validation. - uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin); + bool retCode = uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin) == ESP_OK; UART_MUTEX_UNLOCK(); + return retCode; } // diff --git a/cores/esp32/esp32-hal-uart.h b/cores/esp32/esp32-hal-uart.h index 86d56eb728d..ffb0a3f027a 100644 --- a/cores/esp32/esp32-hal-uart.h +++ b/cores/esp32/esp32-hal-uart.h @@ -91,8 +91,9 @@ int uartGetDebug(); bool uartIsDriverInstalled(uart_t* uart); -// Negative Pin Number will keep it unmodified, thus this function can set individual pins -void uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin); +// Negative Pin Number will keep it unmodified, thus this function can set/reset individual pins +bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin); +void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin); // Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins void uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);