From d208bfef94ab83280de30ba4a0675ff73b3ecef3 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 27 Sep 2026 20:39:33 +1300 Subject: [PATCH] Basic patch for LR2021 packet corruption from race + isReceiving tweaks for continuous mode NOTE: After trying a bunch of variants, these events are < 0.1% so I don't think it's worth the complexity to try read these, and the better approach is just reject all that risk having issues. --- src/helpers/radiolib/CustomLR2021.h | 19 +++++++++++-------- src/helpers/radiolib/RadioLibWrappers.cpp | 3 ++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/helpers/radiolib/CustomLR2021.h b/src/helpers/radiolib/CustomLR2021.h index a89ae94330..1dc2ba8d37 100644 --- a/src/helpers/radiolib/CustomLR2021.h +++ b/src/helpers/radiolib/CustomLR2021.h @@ -79,18 +79,10 @@ class CustomLR2021 : public LR2021 { uint32_t irq = getIrqStatus(); bool preamble = irq & RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED; // bit 5 bool header = irq & RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID; // bit 6 - bool hdrErr = irq & RADIOLIB_LR2021_IRQ_LORA_HDR_CRC_ERROR; // bit 9 uint32_t now = millis(); - if (hdrErr) { - clearIrqFlags(RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED | RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID | RADIOLIB_LR2021_IRQ_LORA_HDR_CRC_ERROR); - _activityAt = 0; - _headerSeen = false; - return false; - } if (!header && _headerSeen) { // something cleared the header flag, reset our state. _activityAt = 0; _headerSeen = false; - return false; } if (header) { @@ -116,6 +108,17 @@ class CustomLR2021 : public LR2021 { _activityAt = 0; _headerSeen = false; return false; } + + int16_t readData(uint8_t* data, size_t len) override { + uint16_t fifoLevel = 0; + getRxFifoLevel(&fifoLevel); + // If there's too few bytes it could be a ghost RX_DONE (0 bytes in buffer), late read with another whole packet in the buffer, + // late and we're mid writing the next packet to the fifo, or leftover data from last event clearing the buffer halfway through. + int16_t state = LR2021::readData(data, len); + RADIOLIB_ASSERT(state); + if (fifoLevel != len) { return RADIOLIB_ERR_PACKET_TOO_SHORT; } + return state; + } void setPreambleMillis(uint32_t preambleMillis) { _preambleMillis = preambleMillis; diff --git a/src/helpers/radiolib/RadioLibWrappers.cpp b/src/helpers/radiolib/RadioLibWrappers.cpp index b9c095ac40..845ec0d252 100644 --- a/src/helpers/radiolib/RadioLibWrappers.cpp +++ b/src/helpers/radiolib/RadioLibWrappers.cpp @@ -139,7 +139,8 @@ int RadioLibWrapper::recvRaw(uint8_t* bytes, int sz) { } } #if defined(USE_LR2021) - state = STATE_RX; // LR2021 stays in Rx after readData, calling startReceive while still in Rx throws -706 errors + state = STATE_RX; // LR2021 stays in Rx after readData, calling startReceive when not in standby throws -706 errors + _radio->clearIrqFlags(RADIOLIB_LR2021_IRQ_RX_DONE); // Ensure we never get stuck #else state = STATE_IDLE; // need another startReceive() #endif