Переглянути джерело

Add dead-link auto-recovery watchdog to fix persistent RF disconnect requiring replug

copilot-swe-agent[bot] 4 місяців тому
батько
коміт
d5cc291d65
2 змінених файлів з 20 додано та 0 видалено
  1. 15 0
      OpenPuck/rf_link.cpp
  2. 5 0
      OpenPuck/rf_link.h

+ 15 - 0
OpenPuck/rf_link.cpp

@@ -334,4 +334,19 @@ void rfLinkTask(){
   }
   if (g_connOn && millis()-g_stMs>=1000){ g_f1ps=g_stF1; g_newps=g_stNew; g_pollsps=(uint16_t)g_stPoll;
     g_pollPeriodUs = g_pollDtCnt ? (uint16_t)(g_pollDtSum/g_pollDtCnt) : 0; g_pollDtSum=0; g_pollDtCnt=0; if(Serial.availableForWrite()>70) Serial.printf("# stat polls=%lu/s F1=%lu/s new=%lu/s F3=%lu/s(v%d) e7b=%u crcfail=%lu noRx=%lu slot=%d\n",(unsigned long)g_stPoll,(unsigned long)g_stF1,(unsigned long)g_stNew,(unsigned long)g_stF3,(int8_t)g_connF3v,g_e7b,(unsigned long)g_stCrc,(unsigned long)g_stNoRx,g_connSlot); g_stPoll=0; g_stF1=0; g_stNew=0; g_stF3=0; g_stCrc=0; g_stNoRx=0; g_chF1[0]=g_chF1[1]=g_chF1[2]=0; g_stMs=millis(); }
+  // Dead-link auto-recovery: the hardware WDT (~8s) resets a HUNG loop, but a wedged nRF52 RADIO peripheral
+  // with a still-running loop feeds the WDT every iteration -- RF is permanently dead while USB stays alive.
+  // If the link has been unresponsive for RFLINK_DEAD_RESET_MS after having been alive, reset to clear the
+  // radio hardware. After reset g_connReplyMs=0 so the watchdog stays disarmed until a fresh connection,
+  // preventing repeated resets when the controller is simply powered off.
+  { static unsigned long s_linkDeadSince = 0;
+    if (g_connReplyMs > 0 && millis()-g_connCooldown > 2500) {
+      if (millis()-g_connReplyMs < 300) { s_linkDeadSince = 0; }   // link alive -> reset timer
+      else if (!s_linkDeadSince) { s_linkDeadSince = millis(); }    // link just went dead -> start timer
+      else if ((uint32_t)(millis()-s_linkDeadSince) > RFLINK_DEAD_RESET_MS) {
+        if (Serial.availableForWrite()>60) Serial.printf("# dead-link watchdog: resetting after %lums down\n",(unsigned long)(millis()-s_linkDeadSince));
+        delay(10); NVIC_SystemReset();
+      }
+    } else { s_linkDeadSince = 0; }
+  }
 }

+ 5 - 0
OpenPuck/rf_link.h

@@ -62,3 +62,8 @@ uint8_t rfConnTx(uint8_t ch, uint8_t s1, const uint8_t* payload, uint8_t plen, u
 void rfHopTo(uint8_t newCh);
 // Per-loop: host-frame beacons + connected-mode poll + remote-wakeup + QoS hop + per-second stats.
 void rfLinkTask();
+
+// Dead-link auto-recovery timeout (ms). If the RF link has been unresponsive for this long after having been
+// alive, rfLinkTask() calls NVIC_SystemReset() to clear any wedged radio hardware state. Set long enough that
+// the user can set down the controller without a spurious reset; short enough to recover without physical replug.
+#define RFLINK_DEAD_RESET_MS 120000u   // 2 minutes