diff --git a/src/SoftwareSerial.cpp b/src/SoftwareSerial.cpp index b4a8ab1..f8956b2 100644 --- a/src/SoftwareSerial.cpp +++ b/src/SoftwareSerial.cpp @@ -573,7 +573,7 @@ void IRAM_ATTR UARTBase::rxBitISR(UARTBase* self) { // tick's LSB is repurposed for the level bit if (!self->m_isrBuffer->push((curTick | 1U) ^ !level)) self->m_isrOverflow.store(true); // Trigger rx callback only when receiver is starved - if (empty && self->m_rxHandler) self->m_rxHandler(); + if (empty) self->m_rxHandler(); } void IRAM_ATTR UARTBase::rxBitSyncISR(UARTBase* self) { @@ -599,7 +599,7 @@ void IRAM_ATTR UARTBase::rxBitSyncISR(UARTBase* self) { } } // Trigger rx callback only when receiver is starved - if (empty && self->m_rxHandler) self->m_rxHandler(); + if (empty) self->m_rxHandler(); } void UARTBase::onReceive(const Delegate& handler) { @@ -617,10 +617,9 @@ void UARTBase::onReceive(Delegate&& handler) { // The template member functions below must be in IRAM, but due to a bug GCC doesn't currently // honor the attribute. Instead, it is possible to do explicit specialization and adorn // these with the IRAM attribute: -// Delegate<>::operator bool, Delegate<>::operator (), circular_queue<>::available, +// Delegate<>::operator (), circular_queue<>::available, // circular_queue<>::available_for_push, circular_queue<>::push_peek, circular_queue<>::push -template IRAM_ATTR delegate::detail::DelegateImpl::operator bool() const; template void IRAM_ATTR delegate::detail::DelegateImpl::operator()() const; template size_t IRAM_ATTR circular_queue::available() const; template bool IRAM_ATTR circular_queue::push(uint32_t&&); diff --git a/src/SoftwareSerial.h b/src/SoftwareSerial.h index 93c3498..c0a6648 100644 --- a/src/SoftwareSerial.h +++ b/src/SoftwareSerial.h @@ -435,10 +435,9 @@ using namespace EspSoftwareSerial; // The template member functions below must be in IRAM, but due to a bug GCC doesn't currently // honor the attribute. Instead, it is possible to do explicit specialization and adorn // these with the IRAM attribute: -// Delegate<>::operator bool, Delegate<>::operator (), circular_queue<>::available, +// Delegate<>::operator (), circular_queue<>::available, // circular_queue<>::available_for_push, circular_queue<>::push_peek, circular_queue<>::push -extern template delegate::detail::DelegateImpl::operator bool() const; extern template void delegate::detail::DelegateImpl::operator()() const; extern template size_t circular_queue::available() const; extern template bool circular_queue::push(uint32_t&&); diff --git a/src/circular_queue/Delegate.h b/src/circular_queue/Delegate.h index 1877293..461287e 100644 --- a/src/circular_queue/Delegate.h +++ b/src/circular_queue/Delegate.h @@ -323,6 +323,14 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()(P... args) const { if (FP == kind) @@ -538,6 +546,14 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()(P... args) const { if (FP == kind) @@ -746,6 +762,14 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()(P... args) const { if (FP == kind) @@ -846,6 +870,14 @@ namespace delegate return reinterpret_cast(fn); } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. inline R IRAM_ATTR operator()(P... args) const __attribute__((always_inline)) { if (fn) return fn(std::forward(args...)); @@ -1127,6 +1159,14 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()() const { if (FP == kind) @@ -1341,6 +1381,14 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()() const { if (FP == kind) @@ -1549,6 +1597,14 @@ namespace delegate } } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. R IRAM_ATTR operator()() const { if (FP == kind) @@ -1649,6 +1705,14 @@ namespace delegate return nullptr; } + /// Calling is safe without checking for nullptr. + /// If non-void, returns the default value. + /// In ISR context, where faults and exceptions must not + /// occurs, this saves the extra check for nullptr, + /// and allows the compiler to optimize out checks + /// in std::function which may not be ISR-safe or + /// cause linker errors, like l32r relocation errors + /// on the Xtensa ISA. inline R IRAM_ATTR operator()() const __attribute__((always_inline)) { if (fn) return fn();