Service watchdog during bounded CAD
This commit is contained in:
1 parent
fc1cfe6952
commit
9051955c6c
7 files changed
+44
-13
No files matched your search
@@ -53,6 +53,10 @@ public:
|
||||
virtual void onAfterTransmit() { }
|
||||
virtual void reboot() = 0;
|
||||
virtual void powerOff() { /* no op */ }
|
||||
// Reload an already-running system watchdog without enabling one. Long,
|
||||
// internally bounded operations can use this while retaining their own
|
||||
// timeout. Boards without an explicit watchdog need no implementation.
|
||||
virtual void serviceWatchdog() { /* no op */ }
|
||||
// Called by example setup() functions to signal that boot is complete.
|
||||
// Boards may override to stop a boot-indicator LED sequence or similar.
|
||||
// Default no-op: boards that don't care need not implement anything.
|
||||
|
||||
@@ -56,6 +56,19 @@ void NRF52Board::begin() {
|
||||
startup_reason = BD_STARTUP_NORMAL;
|
||||
}
|
||||
|
||||
#if NRF52_WATCHDOG_TIMEOUT_SECONDS > 0
|
||||
static void reloadWatchdogChannels() {
|
||||
// Ordinarily only RR0 is enabled. If a bootloader left the watchdog running
|
||||
// with a different reload channel, service every enabled channel.
|
||||
const uint32_t enabled_channels = NRF_WDT->RREN & 0xFFUL;
|
||||
for (uint8_t channel = 0; channel < 8; channel++) {
|
||||
if (enabled_channels & (1UL << channel)) {
|
||||
NRF_WDT->RR[channel] = WDT_RR_RR_Reload;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void NRF52Board::feedWatchdog(bool enabled) {
|
||||
#if NRF52_WATCHDOG_TIMEOUT_SECONDS > 0
|
||||
// The nRF52 watchdog cannot be stopped after it starts. When the persisted
|
||||
@@ -77,20 +90,18 @@ void NRF52Board::feedWatchdog(bool enabled) {
|
||||
NRF_WDT->TASKS_START = 1;
|
||||
}
|
||||
|
||||
// Ordinarily only RR0 is enabled. If a bootloader left the watchdog running
|
||||
// with a different reload channel, service every enabled channel rather
|
||||
// than assuming ownership of RR0 and immediately entering a reset loop.
|
||||
const uint32_t enabled_channels = NRF_WDT->RREN & 0xFFUL;
|
||||
for (uint8_t channel = 0; channel < 8; channel++) {
|
||||
if (enabled_channels & (1UL << channel)) {
|
||||
NRF_WDT->RR[channel] = WDT_RR_RR_Reload;
|
||||
}
|
||||
}
|
||||
reloadWatchdogChannels();
|
||||
#else
|
||||
(void)enabled;
|
||||
#endif
|
||||
}
|
||||
|
||||
void NRF52Board::serviceWatchdog() {
|
||||
#if NRF52_WATCHDOG_TIMEOUT_SECONDS > 0
|
||||
if (NRF_WDT->RUNSTATUS != 0) reloadWatchdogChannels();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
// Power Management global variables
|
||||
uint32_t g_nrf52_reset_reason = 0; // Reset/Startup reason
|
||||
|
||||
@@ -58,6 +58,7 @@ public:
|
||||
// A loop blocked forever in SoftDevice-backed flash I/O will stop feeding it
|
||||
// and be reset automatically.
|
||||
void feedWatchdog(bool enabled = true);
|
||||
void serviceWatchdog() override;
|
||||
virtual uint8_t getStartupReason() const override { return startup_reason; }
|
||||
virtual float getMCUTemperature() override;
|
||||
virtual void reboot() override { NVIC_SystemReset(); }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <RadioLib.h>
|
||||
#include "MeshCore.h"
|
||||
|
||||
#define RH_RF95_MODEM_STATUS_CLEAR 0x10
|
||||
#define RH_RF95_MODEM_STATUS_HEADER_INFO_VALID 0x08
|
||||
@@ -72,7 +73,7 @@ class CustomSX1276 : public SX1276 {
|
||||
| RH_RF95_MODEM_STATUS_HEADER_INFO_VALID)) != 0;
|
||||
}
|
||||
|
||||
int tryScanChannel(unsigned long timeout_ms = 2000UL) {
|
||||
int tryScanChannel(unsigned long timeout_ms, mesh::MainBoard& board) {
|
||||
// start CAD
|
||||
int16_t state = startChannelScan();
|
||||
RADIOLIB_ASSERT(state);
|
||||
@@ -81,12 +82,18 @@ class CustomSX1276 : public SX1276 {
|
||||
// completed, so wait on its IRQ pins with the same bounded policy used
|
||||
// by the generic wrapper.
|
||||
const unsigned long started = millis();
|
||||
unsigned long last_watchdog_service = started;
|
||||
while(!this->mod->hal->digitalRead(this->mod->getIrq())) {
|
||||
this->mod->hal->yield();
|
||||
if(this->mod->hal->digitalRead(this->mod->getGpio())) {
|
||||
return(RADIOLIB_PREAMBLE_DETECTED);
|
||||
}
|
||||
if(millis() - started >= timeout_ms) {
|
||||
const unsigned long now = millis();
|
||||
if(now - last_watchdog_service >= 1000UL) {
|
||||
board.serviceWatchdog();
|
||||
last_watchdog_service = now;
|
||||
}
|
||||
if(now - started >= timeout_ms) {
|
||||
return(RADIOLIB_ERR_RX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
protected:
|
||||
int16_t performChannelScan() override {
|
||||
return ((CustomSX1276 *)_radio)->tryScanChannel();
|
||||
return ((CustomSX1276 *)_radio)->tryScanChannel(CAD_SCAN_TIMEOUT_MS, *_board);
|
||||
}
|
||||
|
||||
bool radioDeepInit() override {
|
||||
|
||||
@@ -621,9 +621,16 @@ int16_t RadioLibWrapper::performChannelScan() {
|
||||
if (result != RADIOLIB_ERR_NONE) return result;
|
||||
|
||||
const unsigned long started = millis();
|
||||
while (millis() - started < 2000UL) {
|
||||
unsigned long last_watchdog_service = started;
|
||||
while (millis() - started < CAD_SCAN_TIMEOUT_MS) {
|
||||
result = _radio->getChannelScanResult();
|
||||
if (result != RADIOLIB_ERR_UNKNOWN) return result;
|
||||
|
||||
const unsigned long now = millis();
|
||||
if (now - last_watchdog_service >= 1000UL) {
|
||||
_board->serviceWatchdog();
|
||||
last_watchdog_service = now;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
class RadioLibWrapper : public mesh::Radio {
|
||||
protected:
|
||||
static constexpr unsigned long CAD_SCAN_TIMEOUT_MS = 10000UL;
|
||||
PhysicalLayer* _radio;
|
||||
mesh::MainBoard* _board;
|
||||
uint32_t n_recv, n_sent, n_recv_errors;
|
||||
|
||||
Reference in new issue
Block a user