diff --git a/src/mesh/RadioLibInterface.cpp b/src/mesh/RadioLibInterface.cpp index de468cf9793..708766b9b4b 100644 --- a/src/mesh/RadioLibInterface.cpp +++ b/src/mesh/RadioLibInterface.cpp @@ -555,6 +555,17 @@ void RadioLibInterface::pollMissedIrqs() if (isReceiving) { checkRxDoneIrqFlag(); } + if (sendingPacket != NULL) { + checkTxDoneIrqFlag(); + // The stuck-TX guard in canSendImmediately only runs when the queue + // gets new packets. If the queue is empty, a wedged radio sits + // forever — fire the same reboot path here so it always trips. + if (!Throttle::isWithinTimespanMs(lastTxStart, 60000) && rebootAtMsec == 0) { + LOG_ERROR("Hardware Failure! TX stuck for more than 60s (poll)"); + RECORD_CRITICALERROR(meshtastic_CriticalErrorCode_TRANSMIT_FAILED); + rebootAtMsec = lastTxStart + 65000; + } + } } void RadioLibInterface::resetAGC() @@ -570,6 +581,14 @@ void RadioLibInterface::checkRxDoneIrqFlag() } } +void RadioLibInterface::checkTxDoneIrqFlag() +{ + if (iface->checkIrq(RADIOLIB_IRQ_TX_DONE)) { + LOG_WARN("caught missed TX_DONE"); + notify(ISR_TX, true); + } +} + void RadioLibInterface::configHardwareForSend() { powerMon->setState(meshtastic_PowerMon_State_Lora_TXOn); diff --git a/src/mesh/RadioLibInterface.h b/src/mesh/RadioLibInterface.h index 0740561f9b2..f024457c211 100644 --- a/src/mesh/RadioLibInterface.h +++ b/src/mesh/RadioLibInterface.h @@ -293,4 +293,5 @@ class RadioLibInterface : public RadioInterface, protected concurrency::Notified bool removePendingTXPacket(NodeNum from, PacketId id, uint32_t hop_limit_lt) override; void checkRxDoneIrqFlag(); + void checkTxDoneIrqFlag(); };