Skip to content

Commit 50e9772

Browse files
authored
Fixes UART pin setting + adds CTS/RTS HW Flow Control (#6272)
* fixes setPins and begin to keep rx/tx unmodified * adds Hardware Flow Control mode and CTS/RTS pin setting * adds Hardware Flow Control mode and CTS/RTS pin setting * adds Hardware Flow Control mode and CTS/RTS pin setting * adds Hardware Flow Control mode and CTS/RTS pin setting * Code Review
1 parent 01303b7 commit 50e9772

File tree

4 files changed

+75
-30
lines changed

4 files changed

+75
-30
lines changed

Diff for: cores/esp32/HardwareSerial.cpp

+37-19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "pins_arduino.h"
77
#include "HardwareSerial.h"
88
#include "soc/soc_caps.h"
9+
#include "driver/uart.h"
910

1011
#ifndef SOC_RX0
1112
#if CONFIG_IDF_TARGET_ESP32
@@ -114,7 +115,6 @@ void serialEventRun(void)
114115
}
115116
#endif
116117

117-
118118
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL), _rxBufferSize(256) {}
119119

120120
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)
@@ -123,28 +123,39 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
123123
log_e("Serial number is invalid, please use numers from 0 to %u", SOC_UART_NUM - 1);
124124
return;
125125
}
126+
127+
// First Time or after end() --> set default Pins
128+
if (!uartIsDriverInstalled(_uart)) {
129+
switch (_uart_nr) {
130+
case UART_NUM_0:
131+
rxPin = rxPin < 0 ? SOC_RX0 : rxPin;
132+
txPin = txPin < 0 ? SOC_TX0 : txPin;
133+
break;
134+
#if SOC_UART_NUM > 1 // may save some flash bytes...
135+
case UART_NUM_1:
136+
rxPin = rxPin < 0 ? RX1 : rxPin;
137+
txPin = txPin < 0 ? TX1 : txPin;
138+
break;
139+
#endif
140+
#if SOC_UART_NUM > 2 // may save some flash bytes...
141+
case UART_NUM_2:
142+
rxPin = rxPin < 0 ? RX2 : rxPin;
143+
txPin = txPin < 0 ? TX2 : txPin;
144+
break;
145+
#endif
146+
default:
147+
log_e("Bad UART Number");
148+
return;
149+
}
150+
}
151+
126152
if(_uart) {
127153
// in this case it is a begin() over a previous begin() - maybe to change baud rate
128154
// thus do not disable debug output
129155
end(false);
130156
}
131-
if(_uart_nr == 0 && rxPin < 0 && txPin < 0) {
132-
rxPin = SOC_RX0;
133-
txPin = SOC_TX0;
134-
}
135-
#if SOC_UART_NUM > 1
136-
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) {
137-
rxPin = RX1;
138-
txPin = TX1;
139-
}
140-
#endif
141-
#if SOC_UART_NUM > 2
142-
if(_uart_nr == 2 && rxPin < 0 && txPin < 0) {
143-
rxPin = RX2;
144-
txPin = TX2;
145-
}
146-
#endif
147157

158+
// IDF UART driver keeps Pin setting on restarting. Negative Pin number will keep it unmodified.
148159
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, _rxBufferSize, invert, rxfifo_full_thrhd);
149160
if (!baud) {
150161
// using baud rate as zero, forces it to try to detect the current baud rate in place
@@ -280,9 +291,16 @@ void HardwareSerial::setRxInvert(bool invert)
280291
uartSetRxInvert(_uart, invert);
281292
}
282293

283-
void HardwareSerial::setPins(uint8_t rxPin, uint8_t txPin)
294+
// negative Pin value will keep it unmodified
295+
void HardwareSerial::setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
296+
{
297+
uartSetPins(_uart, rxPin, txPin, ctsPin, rtsPin);
298+
}
299+
300+
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
301+
void HardwareSerial::setHwFlowCtrlMode(uint8_t mode, uint8_t threshold)
284302
{
285-
uartSetPins(_uart, rxPin, txPin);
303+
uartSetHwFlowCtrlMode(_uart, mode, threshold);
286304
}
287305

