mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-04-20 22:13:47 +00:00
Merge f46f822bfc into dee3e26ac0
This commit is contained in:
commit
f9d43e64ca
14 changed files with 128 additions and 9 deletions
|
|
@ -223,6 +223,7 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
board.loop();
|
||||
the_mesh.loop();
|
||||
sensors.loop();
|
||||
#ifdef DISPLAY_CLASS
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
board.loop();
|
||||
modem->loop();
|
||||
|
||||
if (!modem->isActuallyTransmitting()) {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,8 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
board.loop();
|
||||
|
||||
int len = strlen(command);
|
||||
while (Serial.available() && len < sizeof(command)-1) {
|
||||
char c = Serial.read();
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
board.loop();
|
||||
|
||||
int len = strlen(command);
|
||||
while (Serial.available() && len < sizeof(command)-1) {
|
||||
char c = Serial.read();
|
||||
|
|
|
|||
|
|
@ -589,6 +589,7 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
board.loop();
|
||||
the_mesh.loop();
|
||||
rtc_clock.tick();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,8 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
board.loop();
|
||||
|
||||
int len = strlen(command);
|
||||
while (Serial.available() && len < sizeof(command)-1) {
|
||||
char c = Serial.read();
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ public:
|
|||
virtual uint8_t getStartupReason() const = 0;
|
||||
virtual bool getBootloaderVersion(char* version, size_t max_len) { return false; }
|
||||
virtual bool startOTAUpdate(const char* id, char reply[]) { return false; } // not supported
|
||||
virtual void loop() { /* no op */ }
|
||||
|
||||
// Power management interface (boards with power management override these)
|
||||
virtual bool isExternalPowered() { return false; }
|
||||
|
|
|
|||
|
|
@ -112,15 +112,29 @@ const char* NRF52Board::getShutdownReasonString(uint8_t reason) {
|
|||
bool NRF52Board::checkBootVoltage(const PowerMgtConfig* config) {
|
||||
initPowerMgr();
|
||||
|
||||
// Store config for runtime use (voltage monitoring, WDT)
|
||||
_power_config = config;
|
||||
_last_voltage_check_ms = 0;
|
||||
_low_voltage_count = 0;
|
||||
|
||||
// Read boot voltage
|
||||
boot_voltage_mv = getBattMilliVolts();
|
||||
|
||||
if (config->voltage_bootlock == 0) return true; // Protection disabled
|
||||
|
||||
if (config->voltage_bootlock == 0) {
|
||||
// Boot protection disabled, but still init WDT if configured
|
||||
if (config->wdt_timeout_ms > 0) {
|
||||
initWatchdog(config->wdt_timeout_ms);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip check if externally powered
|
||||
if (isExternalPowered()) {
|
||||
MESH_DEBUG_PRINTLN("PWRMGT: Boot check skipped (external power)");
|
||||
boot_voltage_mv = getBattMilliVolts();
|
||||
if (config->wdt_timeout_ms > 0) {
|
||||
initWatchdog(config->wdt_timeout_ms);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -136,6 +150,11 @@ bool NRF52Board::checkBootVoltage(const PowerMgtConfig* config) {
|
|||
return false; // Should never reach this
|
||||
}
|
||||
|
||||
// Boot voltage OK — start WDT if configured
|
||||
if (config->wdt_timeout_ms > 0) {
|
||||
initWatchdog(config->wdt_timeout_ms);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -236,8 +255,67 @@ void NRF52Board::configureVoltageWake(uint8_t ain_channel, uint8_t refsel) {
|
|||
|
||||
MESH_DEBUG_PRINTLN("PWRMGT: VBUS wake configured");
|
||||
}
|
||||
|
||||
#define VOLTAGE_CHECK_INTERVAL_MS 30000
|
||||
#define LOW_VOLTAGE_COUNT_THRESHOLD 3
|
||||
|
||||
void NRF52Board::initWatchdog(uint32_t timeout_ms) {
|
||||
// Configure WDT via direct register access (same pattern as LPCOMP/POWER registers)
|
||||
NRF_WDT->CONFIG = WDT_CONFIG_SLEEP_Run << WDT_CONFIG_SLEEP_Pos; // Keep running during WFE sleep
|
||||
NRF_WDT->CRV = (uint32_t)((uint64_t)timeout_ms * 32768 / 1000); // Timeout in 32.768kHz ticks
|
||||
NRF_WDT->RREN = WDT_RREN_RR0_Enabled << WDT_RREN_RR0_Pos; // Enable reload register 0
|
||||
NRF_WDT->TASKS_START = 1; // Start — cannot be stopped once started
|
||||
|
||||
// Initial feed
|
||||
NRF_WDT->RR[0] = WDT_RR_RR_Reload;
|
||||
|
||||
MESH_DEBUG_PRINTLN("PWRMGT: WDT started (%lu ms)", (unsigned long)timeout_ms);
|
||||
}
|
||||
|
||||
void NRF52Board::feedWatchdog() {
|
||||
if (NRF_WDT->RUNSTATUS) {
|
||||
NRF_WDT->RR[0] = WDT_RR_RR_Reload;
|
||||
}
|
||||
}
|
||||
|
||||
void NRF52Board::checkRuntimeVoltage() {
|
||||
if (_power_config == nullptr || _power_config->voltage_runtime == 0) return;
|
||||
|
||||
uint32_t now = millis();
|
||||
if (now - _last_voltage_check_ms < VOLTAGE_CHECK_INTERVAL_MS) return;
|
||||
_last_voltage_check_ms = now;
|
||||
|
||||
if (isExternalPowered()) {
|
||||
_low_voltage_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t mv = getBattMilliVolts();
|
||||
|
||||
// Ignore ADC glitch readings
|
||||
if (mv < 1000) return;
|
||||
|
||||
if (mv < _power_config->voltage_runtime) {
|
||||
_low_voltage_count++;
|
||||
MESH_DEBUG_PRINTLN("PWRMGT: Low voltage %u mV (%u/%u)",
|
||||
mv, _low_voltage_count, LOW_VOLTAGE_COUNT_THRESHOLD);
|
||||
if (_low_voltage_count >= LOW_VOLTAGE_COUNT_THRESHOLD) {
|
||||
MESH_DEBUG_PRINTLN("PWRMGT: Runtime voltage too low - shutting down");
|
||||
initiateShutdown(SHUTDOWN_REASON_LOW_VOLTAGE);
|
||||
}
|
||||
} else {
|
||||
_low_voltage_count = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void NRF52Board::loop() {
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
feedWatchdog();
|
||||
checkRuntimeVoltage();
|
||||
#endif
|
||||
}
|
||||
|
||||
void NRF52BoardDCDC::begin() {
|
||||
NRF52Board::begin();
|
||||
|
||||
|
|
@ -252,10 +330,14 @@ void NRF52BoardDCDC::begin() {
|
|||
}
|
||||
|
||||
void NRF52Board::sleep(uint32_t secs) {
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
feedWatchdog();
|
||||
#endif
|
||||
|
||||
// Clear FPU interrupt flags to avoid insomnia
|
||||
// see errata 87 for details https://docs.nordicsemi.com/bundle/errata_nRF52840_Rev3/page/ERR/nRF52840/Rev3/latest/anomaly_840_87.html
|
||||
#if (__FPU_USED == 1)
|
||||
__set_FPSCR(__get_FPSCR() & ~(0x0000009F));
|
||||
__set_FPSCR(__get_FPSCR() & ~(0x0000009F));
|
||||
(void) __get_FPSCR();
|
||||
NVIC_ClearPendingIRQ(FPU_IRQn);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ struct PowerMgtConfig {
|
|||
// Boot protection voltage threshold (millivolts)
|
||||
// Set to 0 to disable boot protection
|
||||
uint16_t voltage_bootlock;
|
||||
|
||||
// Runtime low voltage shutdown threshold (millivolts), 0=disabled
|
||||
uint16_t voltage_runtime;
|
||||
// Watchdog timer timeout (ms), 0=disabled
|
||||
uint32_t wdt_timeout_ms;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
@ -38,14 +43,25 @@ protected:
|
|||
uint8_t shutdown_reason; // GPREGRET value (why we entered last SYSTEMOFF)
|
||||
uint16_t boot_voltage_mv; // Battery voltage at boot (millivolts)
|
||||
|
||||
const PowerMgtConfig* _power_config;
|
||||
uint32_t _last_voltage_check_ms;
|
||||
uint8_t _low_voltage_count;
|
||||
|
||||
bool checkBootVoltage(const PowerMgtConfig* config);
|
||||
void enterSystemOff(uint8_t reason);
|
||||
void configureVoltageWake(uint8_t ain_channel, uint8_t refsel);
|
||||
virtual void initiateShutdown(uint8_t reason);
|
||||
void initWatchdog(uint32_t timeout_ms);
|
||||
void feedWatchdog();
|
||||
void checkRuntimeVoltage();
|
||||
#endif
|
||||
|
||||
public:
|
||||
NRF52Board(char *otaname) : ota_name(otaname) {}
|
||||
NRF52Board(char *otaname) : ota_name(otaname)
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
, _power_config(nullptr), _last_voltage_check_ms(0), _low_voltage_count(0)
|
||||
#endif
|
||||
{}
|
||||
virtual void begin();
|
||||
virtual uint8_t getStartupReason() const override { return startup_reason; }
|
||||
virtual float getMCUTemperature() override;
|
||||
|
|
@ -53,6 +69,7 @@ public:
|
|||
virtual bool getBootloaderVersion(char* version, size_t max_len) override;
|
||||
virtual bool startOTAUpdate(const char *id, char reply[]) override;
|
||||
virtual void sleep(uint32_t secs) override;
|
||||
virtual void loop() override;
|
||||
|
||||
#ifdef NRF52_POWER_MANAGEMENT
|
||||
bool isExternalPowered() override;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,9 @@
|
|||
const PowerMgtConfig power_config = {
|
||||
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
|
||||
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK,
|
||||
.voltage_runtime = PWRMGT_VOLTAGE_BOOTLOCK - 200,
|
||||
.wdt_timeout_ms = 60000
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
const PowerMgtConfig power_config = {
|
||||
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
|
||||
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK,
|
||||
.voltage_runtime = PWRMGT_VOLTAGE_BOOTLOCK - 200,
|
||||
.wdt_timeout_ms = 60000
|
||||
};
|
||||
|
||||
void T114Board::initiateShutdown(uint8_t reason) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
const PowerMgtConfig power_config = {
|
||||
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
|
||||
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK,
|
||||
.voltage_runtime = PWRMGT_VOLTAGE_BOOTLOCK - 200,
|
||||
.wdt_timeout_ms = 60000
|
||||
};
|
||||
|
||||
void RAK4631Board::initiateShutdown(uint8_t reason) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@
|
|||
const PowerMgtConfig power_config = {
|
||||
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
|
||||
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK,
|
||||
.voltage_runtime = PWRMGT_VOLTAGE_BOOTLOCK - 200,
|
||||
.wdt_timeout_ms = 60000
|
||||
};
|
||||
|
||||
void SenseCapSolarBoard::initiateShutdown(uint8_t reason) {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
const PowerMgtConfig power_config = {
|
||||
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
|
||||
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
|
||||
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK,
|
||||
.voltage_runtime = PWRMGT_VOLTAGE_BOOTLOCK - 200,
|
||||
.wdt_timeout_ms = 60000
|
||||
};
|
||||
|
||||
void XiaoNrf52Board::initiateShutdown(uint8_t reason) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue