Skip to content

Commit 7cbd037

Browse files
authored
Improves UART reading performance (espressif#7525)
* Improves UART reading performance * overrides Stream::readBytes() * fixes override signature * adds some IDF error return conditions
1 parent 744cbc2 commit 7cbd037

File tree

4 files changed

+51
-15
lines changed

4 files changed

+51
-15
lines changed

cores/esp32/HardwareSerial.cpp

+12-13
Original file line numberDiff line numberDiff line change
@@ -450,10 +450,12 @@ int HardwareSerial::peek(void)
450450

451451
int HardwareSerial::read(void)
452452
{
453-
if(available()) {
454-
return uartRead(_uart);
453+
uint8_t c = 0;
454+
if (uartReadBytes(_uart, &c, 1, 0) == 1) {
455+
return c;
456+
} else {
457+
return -1;
455458
}
456-
return -1;
457459
}
458460

459461
// read characters into buffer
@@ -462,16 +464,13 @@ int HardwareSerial::read(void)
462464
// the buffer is NOT null terminated.
463465
size_t HardwareSerial::read(uint8_t *buffer, size_t size)
464466
{
465-
size_t avail = available();
466-
if (size < avail) {
467-
avail = size;
468-
}
469-
size_t count = 0;
470-
while(count < avail) {
471-
*buffer++ = uartRead(_uart);
472-
count++;
473-
}
474-
return count;
467+
return uartReadBytes(_uart, buffer, size, 0);
468+
}
469+
470+
// Overrides Stream::readBytes() to be faster using IDF
471+
size_t HardwareSerial::readBytes(uint8_t *buffer, size_t length)
472+
{
473+
return uartReadBytes(_uart, buffer, length, (uint32_t)getTimeout());
475474
}
476475

477476
void HardwareSerial::flush(void)

cores/esp32/HardwareSerial.h

+6
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ class HardwareSerial: public Stream
118118
{
119119
return read((uint8_t*) buffer, size);
120120
}
121+
// Overrides Stream::readBytes() to be faster using IDF
122+
size_t readBytes(uint8_t *buffer, size_t length);
123+
size_t readBytes(char *buffer, size_t length)
124+
{
125+
return readBytes((uint8_t *) buffer, length);
126+
}
121127
void flush(void);
122128
void flush( bool txOnly);
123129
size_t write(uint8_t);

cores/esp32/esp32-hal-uart.c

+32-2
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,36 @@ uint32_t uartAvailableForWrite(uart_t* uart)
331331
return available;
332332
}
333333

334+
size_t uartReadBytes(uart_t* uart, uint8_t *buffer, size_t size, uint32_t timeout_ms)
335+
{
336+
if(uart == NULL || size == 0 || buffer == NULL) {
337+
return 0;
338+
}
339+
340+
size_t bytes_read = 0;
334341

342+
UART_MUTEX_LOCK();
343+
344+
if (uart->has_peek) {
345+
uart->has_peek = false;
346+
*buffer++ = uart->peek_byte;
347+
size--;
348+
bytes_read = 1;
349+
}
350+
351+
if (size > 0) {
352+
int len = uart_read_bytes(uart->num, buffer, size, pdMS_TO_TICKS(timeout_ms));
353+
if (len < 0) len = 0; // error reading UART
354+
bytes_read += len;
355+
}
356+
357+
358+
UART_MUTEX_UNLOCK();
359+
return bytes_read;
360+
}
361+
362+
// DEPRICATED but the original code will be kepts here as future reference when a final solution
363+
// to the UART driver is defined in the use case of reading byte by byte from UART.
335364
uint8_t uartRead(uart_t* uart)
336365
{
337366
if(uart == NULL) {
@@ -347,14 +376,15 @@ uint8_t uartRead(uart_t* uart)
347376
} else {
348377

349378
int len = uart_read_bytes(uart->num, &c, 1, 20 / portTICK_RATE_MS);
350-
if (len == 0) {
379+
if (len <= 0) { // includes negative return from IDF in case of error
351380
c = 0;
352381
}
353382
}
354383
UART_MUTEX_UNLOCK();
355384
return c;
356385
}
357386

387+
358388
uint8_t uartPeek(uart_t* uart)
359389
{
360390
if(uart == NULL) {
@@ -368,7 +398,7 @@ uint8_t uartPeek(uart_t* uart)
368398
c = uart->peek_byte;
369399
} else {
370400
int len = uart_read_bytes(uart->num, &c, 1, 20 / portTICK_RATE_MS);
371-
if (len == 0) {
401+
if (len <= 0) { // includes negative return from IDF in case of error
372402
c = 0;
373403
} else {
374404
uart->has_peek = true;

cores/esp32/esp32-hal-uart.h

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ void uartGetEventQueue(uart_t* uart, QueueHandle_t *q);
6969

7070
uint32_t uartAvailable(uart_t* uart);
7171
uint32_t uartAvailableForWrite(uart_t* uart);
72+
size_t uartReadBytes(uart_t* uart, uint8_t *buffer, size_t size, uint32_t timeout_ms);
7273
uint8_t uartRead(uart_t* uart);
7374
uint8_t uartPeek(uart_t* uart);
7475

0 commit comments

Comments
 (0)