288306
size_t HardwareSerial::setRxBufferSize(size_t new_size) {

Diff for: cores/esp32/HardwareSerial.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,13 @@ class HardwareSerial: public Stream
107107
void setDebugOutput(bool);
108108

109109
void setRxInvert(bool);
110-
void setPins(uint8_t rxPin, uint8_t txPin);
110+
111+
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
112+
// SetPins shall be called after Serial begin()
113+
void setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
114+
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
115+
void setHwFlowCtrlMode(uint8_t mode = HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
116+
111117
size_t setRxBufferSize(size_t new_size);
112118

113119
protected:

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

+17-9
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,27 @@ bool uartIsDriverInstalled(uart_t* uart)
155155
return false;
156156
}
157157

158-
void uartSetPins(uart_t* uart, uint8_t rxPin, uint8_t txPin)
158+
// Valid pin UART_PIN_NO_CHANGE is defined to (-1)
159+
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
160+
void uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin)
159161
{
160-
if(uart == NULL || rxPin >= SOC_GPIO_PIN_COUNT || txPin >= SOC_GPIO_PIN_COUNT) {
162+
if(uart == NULL) {
161163
return;
162164
}
163165
UART_MUTEX_LOCK();
164-
ESP_ERROR_CHECK(uart_set_pin(uart->num, txPin, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
165-
UART_MUTEX_UNLOCK();
166-
166+
// IDF uart_set_pin() will issue necessary Error Message and take care of all GPIO Number validation.
167+
uart_set_pin(uart->num, txPin, rxPin, ctsPin, rtsPin);
168+
UART_MUTEX_UNLOCK();
169+
}
170+
171+
//
172+
void uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold) {
173+
if(uart == NULL) {
174+
return;
175+
}
176+
// IDF will issue corresponding error message when mode or threshold are wrong and prevent crashing
177+
// IDF will check (mode > HW_FLOWCTRL_CTS_RTS || threshold >= SOC_UART_FIFO_LEN)
178+
uart_set_hw_flow_ctrl(uart->num, (uart_hw_flowcontrol_t) mode, threshold);
167179
}
168180

169181

@@ -173,10 +185,6 @@ uart_t* uartBegin(uint8_t uart_nr, uint32_t baudrate, uint32_t config, int8_t rx
173185
return NULL;
174186
}
175187

176-
if(rxPin == -1 && txPin == -1) {
177-
return NULL;
178-
}
179-
180188
uart_t* uart = &_uart_bus_array[uart_nr];
181189

182190
if (uart_is_driver_installed(uart_nr)) {

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

+14-1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ extern "C" {
4848
#define SERIAL_7O2 0x800003b
4949
#define SERIAL_8O2 0x800003f
5050

51+
// These are Hardware Flow Contol possible usage
52+
// equivalent to UDF enum uart_hw_flowcontrol_t from
53+
// https://github.com/espressif/esp-idf/blob/master/components/hal/include/hal/uart_types.h#L75-L81
54+
#define HW_FLOWCTRL_DISABLE 0x0 // disable HW Flow Control
55+
#define HW_FLOWCTRL_RTS 0x1 // use only RTS PIN for HW Flow Control
56+
#define HW_FLOWCTRL_CTS 0x2 // use only CTS PIN for HW Flow Control
57+
#define HW_FLOWCTRL_CTS_RTS 0x3 // use both CTS and RTS PIN for HW Flow Control
58+
5159
struct uart_struct_t;
5260
typedef struct uart_struct_t uart_t;
5361

@@ -76,7 +84,12 @@ void uartSetDebug(uart_t* uart);
7684
int uartGetDebug();
7785

7886
bool uartIsDriverInstalled(uart_t* uart);
79-
void uartSetPins(uart_t* uart, uint8_t rxPin, uint8_t txPin);
87+
88+
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
89+
void uartSetPins(uart_t* uart, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin);
90+
91+
// Enables or disables HW Flow Control function -- needs also to set CTS and/or RTS pins
92+
void uartSetHwFlowCtrlMode(uart_t *uart, uint8_t mode, uint8_t threshold);
8093

8194
void uartStartDetectBaudrate(uart_t *uart);
8295
unsigned long uartDetectBaudrate(uart_t *uart);

0 commit comments

Comments
 (0)