mirror of
https://github.com/meshtastic/firmware.git
synced 2026-10-31 04:19:58 -04:00
SX126x: keep a staged-over frame's RX_DONE across the resume
A CAD skipped because a frame was in flight set keepRxIrqsAtResume only when RX_DONE or CRC_ERR was already up. With a header but no RX_DONE yet, the resume cleared RX_DONE, CRC_ERR, HEADER_ERR and TIMEOUT - and on a CH341 host the flag read in stageTxInRx() and that clear are a USB round trip apart, so a frame completing in between lost its RX_DONE. The poll then had no edge to deliver and the frame waited for checkStaleRxFlags() to retire the latched HEADER_VALID, one max packet later. Keep RX_DONE and CRC_ERR for every busy verdict, so the resume's checkRxDoneIrqFlag() drives the readout. HEADER_ERR and TIMEOUT are still cleared unconditionally: no readout waits on them, and a stale one costs checkStaleRxFlags() a re-arm. Only RX_DONE is mapped to DIO1, so leaving the other terminal flag latched holds no interrupt line. Found by CodeRabbit on #12016; the blanket keep it proposed would have left a stale HEADER_ERR or TIMEOUT latched instead. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0112S3QXU8WUGSCcMQHnwRKZ
This commit is contained in:
1 parent
754975b97e
commit
50f8391918
2 files changed
+12
-8
No files matched your search
@@ -543,12 +543,15 @@ template <typename T> bool SX126xInterface<T>::resumeRunningReceive()
|
||||
#endif
|
||||
if (!rxArmedContinuous)
|
||||
return false;
|
||||
// readData() clears these, but handleReceiveInterrupt()'s early outs do not, and a latched one would hold DIO1
|
||||
// high past the re-arm. PREAMBLE/HEADER_VALID stay: they may belong to the next frame, already arriving. A scan
|
||||
// skipped for an unread frame keeps them all, for its readout.
|
||||
// readData() clears these, but handleReceiveInterrupt()'s early outs do not. PREAMBLE/HEADER_VALID stay: they
|
||||
// may belong to the next frame, already arriving. A scan skipped for a frame in flight or unread keeps that
|
||||
// frame's RX_DONE (the only flag on DIO1) and CRC_ERR for its readout, which checkRxDoneIrqFlag() below drives -
|
||||
// including an RX_DONE that landed in the USB round trip since the scan read the flags. A stale HEADER_ERR or
|
||||
// TIMEOUT has no readout waiting and would cost checkStaleRxFlags() a re-arm, so it goes either way.
|
||||
uint32_t clearMask = RADIOLIB_SX126X_IRQ_HEADER_ERR | RADIOLIB_SX126X_IRQ_TIMEOUT;
|
||||
if (!keepRxIrqs)
|
||||
lora.clearIrqFlags(RADIOLIB_SX126X_IRQ_RX_DONE | RADIOLIB_SX126X_IRQ_CRC_ERR | RADIOLIB_SX126X_IRQ_HEADER_ERR |
|
||||
RADIOLIB_SX126X_IRQ_TIMEOUT);
|
||||
clearMask |= RADIOLIB_SX126X_IRQ_RX_DONE | RADIOLIB_SX126X_IRQ_CRC_ERR;
|
||||
lora.clearIrqFlags(clearMask);
|
||||
activeReceiveStart = 0; // as the standby this replaces would
|
||||
RadioLibInterface::startReceive();
|
||||
enableInterrupt(isrRxLevel0);
|
||||
@@ -779,8 +782,9 @@ template <typename T> bool SX126xInterface<T>::stageTxInRx()
|
||||
// Its readout checks whether our bytes can lie across it
|
||||
if (irq & (RADIOLIB_SX126X_IRQ_HEADER_VALID | doneIrqs))
|
||||
noteStagedOverFrame(base, numbytes);
|
||||
// The busy verdict's rearmReceive() resumes the RX: it must leave a finished frame's flags for its readout
|
||||
keepRxIrqsAtResume = (irq & doneIrqs) != 0;
|
||||
// The busy verdict's rearmReceive() resumes the RX: it must leave the frame's terminal flags for its
|
||||
// readout, whether it had already finished or finishes while we get there
|
||||
keepRxIrqsAtResume = true;
|
||||
LOG_DEBUG("TX stage in RX: frame arriving or unread (irq 0x%04x), scan skipped", (unsigned)irq);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ template <class T> class SX126xInterface : public RadioLibInterface
|
||||
uint8_t rxClobberBase = 0;
|
||||
size_t rxClobberLen = 0;
|
||||
uint8_t rxClobberBytes[256];
|
||||
/** That frame had finished: the next resumeRunningReceive() must not clear its IRQ flags before it is read */
|
||||
/** A frame was in flight or unread: the next resumeRunningReceive() keeps RX_DONE/CRC_ERR for its readout */
|
||||
bool keepRxIrqsAtResume = false;
|
||||
/** A payload written during its backoff: its length (0 if none), packet id, offset and bytes */
|
||||
size_t earlyStagedLen = 0;
|
||||
|
||||
Reference in new issue
Block a user