From 8701c881cf81ba730584e54d870c22568edea8e0 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 27 Nov 2022 17:09:41 -0300 Subject: [PATCH 1/4] Improves UART reading performance --- cores/esp32/HardwareSerial.cpp | 19 ++++++------------- cores/esp32/esp32-hal-uart.c | 28 ++++++++++++++++++++++++++++ cores/esp32/esp32-hal-uart.h | 1 + 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 049c24a74d5..96fbb82cdc5 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -450,10 +450,12 @@ int HardwareSerial::peek(void) int HardwareSerial::read(void) { - if(available()) { - return uartRead(_uart); + uint8_t c = 0; + if (uartReadBytes(_uart, &c, 1, 0) == 1) { + return c; + } else { + return -1; } - return -1; } // read characters into buffer @@ -462,16 +464,7 @@ int HardwareSerial::read(void) // the buffer is NOT null terminated. size_t HardwareSerial::read(uint8_t *buffer, size_t size) { - size_t avail = available(); - if (size < avail) { - avail = size; - } - size_t count = 0; - while(count < avail) { - *buffer++ = uartRead(_uart); - count++; - } - return count; + return uartReadBytes(_uart, buffer, size, 0); } void HardwareSerial::flush(void) diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index e4b24a112f5..5ad7ba13a9c 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -326,6 +326,34 @@ uint32_t uartAvailableForWrite(uart_t* uart) return available; } +size_t uartReadBytes(uart_t* uart, uint8_t *buffer, size_t size, uint32_t timeout_ms) +{ + if(uart == NULL || size == 0 || buffer == NULL) { + return 0; + } + + size_t bytes_read = 0; + + UART_MUTEX_LOCK(); + + if (uart->has_peek) { + uart->has_peek = false; + *buffer++ = uart->peek_byte; + size--; + bytes_read = 1; + } + + if (size > 0) { + int len = uart_read_bytes(uart->num, buffer, size, pdMS_TO_TICKS(timeout_ms)); + if (len < 0) len = 0; // error reading UART + bytes_read += len; + } + + + UART_MUTEX_UNLOCK(); + return bytes_read; +} + uint8_t uartRead(uart_t* uart) { diff --git a/cores/esp32/esp32-hal-uart.h b/cores/esp32/esp32-hal-uart.h index ffb0a3f027a..8e6e7ec4a1b 100644 --- a/cores/esp32/esp32-hal-uart.h +++ b/cores/esp32/esp32-hal-uart.h @@ -69,6 +69,7 @@ void uartGetEventQueue(uart_t* uart, QueueHandle_t *q); uint32_t uartAvailable(uart_t* uart); uint32_t uartAvailableForWrite(uart_t* uart); +size_t uartReadBytes(uart_t* uart, uint8_t *buffer, size_t size, uint32_t timeout_ms); uint8_t uartRead(uart_t* uart); uint8_t uartPeek(uart_t* uart); From e0723028494de5ad6349a039bdd5a190fc5c61ab Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Sun, 4 Dec 2022 10:44:58 -0300 Subject: [PATCH 2/4] overrides Stream::readBytes() --- cores/esp32/HardwareSerial.cpp | 6 ++++++ cores/esp32/HardwareSerial.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 96fbb82cdc5..7b8ee993581 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -467,6 +467,12 @@ size_t HardwareSerial::read(uint8_t *buffer, size_t size) return uartReadBytes(_uart, buffer, size, 0); } +// Overrides Stream::readBytes() to be faster using IDF +size_t HardwareSerial::readBytes(uint8_t *buffer, size_t length) +{ + return uartReadBytes(_uart, buffer, length, (uint32_t)getTimeout()); +} + void HardwareSerial::flush(void) { uartFlush(_uart); diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 0c673c1483f..24b1421311b 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -118,6 +118,12 @@ class HardwareSerial: public Stream { return read((uint8_t*) buffer, size); } + // Overrides Stream::readBytes() to be faster using IDF + size_t readBytes(uint8_t *buffer, size_t length); + size_t readBytes(char *buffer, size_t length) + { + return readBytes((char *) buffer, length); + } void flush(void); void flush( bool txOnly); size_t write(uint8_t); From 6ef09b6a4e13f65b268117ce8356a660d9683ba1 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Tue, 6 Dec 2022 16:42:48 -0300 Subject: [PATCH 3/4] fixes override signature --- cores/esp32/HardwareSerial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 24b1421311b..d5f9c7c1a7b 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -122,7 +122,7 @@ class HardwareSerial: public Stream size_t readBytes(uint8_t *buffer, size_t length); size_t readBytes(char *buffer, size_t length) { - return readBytes((char *) buffer, length); + return readBytes((uint8_t *) buffer, length); } void flush(void); void flush( bool txOnly); From d37a199ebe23ff0f4eb7b923687490780c23ae42 Mon Sep 17 00:00:00 2001 From: Rodrigo Garcia Date: Tue, 6 Dec 2022 16:57:06 -0300 Subject: [PATCH 4/4] adds some IDF error return conditions --- cores/esp32/esp32-hal-uart.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 5ad7ba13a9c..cad9ce7d9c2 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -354,7 +354,8 @@ size_t uartReadBytes(uart_t* uart, uint8_t *buffer, size_t size, uint32_t timeou return bytes_read; } - +// DEPRICATED but the original code will be kepts here as future reference when a final solution +// to the UART driver is defined in the use case of reading byte by byte from UART. uint8_t uartRead(uart_t* uart) { if(uart == NULL) { @@ -370,7 +371,7 @@ uint8_t uartRead(uart_t* uart) } else { int len = uart_read_bytes(uart->num, &c, 1, 20 / portTICK_RATE_MS); - if (len == 0) { + if (len <= 0) { // includes negative return from IDF in case of error c = 0; } } @@ -378,6 +379,7 @@ uint8_t uartRead(uart_t* uart) return c; } + uint8_t uartPeek(uart_t* uart) { if(uart == NULL) { @@ -391,7 +393,7 @@ uint8_t uartPeek(uart_t* uart) c = uart->peek_byte; } else { int len = uart_read_bytes(uart->num, &c, 1, 20 / portTICK_RATE_MS); - if (len == 0) { + if (len <= 0) { // includes negative return from IDF in case of error c = 0; } else { uart->has_peek = true;