-
Notifications
You must be signed in to change notification settings - Fork 7.7k
feat(LP_UART): Implements the ESP32-C6/ESP32-P4 Low Power UART as a possible HardwareSerial port #10967
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(LP_UART): Implements the ESP32-C6/ESP32-P4 Low Power UART as a possible HardwareSerial port #10967
Changes from 2 commits
8586f1a
659cf2a
2bd8304
513497c
a68810c
7cca982
cd681ce
8943e27
cd57c19
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
@@ -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 | ||
|
||
|
@@ -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."); | ||
} | ||
|
@@ -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) - 2) { | ||
_rxFIFOFull = fifoBytes; | ||
} | ||
HSERIAL_MUTEX_UNLOCK(); | ||
|
@@ -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; | ||
} | ||
|
||
|
@@ -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 | ||
|
@@ -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 | ||
|
@@ -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 | ||
|
@@ -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 | ||
} | ||
} | ||
|
||
|
@@ -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); | ||
|
@@ -477,6 +510,12 @@ void HardwareSerial::setDebugOutput(bool en) { | |
if (_uart == 0) { | ||
return; | ||
} | ||
#if (SOC_UART_LP_NUM >= 1) | ||
if (_uart_nr == LP_UART_NUM_0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if (_uart_nr >= SOC_UART_HP_NUM) { Will handle cases where LP uarts are more than one (future) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can be done like that for future extension, although there no single applicable case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. Done. |
||
log_e("LP UART does not support Debug Output."); | ||
return; | ||
} | ||
#endif | ||
if (en) { | ||
uartSetDebug(_uart); | ||
} else { | ||
|
@@ -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; | ||
|
Uh oh!
There was an error while loading. Please reload this page.