diff --git a/src/helpers/radiolib/CustomSX1262.h b/src/helpers/radiolib/CustomSX1262.h index 9337aea4..40c3e146 100644 --- a/src/helpers/radiolib/CustomSX1262.h +++ b/src/helpers/radiolib/CustomSX1262.h @@ -6,6 +6,10 @@ #define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received #define SX126X_IRQ_PREAMBLE_DETECTED 0x04 +#ifndef SX126X_TX_BUSY_TIMEOUT_MS +#define SX126X_TX_BUSY_TIMEOUT_MS 1000UL +#endif + class CustomSX1262 : public SX1262 { public: CustomSX1262(Module *mod) : SX1262(mod) { } @@ -105,6 +109,35 @@ class CustomSX1262 : public SX1262 { return busy != RADIOLIB_NC && this->mod->hal->digitalRead(busy); } + // RadioLib waits without a deadline for BUSY to fall after SetTx. A radio + // fault there blocks the entire main loop until the MCU watchdog reboots + // the node. Keep the normal launch behavior, but return the same timeout + // used by bounded RadioLib SPI waits so the wrapper can reset the radio. + int16_t launchMode() override { + if (this->stagedMode != RADIOLIB_RADIO_MODE_TX) { + return SX1262::launchMode(); + } + + this->mod->setRfSwitchState(this->txMode); + int16_t state = this->setTx(RADIOLIB_SX126X_TX_TIMEOUT_NONE); + if (state != RADIOLIB_ERR_NONE) { + this->stagedMode = RADIOLIB_RADIO_MODE_NONE; + return state; + } + + const unsigned long started = millis(); + while (isChipBusy()) { + yield(); + if (millis() - started >= SX126X_TX_BUSY_TIMEOUT_MS) { + this->stagedMode = RADIOLIB_RADIO_MODE_NONE; + return RADIOLIB_ERR_SPI_CMD_TIMEOUT; + } + } + + this->stagedMode = RADIOLIB_RADIO_MODE_NONE; + return RADIOLIB_ERR_NONE; + } + bool isReceiving() { if (isChipBusy()) return false; // asleep, cannot be mid-receive @@ -136,4 +169,4 @@ class CustomSX1262 : public SX1262 { readRegister(RADIOLIB_SX126X_REG_RX_GAIN, &rxGain, 1); return (rxGain == RADIOLIB_SX126X_RX_GAIN_BOOSTED); } -}; \ No newline at end of file +}; diff --git a/src/helpers/radiolib/RadioLibWrappers.cpp b/src/helpers/radiolib/RadioLibWrappers.cpp index a457477a..efcc03e3 100644 --- a/src/helpers/radiolib/RadioLibWrappers.cpp +++ b/src/helpers/radiolib/RadioLibWrappers.cpp @@ -595,6 +595,11 @@ bool RadioLibWrapper::startSendRaw(const uint8_t* bytes, int len) { MESH_DEBUG_PRINTLN("RadioLibWrapper: error: startTransmit(%d)", err); idle(); // trigger another startRecv() _board->onAfterTransmit(); + if (err == RADIOLIB_ERR_SPI_CMD_TIMEOUT) { + // A stuck BUSY line cannot be repaired with another SPI command. Radios + // with a reset pin recover immediately; others use their safest fallback. + recoverRadio(true); + } return false; }