Recover SX1262 from stuck transmit busy

This commit is contained in:
mikecarper committed 2026-07-23 23:01:17 -07:00
1 parent 9051955c6c
commit e6c878a011
2 files changed
+39 -1

No files matched your search

+34 -1
View File
@@ -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);
}
};
};
@@ -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;
}