Skip to content

Improves UART reading performance #7525

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

Merged
merged 7 commits into from
Dec 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 12 additions & 13 deletions cores/esp32/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -462,16 +464,13 @@ 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);
}

// 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)
Expand Down
6 changes: 6 additions & 0 deletions cores/esp32/HardwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -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((uint8_t *) buffer, length);
}
void flush(void);
void flush( bool txOnly);
size_t write(uint8_t);
Expand Down
34 changes: 32 additions & 2 deletions cores/esp32/esp32-hal-uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,36 @@ 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;
}

// 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) {
Expand All @@ -342,14 +371,15 @@ 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;
}
}
UART_MUTEX_UNLOCK();
return c;
}


uint8_t uartPeek(uart_t* uart)
{
if(uart == NULL) {
Expand All @@ -363,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;
Expand Down
1 change: 1 addition & 0 deletions cores/esp32/esp32-hal-uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down