@@ -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
3150constexpr 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);
0 commit comments