diff --git a/cores/esp8266/HardwareSerial.cpp b/cores/esp8266/HardwareSerial.cpp index ba3d622bb..ebb23ce0c 100644 --- a/cores/esp8266/HardwareSerial.cpp +++ b/cores/esp8266/HardwareSerial.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "Arduino.h" #include "HardwareSerial.h" #include "Esp.h" @@ -132,6 +133,22 @@ unsigned long HardwareSerial::detectBaudrate(time_t timeoutMillis) return detectedBaudrate; } +size_t HardwareSerial::readBytes(char* buffer, size_t size) +{ + size_t got = 0; + + while (got < size) + { + esp8266::polledTimeout::oneShot timeOut(_timeout); + size_t avail; + while ((avail = available()) == 0 && !timeOut); + if (avail == 0) + break; + got += read(buffer + got, std::min(size - got, avail)); + } + return got; +} + #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) HardwareSerial Serial(UART0); #endif diff --git a/cores/esp8266/HardwareSerial.h b/cores/esp8266/HardwareSerial.h index f76e80431..f66bb8a77 100644 --- a/cores/esp8266/HardwareSerial.h +++ b/cores/esp8266/HardwareSerial.h @@ -132,13 +132,15 @@ public: // return -1 when data is unvailable (arduino api) return uart_read_char(_uart); } - size_t readBytes(char* buffer, size_t size) override + // ::read(buffer, size): same as readBytes without timeout + size_t read(char* buffer, size_t size) { return uart_read(_uart, buffer, size); } + size_t readBytes(char* buffer, size_t size) override; size_t readBytes(uint8_t* buffer, size_t size) override { - return uart_read(_uart, (char*)buffer, size); + return readBytes((char*)buffer, size); } int availableForWrite(void) { diff --git a/libraries/esp8266/examples/SerialStress/SerialStress.ino b/libraries/esp8266/examples/SerialStress/SerialStress.ino index 7b13d6eb7..12ca68d4d 100644 --- a/libraries/esp8266/examples/SerialStress/SerialStress.ino +++ b/libraries/esp8266/examples/SerialStress/SerialStress.ino @@ -16,12 +16,15 @@ #define BUFFER_SIZE 4096 // may be useless to use more than 2*SERIAL_SIZE_RX #define SERIAL_SIZE_RX 1024 // Serial.setRxBufferSize() +#define FAKE_INCREASED_AVAILABLE 100 // test readBytes's timeout + #define TIMEOUT 5000 #define DEBUG(x...) //x uint8_t buf [BUFFER_SIZE]; uint8_t temp [BUFFER_SIZE]; bool reading = true; +size_t testReadBytesTimeout = 0; static size_t out_idx = 0, in_idx = 0; static size_t local_receive_size = 0; @@ -83,6 +86,7 @@ void setup() { size_for_1sec = baud / 10; // 8n1=10baudFor8bits logger->printf("led changes state every %zd bytes (= 1 second)\n", size_for_1sec); logger->printf("press 's' to stop reading, not writing (induces overrun)\n"); + logger->printf("press 't' to toggle timeout testing on readBytes\n"); // prepare send/compare buffer for (size_t i = 0; i < sizeof buf; i++) { @@ -136,7 +140,7 @@ void loop() { if (reading) { // receive data - maxlen = Serial.available(); + maxlen = Serial.available() + testReadBytesTimeout; if (maxlen > maxavail) { maxavail = maxlen; } @@ -180,8 +184,16 @@ void loop() { timeout = (last_ms = now_ms) + TIMEOUT; } - if (logger->read() == 's') { - logger->println("now stopping reading, keeping writing"); - reading = false; - } + if (logger->available()) + switch (logger->read()) { + case 's': + logger->println("now stopping reading, keeping writing"); + reading = false; + break; + case 't': + testReadBytesTimeout ^= FAKE_INCREASED_AVAILABLE; + logger->printf("testing readBytes timeout: %d\n", !!testReadBytesTimeout); + break; + default:; + } } diff --git a/tests/host/common/MockSerial.cpp b/tests/host/common/MockSerial.cpp index 8c2798dba..19790dc48 100644 --- a/tests/host/common/MockSerial.cpp +++ b/tests/host/common/MockSerial.cpp @@ -30,6 +30,7 @@ */ #include +#include #include // write @@ -64,6 +65,22 @@ void HardwareSerial::flush () fflush(stdout); } +size_t HardwareSerial::readBytes(char* buffer, size_t size) +{ + size_t got = 0; + + while (got < size) + { + esp8266::polledTimeout::oneShot timeOut(_timeout); + size_t avail; + while ((avail = available()) == 0 && !timeOut); + if (avail == 0) + break; + got += read(buffer + got, std::min(size - got, avail)); + } + return got; +} + // uart.c extern "C"