Skip to content

Commit 80c3127

Browse files
committed
Subtle change in API contract: readBytes() are blocking in Stream and HardwareSerial. EspSoftwareSerial adopts this behavior now.
For non-blocking buffer read, use the new read(buffer, size) functions. Fixes #127 Bump minor release tag.
1 parent e1bb39a commit 80c3127

File tree

4 files changed

+34
-13
lines changed

4 files changed

+34
-13
lines changed

library.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "EspSoftwareSerial",
3-
"version": "6.4.0",
3+
"version": "6.5.0",
44
"keywords": [
55
"serial", "io", "softwareserial"
66
],

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=EspSoftwareSerial
2-
version=6.4.0
2+
version=6.5.0
33
author=Peter Lerup, Dirk Kaar
44
maintainer=Peter Lerup <[email protected]>
55
sentence=Implementation of the Arduino software serial for ESP8266/ESP32.

src/SoftwareSerial.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ void SoftwareSerial::begin(uint32_t baud, SoftwareSerialConfig config,
6868
m_parityMode = static_cast<SoftwareSerialParity>(config & 070);
6969
m_stopBits = 1 + ((config & 0300) ? 1 : 0);
7070
m_pduBits = m_dataBits + static_cast<bool>(m_parityMode) + m_stopBits;
71-
m_bit_us = (1000000 + baud / 2) / baud;
72-
m_bitCycles = (ESP.getCpuFreqMHz() * 1000000 + baud / 2) / baud;
71+
m_bit_us = (1000000UL + baud / 2) / baud;
72+
m_bitCycles = (ESP.getCpuFreqMHz() * 1000000UL + baud / 2) / baud;
7373
m_intTxEnabled = true;
7474
if (isValidGPIOpin(m_rxPin)) {
7575
std::unique_ptr<circular_queue<uint8_t> > buffer(new circular_queue<uint8_t>((bufCapacity > 0) ? bufCapacity : 64));
@@ -116,7 +116,7 @@ void SoftwareSerial::end()
116116
}
117117

118118
uint32_t SoftwareSerial::baudRate() {
119-
return ESP.getCpuFreqMHz() * 1000000 / m_bitCycles;
119+
return ESP.getCpuFreqMHz() * 1000000UL / m_bitCycles;
120120
}
121121

122122
void SoftwareSerial::setTransmitEnablePin(int8_t txEnablePin) {
@@ -155,7 +155,7 @@ void SoftwareSerial::enableRx(bool on) {
155155
m_rxCurBit = m_pduBits - 1;
156156
// Init to stop bit level and current cycle
157157
m_isrLastCycle = (ESP.getCycleCount() | 1) ^ m_invert;
158-
if (m_bitCycles >= (ESP.getCpuFreqMHz() * 1000000U) / 74880U)
158+
if (m_bitCycles >= (ESP.getCpuFreqMHz() * 1000000UL) / 74880UL)
159159
attachInterruptArg(digitalPinToInterrupt(m_rxPin), reinterpret_cast<void (*)(void*)>(rxBitISR), this, CHANGE);
160160
else
161161
attachInterruptArg(digitalPinToInterrupt(m_rxPin), reinterpret_cast<void (*)(void*)>(rxBitSyncISR), this, m_invert ? RISING : FALLING);
@@ -187,14 +187,14 @@ int SoftwareSerial::read() {
187187
return val;
188188
}
189189

190-
size_t SoftwareSerial::readBytes(uint8_t * buffer, size_t size) {
191-
if (!m_rxValid) { return -1; }
190+
size_t SoftwareSerial::read(uint8_t * buffer, size_t size) {
191+
if (!m_rxValid) { return 0; }
192192
size_t avail;
193193
if (0 == (avail = m_buffer->pop_n(buffer, size))) {
194194
rxBits();
195195
avail = m_buffer->pop_n(buffer, size);
196196
}
197-
if (!avail) return -1;
197+
if (!avail) return 0;
198198
if (m_parityBuffer) {
199199
uint32_t parityBits = avail;
200200
while (m_parityOutPos >>= 1) ++parityBits;
@@ -204,12 +204,25 @@ size_t SoftwareSerial::readBytes(uint8_t * buffer, size_t size) {
204204
return avail;
205205
}
206206

207+
size_t SoftwareSerial::readBytes(uint8_t * buffer, size_t size) {
208+
if (!m_rxValid || !size) { return 0; }
209+
size_t count = 0;
210+
const auto timeout = _timeout * ESP.getCpuFreqMHz() * 1000UL;
211+
const auto start = ESP.getCycleCount();
212+
do {
213+
count += read(&buffer[count], size - count);
214+
if (count >= size) break;
215+
yield();
216+
} while (ESP.getCycleCount() - start < timeout);
217+
return count;
218+
}
219+
207220
int SoftwareSerial::available() {
208221
if (!m_rxValid) { return 0; }
209222
rxBits();
210223
int avail = m_buffer->available();
211224
if (!avail) {
212-
optimistic_yield(10000);
225+
optimistic_yield(10000UL);
213226
}
214227
return avail;
215228
}
@@ -228,7 +241,7 @@ void ICACHE_RAM_ATTR SoftwareSerial::preciseDelay(bool sync) {
228241
// Disable interrupts again
229242
if (!m_intTxEnabled) { m_savedPS = xt_rsil(15); }
230243
}
231-
while ((ESP.getCycleCount() - m_periodStart) < m_periodDuration) { if (!sync) optimistic_yield(10000); }
244+
while ((ESP.getCycleCount() - m_periodStart) < m_periodDuration) { if (!sync) optimistic_yield(10000UL); }
232245
resetPeriodStart();
233246
}
234247

src/SoftwareSerial.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,17 @@ class SoftwareSerial : public Stream {
150150
bool parityOdd(uint8_t byte) {
151151
return !parityEven(byte);
152152
}
153-
/// The readBytes functions are non-waiting, there is no timeout.
153+
/// The read(buffer, size) functions are non-blocking, the same as readBytes but without timeout
154+
size_t read(uint8_t* buffer, size_t size);
155+
/// The read(buffer, size) functions are non-blocking, the same as readBytes but without timeout
156+
size_t read(char* buffer, size_t size) {
157+
return read(reinterpret_cast<uint8_t*>(buffer), size);
158+
}
159+
/// @returns The number of bytes read into buffer, up to size. Times out if the limit set through
160+
/// Stream::setTimeout() is reached. The maximum permissible timeout at 80MHz CPU freq. is ~26s.
154161
size_t readBytes(uint8_t* buffer, size_t size) override;
155-
/// The readBytes functions are non-waiting, there is no timeout.
162+
/// @returns The number of bytes read into buffer, up to size. Times out if the limit set through
163+
/// Stream::setTimeout() is reached. The maximum permissible timeout at 80MHz CPU freq. is ~26s.
156164
size_t readBytes(char* buffer, size_t size) override {
157165
return readBytes(reinterpret_cast<uint8_t*>(buffer), size);
158166
}

0 commit comments

Comments
 (0)