Skip to content

Commit 2cebee4

Browse files
authored
fixes UART pin detach on end() (espressif#7402)
1 parent d3ccd2a commit 2cebee4

File tree

4 files changed

+64
-8
lines changed

4 files changed

+64
-8
lines changed

Diff for: cores/esp32/HardwareSerial.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,10 @@ _eventTask(NULL)
145145
#if !CONFIG_DISABLE_HAL_LOCKS
146146
,_lock(NULL)
147147
#endif
148+
,_rxPin(-1)
149+
,_txPin(-1)
150+
,_ctsPin(-1)
151+
,_rtsPin(-1)
148152
{
149153
#if !CONFIG_DISABLE_HAL_LOCKS
150154
if(_lock == NULL){
@@ -384,7 +388,8 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
384388

385389
// Set UART RX timeout
386390
uartSetRxTimeout(_uart, _rxTimeout);
387-
391+
_rxPin = rxPin;
392+
_txPin = txPin;
388393
HSERIAL_MUTEX_UNLOCK();
389394
}
390395

@@ -403,6 +408,8 @@ void HardwareSerial::end(bool fullyTerminate)
403408
if (uartGetDebug() == _uart_nr) {
404409
uartSetDebug(0);
405410
}
411+
uartDetachPins(_uart, _rxPin, _txPin, _ctsPin, _rtsPin);
412+
_rxPin = _txPin = _ctsPin = _rtsPin = -1;
406413
}
407414
delay(10);
408415
uartEnd(_uart);
@@ -507,10 +514,19 @@ void HardwareSerial::setRxInvert(bool invert)
507514
void HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
508515
{
509516
if(_uart == NULL) {
510-
log_e("setPins() shall be called after begin() - nothing done");
517+
log_e("setPins() shall be called after begin() - nothing done\n");
511518
return;
512519
}
513-
uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin);
520+
521+
// uartSetPins() checks if pins are valid for each function and for the SoC
522+
if (uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin)) {
523+
_txPin = _txPin >= 0 ? txPin : _txPin;
524+
_rxPin = _rxPin >= 0 ? rxPin : _rxPin;
525+
_rtsPin = _rtsPin >= 0 ? rtsPin : _rtsPin;
526+
_ctsPin = _ctsPin >= 0 ? ctsPin : _ctsPin;
527+
} else {
528+
log_e("Error when setting Serial port Pins. Invalid Pin.\n");
529+
}
514530
}
515531

516532
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)

Diff for: cores/esp32/HardwareSerial.h

+1
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ class HardwareSerial: public Stream
176176
#if !CONFIG_DISABLE_HAL_LOCKS
177177
SemaphoreHandle_t _lock;
178178
#endif
179+
int8_t _rxPin, _txPin, _ctsPin, _rtsPin;
179180

180181
void _createEventTask(void *args);
181182
void _destroyEventTask(void);

Diff for: cores/esp32/esp32-hal-uart.c

+41-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#include "soc/soc_caps.h"
2424
#include "soc/uart_struct.h"
2525

26+
#include "hal/gpio_hal.h"
27+
#include "esp_rom_gpio.h"
28+
2629
static int s_uart_debug_nr = 0;
2730

2831
struct uart_struct_t {
@@ -69,6 +72,40 @@ static uart_t _uart_bus_array[] = {
6972

7073
#endif
7174

75+
// IDF UART has no detach function. As consequence, after ending a UART, the previous pins continue
76+
// to work as RX/TX. It can be verified by changing the UART pins and writing to the UART. Output can
77+
// be seen in the previous pins and new pins as well.
78+
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
79+
// Negative Pin Number will keep it unmodified, thus this function can detach individual pins
80+
void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
81+
{
82+
if(uart == NULL) {
83+
return;
84+
}
85+
86+
UART_MUTEX_LOCK();
87+
if (txPin >= 0) {
88+
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[txPin], PIN_FUNC_GPIO);
89+
esp_rom_gpio_connect_out_signal(txPin, SIG_GPIO_OUT_IDX, false, false);
90+
}
91+
92+
if (rxPin >= 0) {
93+
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rxPin], PIN_FUNC_GPIO);
94+
esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_RX_PIN_IDX), false);
95+
}
96+
97+
if (rtsPin >= 0) {
98+
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rtsPin], PIN_FUNC_GPIO);
99+
esp_rom_gpio_connect_out_signal(rtsPin, SIG_GPIO_OUT_IDX, false, false);
100+
}
101+
102+
if (ctsPin >= 0) {
103+
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[ctsPin], PIN_FUNC_GPIO);
104+
esp_rom_gpio_connect_in_signal(GPIO_FUNC_IN_LOW, UART_PERIPH_SIGNAL(uart->num, SOC_UART_CTS_PIN_IDX), false);
105+
}
106+
UART_MUTEX_UNLOCK();
107+
}
108+
72109
// solves issue https://github.com/espressif/arduino-esp32/issues/6032
73110
// baudrate must be multiplied when CPU Frequency is lower than APB 80MHz
74111
uint32_t _get_effective_baudrate(uint32_t baudrate)
@@ -108,15 +145,16 @@ bool uartIsDriverInstalled(uart_t* uart)
108145

109146
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
110147
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
111-
void uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
148+
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
112149
{
113150
if(uart == NULL) {
114-
return;
151+
return false;
115152
}
116153
UART_MUTEX_LOCK();
117154
// IDF uart_set_pin() will issue necessary Error Message and take care of all GPIO Number validation.
118-
uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin);
155+
bool retCode = uart_set_pin(uart->num, txPin, rxPin, rtsPin, ctsPin) == ESP_OK;
119156
UART_MUTEX_UNLOCK();
157+
return retCode;
120158
}
121159

122160
//

Diff for: cores/esp32/esp32-hal-uart.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ int uartGetDebug();
9191

9292
bool uartIsDriverInstalled(uart_t* uart);
9393

94-
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
95-
void uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
94+
// Negative Pin Number will keep it unmodified, thus this function can set/reset individual pins
95+
bool uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
96+
void uartDetachPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
9697

9798
// Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins
9899
void uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);

0 commit comments

Comments
 (0)