Skip to content
126 changes: 84 additions & 42 deletions cores/esp32/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,40 +23,52 @@
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
#endif

#if (SOC_UART_LP_NUM >= 1)
#define UART_HW_FIFO_LEN(uart_num) ((uart_num < SOC_UART_HP_NUM) ? SOC_UART_FIFO_LEN : SOC_LP_UART_FIFO_LEN)
#else
#define UART_HW_FIFO_LEN(uart_num) SOC_UART_FIFO_LEN
#endif

void serialEvent(void) __attribute__((weak));

#if SOC_UART_HP_NUM > 1
#if SOC_UART_NUM > 1
void serialEvent1(void) __attribute__((weak));
#endif /* SOC_UART_HP_NUM > 1 */
#endif /* SOC_UART_NUM > 1 */

#if SOC_UART_HP_NUM > 2
#if SOC_UART_NUM > 2
void serialEvent2(void) __attribute__((weak));
#endif /* SOC_UART_HP_NUM > 2 */
#endif /* SOC_UART_NUM > 2 */

#if SOC_UART_HP_NUM > 3
#if SOC_UART_NUM > 3
void serialEvent3(void) __attribute__((weak));
#endif /* SOC_UART_HP_NUM > 3 */
#endif /* SOC_UART_NUM > 3 */

#if SOC_UART_HP_NUM > 4
#if SOC_UART_NUM > 4
void serialEvent4(void) __attribute__((weak));
#endif /* SOC_UART_HP_NUM > 4 */
#endif /* SOC_UART_NUM > 4 */

#if SOC_UART_NUM > 5
void serialEvent5(void) __attribute__((weak));
#endif /* SOC_UART_NUM > 5 */

#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
// There is always Seria0 for UART0
HardwareSerial Serial0(0);
#if SOC_UART_HP_NUM > 1
#if SOC_UART_NUM > 1
HardwareSerial Serial1(1);
#endif
#if SOC_UART_HP_NUM > 2
#if SOC_UART_NUM > 2
HardwareSerial Serial2(2);
#endif
#if SOC_UART_HP_NUM > 3
#if SOC_UART_NUM > 3
HardwareSerial Serial3(3);
#endif
#if SOC_UART_HP_NUM > 4
#if SOC_UART_NUM > 4
HardwareSerial Serial4(4);
#endif

#if (SOC_UART_NUM > 5)
HardwareSerial Serial5(5);
#endif
#if HWCDC_SERIAL_IS_DEFINED == 1 // Hardware JTAG CDC Event
extern void HWCDCSerialEvent(void) __attribute__((weak));
#endif
Expand All @@ -81,26 +93,31 @@ void serialEventRun(void) {
if (serialEvent && Serial0.available()) {
serialEvent();
}
#if SOC_UART_HP_NUM > 1
#if SOC_UART_NUM > 1
if (serialEvent1 && Serial1.available()) {
serialEvent1();
}
#endif
#if SOC_UART_HP_NUM > 2
#if SOC_UART_NUM > 2
if (serialEvent2 && Serial2.available()) {
serialEvent2();
}
#endif
#if SOC_UART_HP_NUM > 3
#if SOC_UART_NUM > 3
if (serialEvent3 && Serial3.available()) {
serialEvent3();
}
#endif
#if SOC_UART_HP_NUM > 4
#if SOC_UART_NUM > 4
if (serialEvent4 && Serial4.available()) {
serialEvent4();
}
#endif
#if SOC_UART_NUM > 5
if (serialEvent5 && Serial5.available()) {
serialEvent5();
}
#endif
}
#endif

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

// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
// this is a work around for an IDF issue with events and low FIFO Full value (< 3)
if (_onReceiveTimeout) {
// Not valid for the LP UART
if (_onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) {
uartSetRxFIFOFull(_uart, 120);
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
}
Expand All @@ -207,12 +225,13 @@ bool HardwareSerial::setRxFIFOFull(uint8_t fifoBytes) {
HSERIAL_MUTEX_LOCK();
// in case that onReceive() shall work only with RX Timeout, FIFO shall be high
// this is a work around for an IDF issue with events and low FIFO Full value (< 3)
if (_onReceiveCB != NULL && _onReceiveTimeout) {
// Not valid for the LP UART
if (_onReceiveCB != NULL && _onReceiveTimeout && _uart_nr < SOC_UART_HP_NUM) {
fifoBytes = 120;
log_w("OnReceive is set to Timeout only, thus FIFO Full is now 120 bytes.");
}
bool retCode = uartSetRxFIFOFull(_uart, fifoBytes); // Set new timeout
if (fifoBytes > 0 && fifoBytes < SOC_UART_FIFO_LEN - 1) {
if (fifoBytes > 0 && fifoBytes < UART_HW_FIFO_LEN(_uart_nr) - 1) {
_rxFIFOFull = fifoBytes;
}
HSERIAL_MUTEX_UNLOCK();
Expand Down Expand Up @@ -298,8 +317,8 @@ 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 (_uart_nr >= SOC_UART_HP_NUM) {
log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_HP_NUM - 1);
if (_uart_nr >= SOC_UART_NUM) {
log_e("Serial number is invalid, please use a number from 0 to %u", SOC_UART_NUM - 1);
return;
}

Expand Down Expand Up @@ -333,16 +352,16 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
txPin = _txPin < 0 ? (int8_t)SOC_TX0 : _txPin;
}
break;
#if SOC_UART_HP_NUM > 1 // may save some flash bytes...
#if SOC_UART_HP_NUM > 1
case UART_NUM_1:
if (rxPin < 0 && txPin < 0) {
// do not change RX1/TX1 if it has already been set before
rxPin = _rxPin < 0 ? (int8_t)RX1 : _rxPin;
txPin = _txPin < 0 ? (int8_t)TX1 : _txPin;
}
break;
#endif
#if SOC_UART_HP_NUM > 2 // may save some flash bytes...
#endif // UART_NUM_1
#if SOC_UART_HP_NUM > 2
case UART_NUM_2:
if (rxPin < 0 && txPin < 0) {
// do not change RX2/TX2 if it has already been set before
Expand All @@ -354,11 +373,11 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
#endif
}
break;
#endif
#if SOC_UART_HP_NUM > 3 // may save some flash bytes...
#endif // UART_NUM_2
#if SOC_UART_HP_NUM > 3
case UART_NUM_3:
if (rxPin < 0 && txPin < 0) {
// do not change RX2/TX2 if it has already been set before
// do not change RX3/TX3 if it has already been set before
#ifdef RX3
rxPin = _rxPin < 0 ? (int8_t)RX3 : _rxPin;
#endif
Expand All @@ -367,11 +386,11 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
#endif
}
break;
#endif
#if SOC_UART_HP_NUM > 4 // may save some flash bytes...
#endif // UART_NUM_3
#if SOC_UART_HP_NUM > 4
case UART_NUM_4:
if (rxPin < 0 && txPin < 0) {
// do not change RX2/TX2 if it has already been set before
// do not change RX4/TX4 if it has already been set before
#ifdef RX4
rxPin = _rxPin < 0 ? (int8_t)RX4 : _rxPin;
#endif
Expand All @@ -380,7 +399,20 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
#endif
}
break;
#endif // UART_NUM_4
#if (SOC_UART_LP_NUM >= 1)
case LP_UART_NUM_0:
if (rxPin < 0 && txPin < 0) {
// do not change RX0_LP/TX0_LP if it has already been set before
#ifdef LP_RX0
rxPin = _rxPin < 0 ? (int8_t)LP_RX0 : _rxPin;
#endif
#ifdef LP_TX0
txPin = _txPin < 0 ? (int8_t)LP_TX0 : _txPin;
#endif
}
break;
#endif // LP_UART_NUM_0
}
}

Expand Down Expand Up @@ -445,7 +477,8 @@ void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, in
if (!_rxFIFOFull) { // it has not being changed before calling begin()
// set a default FIFO Full value for the IDF driver
uint8_t fifoFull = 1;
if (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout)) {
// if baud rate is higher than 57600 or onReceive() is set, it will set FIFO Full to 120 bytes, except for LP UART
if (_uart_nr < SOC_UART_HP_NUM && (baud > 57600 || (_onReceiveCB != NULL && _onReceiveTimeout))) {
fifoFull = 120;
}
uartSetRxFIFOFull(_uart, fifoFull);
Expand Down Expand Up @@ -477,6 +510,12 @@ void HardwareSerial::setDebugOutput(bool en) {
if (_uart == 0) {
return;
}
#if (SOC_UART_LP_NUM >= 1)
if (_uart_nr >= SOC_UART_HP_NUM) {
log_e("LP UART does not support Debug Output.");
return;
}
#endif
if (en) {
uartSetDebug(_uart);
} else {
Expand Down Expand Up @@ -581,34 +620,37 @@ bool HardwareSerial::setMode(SerialMode mode) {
}

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

if (_uart) {
log_e("RX Buffer can't be resized when Serial is already running. Set it before calling begin().");
return 0;
}

if (new_size <= SOC_UART_FIFO_LEN) {
log_w("RX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN + 1); // ESP32, S2, S3 and C3 means higher than 128
new_size = SOC_UART_FIFO_LEN + 1;
uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr);
// Valid value is higher than the FIFO length
if (new_size <= FIFOLen) {
new_size = FIFOLen + 1;
log_w("RX Buffer set to minimum value: %d.", new_size);
}

_rxBufferSize = new_size;
return _rxBufferSize;
}

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

if (_uart) {
log_e("TX Buffer can't be resized when Serial is already running. Set it before calling begin().");
return 0;
}

if (new_size <= SOC_UART_FIFO_LEN) {
log_w("TX Buffer set to minimum value: %d.", SOC_UART_FIFO_LEN); // ESP32, S2, S3 and C3 means higher than 128
_txBufferSize = 0; // it will use just UART FIFO with SOC_UART_FIFO_LEN bytes (128 for most SoC)
return SOC_UART_FIFO_LEN;
uint8_t FIFOLen = UART_HW_FIFO_LEN(_uart_nr);
// Valid values are zero or higher than the FIFO length
if (new_size > 0 && new_size <= FIFOLen) {
new_size = FIFOLen + 1;
log_w("TX Buffer set to minimum value: %d.", new_size);
}
// if new_size is higher than SOC_UART_FIFO_LEN, TX Ringbuffer will be active and it will be used to report back "availableToWrite()"
_txBufferSize = new_size;
Expand Down
23 changes: 18 additions & 5 deletions cores/esp32/HardwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ typedef enum {
#endif
#endif /* SOC_UART_HP_NUM > 2 */

#if SOC_UART_LP_NUM >= 1
#ifndef LP_RX0
#define LP_RX0 (gpio_num_t) LP_U0RXD_GPIO_NUM
#endif

#ifndef LP_TX0
#define LP_TX0 (gpio_num_t) LP_U0TXD_GPIO_NUM
#endif
#endif /* SOC_UART_LP_NUM >= 1 */

typedef std::function<void(void)> OnReceiveCb;
typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;

Expand Down Expand Up @@ -259,7 +269,7 @@ class HardwareSerial : public Stream {
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
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
uint8_t rxfifo_full_thrhd = 120
);
void end(void);
void updateBaudRate(unsigned long baud);
Expand Down Expand Up @@ -365,18 +375,21 @@ extern void serialEventRun(void) __attribute__((weak));
#endif // ARDUINO_USB_CDC_ON_BOOT
// There is always Seria0 for UART0
extern HardwareSerial Serial0;
#if SOC_UART_HP_NUM > 1
#if SOC_UART_NUM > 1
extern HardwareSerial Serial1;
#endif
#if SOC_UART_HP_NUM > 2
#if SOC_UART_NUM > 2
extern HardwareSerial Serial2;
#endif
#if SOC_UART_HP_NUM > 3
#if SOC_UART_NUM > 3
extern HardwareSerial Serial3;
#endif
#if SOC_UART_HP_NUM > 4
#if SOC_UART_NUM > 4
extern HardwareSerial Serial4;
#endif
#if SOC_UART_NUM > 5
extern HardwareSerial Serial5;
#endif
#endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)

#endif // HardwareSerial_h
Loading
Loading