diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 4655cf27a6f..d4ae08ff0e7 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -133,7 +133,7 @@ void serialEventRun(void) #define HSERIAL_MUTEX_UNLOCK() #endif -HardwareSerial::HardwareSerial(int uart_nr) : +HardwareSerial::HardwareSerial(uint8_t uart_nr) : _uart_nr(uart_nr), _uart(NULL), _rxBufferSize(256), @@ -147,8 +147,6 @@ _eventTask(NULL) #if !CONFIG_DISABLE_HAL_LOCKS ,_lock(NULL) #endif -,_rxPin(-1) -,_txPin(-1) ,_ctsPin(-1) ,_rtsPin(-1) { @@ -161,6 +159,14 @@ _eventTask(NULL) } } #endif + // sets UART0 (default console) RX/TX pins as already configured in boot + if (uart_nr == 0) { + _rxPin = SOC_RX0; + _txPin = SOC_TX0; + } else { + _rxPin = -1; + _txPin = -1; + } } HardwareSerial::~HardwareSerial() @@ -330,7 +336,7 @@ void HardwareSerial::_uartEventTask(void *args) void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms, uint8_t rxfifo_full_thrhd) { - if(0 > _uart_nr || _uart_nr >= SOC_UART_NUM) { + if(_uart_nr >= SOC_UART_NUM) { log_e("Serial number is invalid, please use numers from 0 to %u", SOC_UART_NUM - 1); return; } @@ -348,23 +354,26 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in switch (_uart_nr) { case UART_NUM_0: if (rxPin < 0 && txPin < 0) { - rxPin = SOC_RX0; - txPin = SOC_TX0; + // do not change RX0/TX0 if it has already been set before + rxPin = _rxPin < 0 ? SOC_RX0 : _rxPin; + txPin = _txPin < 0 ? SOC_TX0 : _txPin; } break; #if SOC_UART_NUM > 1 // may save some flash bytes... case UART_NUM_1: if (rxPin < 0 && txPin < 0) { - rxPin = RX1; - txPin = TX1; + // do not change RX1/TX1 if it has already been set before + rxPin = _rxPin < 0 ? RX1 : _rxPin; + txPin = _txPin < 0 ? TX1 : _txPin; } break; #endif #if SOC_UART_NUM > 2 // may save some flash bytes... case UART_NUM_2: if (rxPin < 0 && txPin < 0) { - rxPin = RX2; - txPin = TX2; + // do not change RX2/TX2 if it has already been set before + rxPin = _rxPin < 0 ? RX2 : _rxPin; + txPin = _txPin < 0 ? TX2 : _txPin; } break; #endif @@ -424,9 +433,17 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in uartSetRxFIFOFull(_uart, fifoFull); _rxFIFOFull = fifoFull; } - - _rxPin = rxPin; - _txPin = txPin; + // detach previous attached RX/TX pins when it has changed + if (_uart != NULL) { + if (rxPin >= 0 && rxPin != _rxPin) { + uartDetachPins(_uart_nr, _rxPin, -1, -1, -1); + _rxPin = rxPin; + } + if (txPin >= 0 && txPin != _txPin) { + uartDetachPins(_uart_nr, -1, _txPin, -1, -1); + _txPin = txPin; + } + } HSERIAL_MUTEX_UNLOCK(); } @@ -449,7 +466,7 @@ void HardwareSerial::end(bool fullyTerminate) _rxFIFOFull = 0; - uartDetachPins(_uart, _rxPin, _txPin, _ctsPin, _rtsPin); + uartDetachPins(_uart_nr, _rxPin, _txPin, _ctsPin, _rtsPin); _rxPin = _txPin = _ctsPin = _rtsPin = -1; } @@ -554,11 +571,6 @@ void HardwareSerial::setRxInvert(bool invert) // negative Pin value will keep it unmodified bool 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\n"); - return false; - } - // map logical pins to GPIO numbers rxPin = digitalPinToGPIONumber(rxPin); txPin = digitalPinToGPIONumber(txPin); @@ -566,12 +578,18 @@ bool HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t r rtsPin = digitalPinToGPIONumber(rtsPin); // uartSetPins() checks if pins are valid for each function and for the SoC - bool retCode = uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin); + bool retCode = uartSetPins(_uart_nr, rxPin, txPin, ctsPin, rtsPin); if (retCode) { - _txPin = _txPin >= 0 ? txPin : _txPin; - _rxPin = _rxPin >= 0 ? rxPin : _rxPin; - _rtsPin = _rtsPin >= 0 ? rtsPin : _rtsPin; - _ctsPin = _ctsPin >= 0 ? ctsPin : _ctsPin; + // detach previous attached UART pins if not set as same as before + if (_rxPin >= 0 && rxPin >= 0 &&_rxPin != rxPin) uartDetachPins(_uart_nr, _rxPin, -1, -1, -1); + if (_txPin >= 0 && txPin >= 0 && _txPin != txPin) uartDetachPins(_uart_nr, -1, _txPin, -1, -1); + if (_ctsPin >= 0 && ctsPin >= 0 && _ctsPin != ctsPin) uartDetachPins(_uart_nr, -1, -1, _ctsPin, -1); + if (_rtsPin >= 0 && rtsPin >= 0 &&_rtsPin != rtsPin) uartDetachPins(_uart_nr, -1, -1, -1, _rtsPin); + // set new pins for a future end() or a setPins() + _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"); } diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index d6516f06f3e..37d1fedd9bc 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -71,7 +71,7 @@ typedef std::function OnReceiveErrorCb; class HardwareSerial: public Stream { public: - HardwareSerial(int uart_nr); + HardwareSerial(uint8_t uart_nr); ~HardwareSerial(); // setRxTimeout sets the timeout after which onReceive callback will be called (after receiving data, it waits for this time of UART rx inactivity to call the callback fnc) @@ -170,7 +170,7 @@ class HardwareSerial: public Stream size_t setTxBufferSize(size_t new_size); protected: - int _uart_nr; + uint8_t _uart_nr; uart_t* _uart; size_t _rxBufferSize; size_t _txBufferSize; diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index ca212577891..c649c58ea94 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -79,13 +79,13 @@ static uart_t _uart_bus_array[] = { // 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) +void uartDetachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) { - if(uart == NULL) { + if(uart_num >= SOC_UART_NUM) { + log_e("Serial number is invalid, please use numers from 0 to %u", SOC_UART_NUM - 1); 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); @@ -93,7 +93,7 @@ void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int 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); + esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false); } if (rtsPin >= 0) { @@ -103,9 +103,8 @@ void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int 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); + 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 @@ -147,15 +146,15 @@ 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 -bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) +bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) { - if(uart == NULL) { - return false; + if(uart_num >= SOC_UART_NUM) { + log_e("Serial number is invalid, please use numers from 0 to %u", SOC_UART_NUM - 1); + return; } - UART_MUTEX_LOCK(); + // IDF uart_set_pin() will issue necessary Error Message and take care of all GPIO Number validation. - bool retCode = uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin) == ESP_OK; - UART_MUTEX_UNLOCK(); + bool retCode = uart_set_pin(uart_num, txPin, rxPin, rtsPin, ctsPin) == ESP_OK; return retCode; } diff --git a/cores/esp32/esp32-hal-uart.h b/cores/esp32/esp32-hal-uart.h index c9cdd114909..886142ce23b 100644 --- a/cores/esp32/esp32-hal-uart.h +++ b/cores/esp32/esp32-hal-uart.h @@ -131,8 +131,8 @@ int uartGetDebug(); bool uartIsDriverInstalled(uart_t* uart); // 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); +bool uartSetPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin); +void uartDetachPins(uint8_t uart_num, 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 bool uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);