Skip to content

Commit eb4b290

Browse files
committed
Refactored interrupts disabling and proper FreeRTOS-compliant code for ESP32 class of MCUs.
1 parent b1aae5c commit eb4b290

File tree

2 files changed

+35
-10
lines changed

2 files changed

+35
-10
lines changed

src/SoftwareSerial.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,29 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2323
#include "SoftwareSerial.h"
2424
#include <Arduino.h>
2525

26-
#ifdef ESP32
27-
#define xt_rsil(a) (a)
28-
#define xt_wsr_ps(a)
26+
#ifndef ESP32
27+
uint32_t SoftwareSerial::m_savedPS = 0;
28+
#else
29+
portMUX_TYPE SoftwareSerial::m_interruptsMux = portMUX_INITIALIZER_UNLOCKED;
30+
#endif
31+
32+
inline void IRAM_ATTR SoftwareSerial::disableInterrupts()
33+
{
34+
#ifndef ESP32
35+
m_savedPS = xt_rsil(15);
36+
#else
37+
taskENTER_CRITICAL(&m_interruptsMux);
2938
#endif
39+
}
40+
41+
inline void IRAM_ATTR SoftwareSerial::restoreInterrupts()
42+
{
43+
#ifndef ESP32
44+
xt_wsr_ps(m_savedPS);
45+
#else
46+
taskEXIT_CRITICAL(&m_interruptsMux);
47+
#endif
48+
}
3049

3150
constexpr uint8_t BYTE_ALL_BITS_SET = ~static_cast<uint8_t>(0);
3251

@@ -287,10 +306,10 @@ void IRAM_ATTR SoftwareSerial::preciseDelay(bool sync) {
287306
if (!sync)
288307
{
289308
// Reenable interrupts while delaying to avoid other tasks piling up
290-
if (!m_intTxEnabled) { xt_wsr_ps(m_savedPS); }
309+
if (!m_intTxEnabled) { restoreInterrupts(); }
291310
const auto expired = ESP.getCycleCount() - m_periodStart;
292311
const int32_t remaining = m_periodDuration - expired;
293-
const int32_t ms = remaining / 1000L / static_cast<int32_t>(ESP.getCpuFreqMHz());
312+
const int32_t ms = remaining > 0 ? remaining / 1000L / static_cast<int32_t>(ESP.getCpuFreqMHz()) : 0;
294313
if (ms > 0)
295314
{
296315
delay(ms);
@@ -302,7 +321,7 @@ void IRAM_ATTR SoftwareSerial::preciseDelay(bool sync) {
302321
}
303322
while ((ESP.getCycleCount() - m_periodStart) < m_periodDuration) {}
304323
// Disable interrupts again if applicable
305-
if (!sync && !m_intTxEnabled) { m_savedPS = xt_rsil(15); }
324+
if (!sync && !m_intTxEnabled) { disableInterrupts(); }
306325
m_periodDuration = 0;
307326
m_periodStart = ESP.getCycleCount();
308327
}
@@ -349,7 +368,7 @@ size_t IRAM_ATTR SoftwareSerial::write(const uint8_t* buffer, size_t size, Softw
349368
uint32_t offCycle = 0;
350369
if (!m_intTxEnabled) {
351370
// Disable interrupts in order to get a clean transmit timing
352-
m_savedPS = xt_rsil(15);
371+
disableInterrupts();
353372
}
354373
const uint32_t dataMask = ((1UL << m_dataBits) - 1);
355374
bool withStopBit = true;
@@ -415,8 +434,8 @@ size_t IRAM_ATTR SoftwareSerial::write(const uint8_t* buffer, size_t size, Softw
415434
}
416435
writePeriod(dutyCycle, offCycle, true);
417436
if (!m_intTxEnabled) {
418-
// restore the interrupt state
419-
xt_wsr_ps(m_savedPS);
437+
// restore the interrupt state if applicable
438+
restoreInterrupts();
420439
}
421440
if (m_txEnableValid) {
422441
digitalWrite(m_txEnablePin, LOW);

src/SoftwareSerial.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ class SoftwareSerial : public Stream {
229229
/* check m_rxValid that calling is safe */
230230
void rxBits();
231231
void rxBits(const uint32_t isrCycle);
232+
static void disableInterrupts();
233+
static void restoreInterrupts();
232234

233235
static void rxBitISR(SoftwareSerial* self);
234236
static void rxBitSyncISR(SoftwareSerial* self);
@@ -261,7 +263,11 @@ class SoftwareSerial : public Stream {
261263
std::unique_ptr<circular_queue<uint8_t> > m_parityBuffer;
262264
uint32_t m_periodStart;
263265
uint32_t m_periodDuration;
264-
uint32_t m_savedPS = 0;
266+
#ifndef ESP32
267+
static uint32_t m_savedPS;
268+
#else
269+
static portMUX_TYPE m_interruptsMux;
270+
#endif
265271
// the ISR stores the relative bit times in the buffer. The inversion corrected level is used as sign bit (2's complement):
266272
// 1 = positive including 0, 0 = negative.
267273
std::unique_ptr<circular_queue<uint32_t, SoftwareSerial*> > m_isrBuffer;

0 commit comments

Comments
 (0)