Skip to content

Commit 646785e

Browse files
SuGliderme-no-devpre-commit-ci-lite[bot]
authored
feat(LP_UART): Implements the ESP32-C6/ESP32-P4 Low Power UART as a possible HardwareSerial port (#10967)
* feat(uart): adds low power uart peripheral into hardware serial class * feat(lp_uart): pin setting for lp uart plus esp32p4 fixes * fix(uart): keeps the test as it was before. * fix(uart): updates the copyright year reference * fix(uart): updates the copyright year reference * feat(lp_uart): supports any number of lp uart port for the future * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: Me No Dev <[email protected]> Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent 55f4f1b commit 646785e

File tree

4 files changed

+330
-87
lines changed

4 files changed

+330
-87
lines changed

cores/esp32/HardwareSerial.cpp

+84-42
Original file line numberDiff line numberDiff line change
@@ -23,40 +23,52 @@
2323
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
2424
#endif
2525

26+
#if (SOC_UART_LP_NUM >= 1)
27+
#define UART_HW_FIFO_LEN(uart_num) ((uart_num < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN)
28+
#else
29+
#define UART_HW_FIFO_LEN(uart_num) SOC_UART_FIFO_LEN
30+
#endif
31+
2632
void serialEvent(void) __attribute__((weak));
2733

28-
#if SOC_UART_HP_NUM > 1
34+
#if SOC_UART_NUM > 1
2935
void serialEvent1(void) __attribute__((weak));
30-
#endif /* SOC_UART_HP_NUM > 1 */
36+
#endif /* SOC_UART_NUM > 1 */
3137

32-
#if SOC_UART_HP_NUM > 2
38+
#if SOC_UART_NUM > 2
3339
void serialEvent2(void) __attribute__((weak));
34-
#endif /* SOC_UART_HP_NUM > 2 */
40+
#endif /* SOC_UART_NUM > 2 */
3541

36-
#if SOC_UART_HP_NUM > 3
42+
#if SOC_UART_NUM > 3
3743
void serialEvent3(void) __attribute__((weak));
38-
#endif /* SOC_UART_HP_NUM > 3 */
44+
#endif /* SOC_UART_NUM > 3 */
3945

40-
#if SOC_UART_HP_NUM > 4
46+
#if SOC_UART_NUM > 4
4147
void serialEvent4(void) __attribute__((weak));
42-
#endif /* SOC_UART_HP_NUM > 4 */
48+
#endif /* SOC_UART_NUM > 4 */
49+
50+
#if SOC_UART_NUM > 5
51+
void serialEvent5(void) __attribute__((weak));
52+
#endif /* SOC_UART_NUM > 5 */
4353

4454
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
4555
// There is always Seria0 for UART0
4656
HardwareSerial Serial0(0);
47-
#if SOC_UART_HP_NUM > 1
57+
#if SOC_UART_NUM > 1
4858
HardwareSerial Serial1(1);
4959
#endif
50-
#if SOC_UART_HP_NUM > 2
60+
#if SOC_UART_NUM > 2
5161
HardwareSerial Serial2(2);
5262
#endif
53-
#if SOC_UART_HP_NUM > 3
63+
#if SOC_UART_NUM > 3
5464
HardwareSerial Serial3(3);
5565
#endif
56-
#if SOC_UART_HP_NUM > 4
66+
#if SOC_UART_NUM > 4
5767
HardwareSerial Serial4(4);
5868
#endif
59-
69+
#if (SOC_UART_NUM > 5)
70+
HardwareSerial Serial5(5);
71+
#endif
6072
#if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event
6173
extern void HWCDCSerialEvent(void) __attribute__((weak));
6274
#endif
@@ -81,26 +93,31 @@ void serialEventRun(void) {
8193
if (serialEvent && Serial0.available()) {
8294
serialEvent();
8395
}
84-
#if SOC_UART_HP_NUM > 1
96+
#if SOC_UART_NUM > 1
8597
if (serialEvent1 && Serial1.available()) {
8698
serialEvent1();
8799
}
88100
#endif
89-
#if SOC_UART_HP_NUM > 2
101+
#if SOC_UART_NUM > 2
90102
if (serialEvent2 && Serial2.available()) {
91103
serialEvent2();
92104
}
93105
#endif
94-
#if SOC_UART_HP_NUM > 3
106+
#if SOC_UART_NUM > 3
95107
if (serialEvent3 && Serial3.available()) {
96108
serialEvent3();
97109
}
98110
#endif
99-
#if SOC_UART_HP_NUM > 4
111+
#if SOC_UART_NUM > 4
100112
if (serialEvent4 && Serial4.available()) {
101113
serialEvent4();
102114
}
103115
#endif
116+
#if SOC_UART_NUM > 5
117+
if (serialEvent5 && Serial5.available()) {
118+
serialEvent5();
119+
}
120+
#endif
104121
}
105122
#endif
106123

@@ -185,7 +202,8 @@ void HardwareSerial::onReceive(OnReceiveCb function, bool onlyOnTimeout) {
185202

186203
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
187204
// this is a work around for an IDF issue with events and low FIFO Full value (< 3)
188-
if (_onReceiveTimeout) {
205+
// Not valid for the LP UART
206+
if (_onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) {
189207
uartSetRxFIFOFull(_uart, 120);
190208
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
191209
}
@@ -207,12 +225,13 @@ bool HardwareSerial::setRxFIFOFull(uint8_t fifoBytes) {
207225
HSERIAL_MUTEX_LOCK();
208226
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
209227
// this is a work around for an IDF issue with events and low FIFO Full value (< 3)
210-
if (_onReceiveCB != NULL && _onReceiveTimeout) {
228+
// Not valid for the LP UART
229+
if (_onReceiveCB != NULL && _onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) {
211230
fifoBytes = 120;
212231
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
213232
}
214233
bool retCode = uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout
215-
if (fifoBytes > 0 && fifoBytes < SOC_UART_FIFO_LEN - 1) {
234+
if (fifoBytes > 0 && fifoBytes < UART_HW_FIFO_LEN(_uart_nr) - 1) {
216235
_rxFIFOFull = fifoBytes;
217236
}
218237
HSERIAL_MUTEX_UNLOCK();
@@ -298,8 +317,8 @@ void HardwareSerial::_uartEventTask(void *args) {
298317
}
299318

300319
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) {
301-
if (_uart_nr >= SOC_UART_HP_NUM) {
302-
log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_HP_NUM - 1);
320+
if (_uart_nr >= SOC_UART_NUM) {
321+
log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_NUM - 1);
303322
return;
304323
}
305324

@@ -333,16 +352,16 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
333352
txPin = _txPin < 0 ? (int8_t)SOC_TX0 : _txPin;
334353
}
335354
break;
336-
#if SOC_UART_HP_NUM > 1 // may save some flash bytes...
355+
#if SOC_UART_HP_NUM > 1
337356
case UART_NUM_1:
338357
if (rxPin < 0 && txPin < 0) {
339358
// do not change RX1/TX1 if it has already been set before
340359
rxPin = _rxPin < 0 ? (int8_t)RX1 : _rxPin;
341360
txPin = _txPin < 0 ? (int8_t)TX1 : _txPin;
342361
}
343362
break;
344-
#endif
345-
#if SOC_UART_HP_NUM > 2 // may save some flash bytes...
363+
#endif // UART_NUM_1
364+
#if SOC_UART_HP_NUM > 2
346365
case UART_NUM_2:
347366
if (rxPin < 0 && txPin < 0) {
348367
// do not change RX2/TX2 if it has already been set before
@@ -354,11 +373,11 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
354373
#endif
355374
}
356375
break;
357-
#endif
358-
#if SOC_UART_HP_NUM > 3 // may save some flash bytes...
376+
#endif // UART_NUM_2
377+
#if SOC_UART_HP_NUM > 3
359378
case UART_NUM_3:
360379
if (rxPin < 0 && txPin < 0) {
361-
// do not change RX2/TX2 if it has already been set before
380+
// do not change RX3/TX3 if it has already been set before
362381
#ifdef RX3
363382
rxPin = _rxPin < 0 ? (int8_t)RX3 : _rxPin;
364383
#endif
@@ -367,11 +386,11 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
367386
#endif
368387
}
369388
break;
370-
#endif
371-
#if SOC_UART_HP_NUM > 4 // may save some flash bytes...
389+
#endif // UART_NUM_3
390+
#if SOC_UART_HP_NUM > 4
372391
case UART_NUM_4:
373392
if (rxPin < 0 && txPin < 0) {
374-
// do not change RX2/TX2 if it has already been set before
393+
// do not change RX4/TX4 if it has already been set before
375394
#ifdef RX4
376395
rxPin = _rxPin < 0 ? (int8_t)RX4 : _rxPin;
377396
#endif
@@ -380,7 +399,20 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
380399
#endif
381400
}
382401
break;
402+
#endif // UART_NUM_4
403+
#if (SOC_UART_LP_NUM >= 1)
404+
case LP_UART_NUM_0:
405+
if (rxPin < 0 && txPin < 0) {
406+
// do not change RX0_LP/TX0_LP if it has already been set before
407+
#ifdef LP_RX0
408+
rxPin = _rxPin < 0 ? (int8_t)LP_RX0 : _rxPin;
409+
#endif
410+
#ifdef LP_TX0
411+
txPin = _txPin < 0 ? (int8_t)LP_TX0 : _txPin;
383412
#endif
413+
}
414+
break;
415+
#endif // LP_UART_NUM_0
384416
}
385417
}
386418

@@ -445,7 +477,8 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
445477
if (!_rxFIFOFull) { // it has not being changed before calling begin()
446478
// set a default FIFO Full value for the IDF driver
447479
uint8_t fifoFull = 1;
448-
if (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout)) {
480+
// if baud rate is higher than 57600 or onReceive() is set, it will set FIFO Full to 120 bytes, except for LP UART
481+
if (_uart_nr < SOC_UART_HP_NUM && (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout))) {
449482
fifoFull = 120;
450483
}
451484
uartSetRxFIFOFull(_uart, fifoFull);
@@ -477,6 +510,12 @@ void HardwareSerial::setDebugOutput(bool en) {
477510
if (_uart == 0) {
478511
return;
479512
}
513+
#if (SOC_UART_LP_NUM >= 1)
514+
if (_uart_nr >= SOC_UART_HP_NUM) {
515+
log_e("LP UART does not support Debug Output.");
516+
return;
517+
}
518+
#endif
480519
if (en) {
481520
uartSetDebug(_uart);
482521
} else {
@@ -581,34 +620,37 @@ bool HardwareSerial::setMode(SerialMode mode) {
581620
}
582621

583622
// minimum total RX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1. IDF imposition.
623+
// LP UART has FIFO of 16 bytes
584624
size_t HardwareSerial::setRxBufferSize(size_t new_size) {
585625

586626
if (_uart) {
587627
log_e("RX Buffer can't be resized when Serial is already running. Set it before calling begin().");
588628
return 0;
589629
}
590-
591-
if (new_size <= SOC_UART_FIFO_LEN) {
592-
log_w("RX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN + 1); // ESP32, S2, S3 and C3 means higher than 128
593-
new_size = SOC_UART_FIFO_LEN + 1;
630+
uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr);
631+
// Valid value is higher than the FIFO length
632+
if (new_size <= FIFOLen) {
633+
new_size = FIFOLen + 1;
634+
log_w("RX Buffer set to minimum value: %d.", new_size);
594635
}
595636

596637
_rxBufferSize = new_size;
597638
return _rxBufferSize;
598639
}
599640

600-
// minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC).
641+
// minimum total TX Buffer size is the UART FIFO space (128 bytes for most SoC) + 1.
642+
// LP UART has FIFO of 16 bytes
601643
size_t HardwareSerial::setTxBufferSize(size_t new_size) {
602644

603645
if (_uart) {
604646
log_e("TX Buffer can't be resized when Serial is already running. Set it before calling begin().");
605647
return 0;
606648
}
607-
608-
if (new_size <= SOC_UART_FIFO_LEN) {
609-
log_w("TX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN); // ESP32, S2, S3 and C3 means higher than 128
610-
_txBufferSize = 0; // it will use just UART FIFO with SOC_UART_FIFO_LEN bytes (128 for most SoC)
611-
return SOC_UART_FIFO_LEN;
649+
uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr);
650+
// Valid values are zero or higher than the FIFO length
651+
if (new_size > 0 && new_size <= FIFOLen) {
652+
new_size = FIFOLen + 1;
653+
log_w("TX Buffer set to minimum value: %d.", new_size);
612654
}
613655
// if new_size is higher than SOC_UART_FIFO_LEN, TX Ringbuffer will be active and it will be used to report back "availableToWrite()"
614656
_txBufferSize = new_size;

cores/esp32/HardwareSerial.h

+18-5
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,16 @@ typedef enum {
212212
#endif
213213
#endif /* SOC_UART_HP_NUM > 2 */
214214

215+
#if SOC_UART_LP_NUM >= 1
216+
#ifndef LP_RX0
217+
#define LP_RX0 (gpio_num_t) LP_U0RXD_GPIO_NUM
218+
#endif
219+
220+
#ifndef LP_TX0
221+
#define LP_TX0 (gpio_num_t) LP_U0TXD_GPIO_NUM
222+
#endif
223+
#endif /* SOC_UART_LP_NUM >= 1 */
224+
215225
typedef std::function<void(void)> OnReceiveCb;
216226
typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;
217227

@@ -259,7 +269,7 @@ class HardwareSerial : public Stream {
259269
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
260270
void begin(
261271
unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL,
262-
uint8_t rxfifo_full_thrhd = 112
272+
uint8_t rxfifo_full_thrhd = 120
263273
);
264274
void end(void);
265275
void updateBaudRate(unsigned long baud);
@@ -365,18 +375,21 @@ extern void serialEventRun(void) __attribute__((weak));
365375
#endif // ARDUINO_USB_CDC_ON_BOOT
366376
// There is always Seria0 for UART0
367377
extern HardwareSerial Serial0;
368-
#if SOC_UART_HP_NUM > 1
378+
#if SOC_UART_NUM > 1
369379
extern HardwareSerial Serial1;
370380
#endif
371-
#if SOC_UART_HP_NUM > 2
381+
#if SOC_UART_NUM > 2
372382
extern HardwareSerial Serial2;
373383
#endif
374-
#if SOC_UART_HP_NUM > 3
384+
#if SOC_UART_NUM > 3
375385
extern HardwareSerial Serial3;
376386
#endif
377-
#if SOC_UART_HP_NUM > 4
387+
#if SOC_UART_NUM > 4
378388
extern HardwareSerial Serial4;
379389
#endif
390+
#if SOC_UART_NUM > 5
391+
extern HardwareSerial Serial5;
392+
#endif
380393
#endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
381394

382395
#endif // HardwareSerial_h

0 commit comments

Comments
 (0)