Skip to content

Commit b1d072d

Browse files
authored
Implements UART SerialHardware Refactoring on top of IDF (#5549)
## Summary This PR is a complete reffactoring of UART Serial Hardware and respective HAL in order to use IDF instead of current Register manipulation approach. It implements Arduino SerialEvent functionality. Fix #5287 Fix #5273 Fix #5519 Fix #5247 Fix #5403 Fix #5429 Fix #5047 Fix #5463 Fix #5362 Fix #5112 Fix #5443 ## Impact It solves many reported issues related to UART. It was tested and works fine for ESP32, ESP-S2 and ESP32-C3.
1 parent 929cf2c commit b1d072d

File tree

4 files changed

+321
-471
lines changed

4 files changed

+321
-471
lines changed

Diff for: cores/esp32/HardwareSerial.cpp

+90-41
Original file line numberDiff line numberDiff line change
@@ -5,104 +5,152 @@
55

66
#include "pins_arduino.h"
77
#include "HardwareSerial.h"
8+
#include "soc/soc_caps.h"
89

10+
#ifndef SOC_RX0
911
#if CONFIG_IDF_TARGET_ESP32
12+
#define SOC_RX0 3
13+
#elif CONFIG_IDF_TARGET_ESP32S2
14+
#define SOC_RX0 44
15+
#elif CONFIG_IDF_TARGET_ESP32C3
16+
#define SOC_RX0 20
17+
#endif
18+
#endif
19+
20+
#ifndef SOC_TX0
21+
#if CONFIG_IDF_TARGET_ESP32
22+
#define SOC_TX0 1
23+
#elif CONFIG_IDF_TARGET_ESP32S2
24+
#define SOC_TX0 43
25+
#elif CONFIG_IDF_TARGET_ESP32C3
26+
#define SOC_TX0 21
27+
#endif
28+
#endif
29+
30+
void serialEvent(void) __attribute__((weak));
31+
void serialEvent(void) {}
32+
33+
#if SOC_UART_NUM > 1
1034

1135
#ifndef RX1
36+
#if CONFIG_IDF_TARGET_ESP32
1237
#define RX1 9
38+
#elif CONFIG_IDF_TARGET_ESP32S2
39+
#define RX1 18
40+
#elif CONFIG_IDF_TARGET_ESP32C3
41+
#define RX1 18
42+
#endif
1343
#endif
1444

1545
#ifndef TX1
46+
#if CONFIG_IDF_TARGET_ESP32
1647
#define TX1 10
48+
#elif CONFIG_IDF_TARGET_ESP32S2
49+
#define TX1 17
50+
#elif CONFIG_IDF_TARGET_ESP32C3
51+
#define TX1 19
1752
#endif
53+
#endif
54+
55+
void serialEvent1(void) __attribute__((weak));
56+
void serialEvent1(void) {}
57+
#endif /* SOC_UART_NUM > 1 */
1858

59+
#if SOC_UART_NUM > 2
1960
#ifndef RX2
61+
#if CONFIG_IDF_TARGET_ESP32
2062
#define RX2 16
2163
#endif
64+
#endif
2265

2366
#ifndef TX2
67+
#if CONFIG_IDF_TARGET_ESP32
2468
#define TX2 17
2569
#endif
26-
27-
#else
28-
29-
#ifndef RX1
30-
#define RX1 18
31-
#endif
32-
33-
#ifndef TX1
34-
#define TX1 17
3570
#endif
3671

37-
#endif
72+
void serialEvent2(void) __attribute__((weak));
73+
void serialEvent2(void) {}
74+
#endif /* SOC_UART_NUM > 2 */
3875

3976
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
4077
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
4178
HardwareSerial Serial0(0);
4279
#else
4380
HardwareSerial Serial(0);
4481
#endif
82+
#if SOC_UART_NUM > 1
4583
HardwareSerial Serial1(1);
46-
#if CONFIG_IDF_TARGET_ESP32
84+
#endif
85+
#if SOC_UART_NUM > 2
4786
HardwareSerial Serial2(2);
4887
#endif
4988
#endif
5089

90+
void serialEventRun(void)
91+
{
92+
#if ARDUINO_USB_CDC_ON_BOOT //Serial used for USB CDC
93+
if(Serial0.available()) serialEvent();
94+
#else
95+
if(Serial.available()) serialEvent();
96+
#endif
97+
#if SOC_UART_NUM > 1
98+
if(Serial1.available()) serialEvent1();
99+
#endif
100+
#if SOC_UART_NUM > 2
101+
if(Serial2.available()) serialEvent2();
102+
#endif
103+
}
104+
105+
51106
HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {}
52107

53108
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)
54109
{
55-
if(0 > _uart_nr || _uart_nr > 2) {
56-
log_e("Serial number is invalid, please use 0, 1 or 2");
110+
if(0 > _uart_nr || _uart_nr >= SOC_UART_NUM) {
111+
log_e("Serial number is invalid, please use numers from 0 to %u", SOC_UART_NUM - 1);
57112
return;
58113
}
59114
if(_uart) {
60-
end();
115+
// in this case it is a begin() over a previous begin() - maybe to change baud rate
116+
// thus do not disable debug output
117+
end(false);
61118
}
62119
if(_uart_nr == 0 && rxPin < 0 && txPin < 0) {
63-
#if CONFIG_IDF_TARGET_ESP32
64-
rxPin = 3;
65-
txPin = 1;
66-
#elif CONFIG_IDF_TARGET_ESP32S2
67-
rxPin = 44;
68-
txPin = 43;
69-
#elif CONFIG_IDF_TARGET_ESP32C3
70-
rxPin = 20;
71-
txPin = 21;
72-
#endif
120+
rxPin = SOC_RX0;
121+
txPin = SOC_TX0;
73122
}
123+
#if SOC_UART_NUM > 1
74124
if(_uart_nr == 1 && rxPin < 0 && txPin < 0) {
75125
rxPin = RX1;
76126
txPin = TX1;
77127
}
78-
#if CONFIG_IDF_TARGET_ESP32
128+
#endif
129+
#if SOC_UART_NUM > 2
79130
if(_uart_nr == 2 && rxPin < 0 && txPin < 0) {
80131
rxPin = RX2;
81132
txPin = TX2;
82133
}
83134
#endif
84-
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert, rxfifo_full_thrhd);
85-
_tx_pin = txPin;
86-
_rx_pin = rxPin;
87135

88-
if(!baud) {
136+
_uart = uartBegin(_uart_nr, baud ? baud : 9600, config, rxPin, txPin, 256, invert, rxfifo_full_thrhd);
137+
if (!baud) {
138+
// using baud rate as zero, forces it to try to detect the current baud rate in place
89139
uartStartDetectBaudrate(_uart);
90140
time_t startMillis = millis();
91141
unsigned long detectedBaudRate = 0;
92142
while(millis() - startMillis < timeout_ms && !(detectedBaudRate = uartDetectBaudrate(_uart))) {
93143
yield();
94144
}
95145

96-
end();
146+
end(false);
97147

98148
if(detectedBaudRate) {
99149
delay(100); // Give some time...
100150
_uart = uartBegin(_uart_nr, detectedBaudRate, config, rxPin, txPin, 256, invert, rxfifo_full_thrhd);
101151
} else {
102152
log_e("Could not detect baudrate. Serial data at the port must be present within the timeout for detection to be possible");
103153
_uart = NULL;
104-
_tx_pin = 255;
105-
_rx_pin = 255;
106154
}
107155
}
108156
}
@@ -112,21 +160,16 @@ void HardwareSerial::updateBaudRate(unsigned long baud)
112160
uartSetBaudRate(_uart, baud);
113161
}
114162

115-
void HardwareSerial::end()
163+
void HardwareSerial::end(bool turnOffDebug)
116164
{
117-
if(uartGetDebug() == _uart_nr) {
165+
if(turnOffDebug && uartGetDebug() == _uart_nr) {
118166
uartSetDebug(0);
119167
}
120168
delay(10);
121-
log_v("pins %d %d",_tx_pin, _rx_pin);
122-
uartEnd(_uart, _tx_pin, _rx_pin);
169+
uartEnd(_uart);
123170
_uart = 0;
124171
}
125172

126-
size_t HardwareSerial::setRxBufferSize(size_t new_size) {
127-
return uartResizeRxBuffer(_uart, new_size);
128-
}
129-
130173
void HardwareSerial::setDebugOutput(bool en)
131174
{
132175
if(_uart == 0) {
@@ -212,10 +255,16 @@ uint32_t HardwareSerial::baudRate()
212255
}
213256
HardwareSerial::operator bool() const
214257
{
215-
return true;
258+
return uartIsDriverInstalled(_uart);
216259
}
217260

218261
void HardwareSerial::setRxInvert(bool invert)
219262
{
220263
uartSetRxInvert(_uart, invert);
221264
}
265+
266+
void HardwareSerial::setPins(uint8_t rxPin, uint8_t txPin)
267+
{
268+
uartSetPins(_uart, rxPin, txPin);
269+
}
270+

Diff for: cores/esp32/HardwareSerial.h

+6-5
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,15 @@
4949

5050
#include "Stream.h"
5151
#include "esp32-hal.h"
52+
#include "soc/soc_caps.h"
5253

5354
class HardwareSerial: public Stream
5455
{
5556
public:
5657
HardwareSerial(int uart_nr);
5758

5859
void begin(unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1, bool invert=false, unsigned long timeout_ms = 20000UL, uint8_t rxfifo_full_thrhd = 112);
59-
void end();
60+
void end(bool turnOffDebug = true);
6061
void updateBaudRate(unsigned long baud);
6162
int available(void);
6263
int availableForWrite(void);
@@ -98,16 +99,14 @@ class HardwareSerial: public Stream
9899
uint32_t baudRate();
99100
operator bool() const;
100101

101-
size_t setRxBufferSize(size_t);
102102
void setDebugOutput(bool);
103103

104104
void setRxInvert(bool);
105+
void setPins(uint8_t rxPin, uint8_t txPin);
105106

106107
protected:
107108
int _uart_nr;
108109
uart_t* _uart;
109-
uint8_t _tx_pin;
110-
uint8_t _rx_pin;
111110
};
112111

113112
extern void serialEventRun(void) __attribute__((weak));
@@ -123,8 +122,10 @@ extern HardwareSerial Serial0;
123122
#else
124123
extern HardwareSerial Serial;
125124
#endif
125+
#if SOC_UART_NUM > 1
126126
extern HardwareSerial Serial1;
127-
#if CONFIG_IDF_TARGET_ESP32
127+
#endif
128+
#if SOC_UART_NUM > 2
128129
extern HardwareSerial Serial2;
129130
#endif
130131
#endif

0 commit comments

Comments
 (0)