Skip to content
Open
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ compile_commands.json
.venv/
venv/
platformio.local.ini
Pipfile
7 changes: 7 additions & 0 deletions boards/nrf52840_s140_v6.ld
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ SECTIONS
KEEP(*(.fs_data))
PROVIDE(__stop_fs_data = .);
} > RAM

.noinit (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.noinit))
. = ALIGN(4);
} > RAM
} INSERT AFTER .data;

INCLUDE "nrf52_common.ld"
7 changes: 7 additions & 0 deletions boards/nrf52840_s140_v6_extrafs.ld
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ SECTIONS
KEEP(*(.fs_data))
PROVIDE(__stop_fs_data = .);
} > RAM

.noinit (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.noinit))
. = ALIGN(4);
} > RAM
} INSERT AFTER .data;

INCLUDE "nrf52_common.ld"
7 changes: 7 additions & 0 deletions boards/nrf52840_s140_v7.ld
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ SECTIONS
KEEP(*(.fs_data))
PROVIDE(__stop_fs_data = .);
} > RAM

.noinit (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.noinit))
. = ALIGN(4);
} > RAM
} INSERT AFTER .data;

INCLUDE "nrf52_common.ld"
7 changes: 7 additions & 0 deletions boards/nrf52840_s140_v7_extrafs.ld
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ SECTIONS
KEEP(*(.fs_data))
PROVIDE(__stop_fs_data = .);
} > RAM

.noinit (NOLOAD) :
{
. = ALIGN(4);
KEEP(*(.noinit))
. = ALIGN(4);
} > RAM
} INSERT AFTER .data;

INCLUDE "nrf52_common.ld"
40 changes: 40 additions & 0 deletions docs/cli_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -1107,6 +1107,26 @@ region save
#### View the current power source
**Usage:** `get pwrmgt.source`

Returns a composite source and confidence state, for example `vusb+bat:valid`,
`vusb-only:valid`, `bat-only:implausible`, or `vusb-only:possible-battery`.

Confidence thresholds are board-configured in `PowerMgtConfig`. The current
nRF52 power-management board configs all set `battery_min_present_mv = 1000`,
`battery_min_plausible_mv = 2500`
and `battery_max_plausible_mv = 4500`, so BAT voltage is `valid` from 2500mV
to 4500mV inclusive. Readings outside that range are `implausible`, boards with
unusable BAT sensing report `invalid`, and missing power-management
configuration reports `unknown`. VUSB has no configured millivolt thresholds;
it is detected through the nRF52 `USBREGSTATUS.VBUSDETECT` hardware signal.
BAT readings below 1000mV are treated as absent/floating for boot-lock
decisions and are not reported as a BAT source. With VBUS detected this reports
`vusb-only:valid`; without VBUS detect this reports `vusb-only:possible-battery`.
Readings from 1000mV up to the boot-lock threshold still trigger protective
shutdown; high readings above 4500mV are treated as unsafe evidence.
If a battery is connected to VUSB and falls below the hardware VBUS-detect
point while still powering the MCU, the source is reported as
`vusb-only:possible-battery`.

**Note:** Returns an error on boards without power management support.

---
Expand All @@ -1121,6 +1141,26 @@ region save
#### View the boot voltage
**Usage:** `get pwrmgt.bootmv`

Adds `invalid` when the board configuration marks BAT voltage sensing as
untrusted, for example `> 426 mV invalid`.

**Note:** Returns an error on boards without power management support.

---

#### View the last radio initialisation status
**Usage:** `get radio.init_status`

---

#### View the radio initialisation attempt count
**Usage:** `get radio.init_attempts`

---

#### View compact boot diagnostics
**Usage:** `get diag.boot`

**Note:** Returns current and previous reset-retained boot diagnostics. `cur_sd` and `prev_sd` are raw shutdown/fault markers, including low voltage, boot protection, user shutdown, and radio initialisation failure.

---
129 changes: 100 additions & 29 deletions docs/nrf52_power_management.md

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/MeshCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ class MainBoard {

// Power management interface (boards with power management override these)
virtual bool isExternalPowered() { return false; }
virtual const char* getPowerSourceState() { return isExternalPowered() ? "vusb-only:unknown" : "none:unknown"; }
virtual uint16_t getBootVoltage() { return 0; }
virtual bool isBootVoltageValid() { return false; }
virtual uint32_t getResetReason() const { return 0; }
virtual const char* getResetReasonString(uint32_t reason) { return "Not available"; }
virtual uint8_t getShutdownReason() const { return 0; }
Expand Down
24 changes: 22 additions & 2 deletions src/helpers/CommonCLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "TxtDataHelpers.h"
#include "AdvertDataHelpers.h"
#include "TxtDataHelpers.h"
#include "RadioInitDiagnostics.h"
#include <RTClib.h>

#ifndef BRIDGE_MAX_BAUD
Expand Down Expand Up @@ -908,7 +909,7 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
#endif
} else if (memcmp(config, "pwrmgt.source", 13) == 0) {
#ifdef NRF52_POWER_MANAGEMENT
strcpy(reply, _board->isExternalPowered() ? "> external" : "> battery");
sprintf(reply, "> %s", _board->getPowerSourceState());
#else
strcpy(reply, "ERROR: Power management not supported");
#endif
Expand All @@ -922,10 +923,29 @@ void CommonCLI::handleGetCmd(uint32_t sender_timestamp, char* command, char* rep
#endif
} else if (memcmp(config, "pwrmgt.bootmv", 13) == 0) {
#ifdef NRF52_POWER_MANAGEMENT
sprintf(reply, "> %u mV", _board->getBootVoltage());
sprintf(reply, _board->isBootVoltageValid() ? "> %u mV" : "> %u mV invalid",
_board->getBootVoltage());
#else
strcpy(reply, "ERROR: Power management not supported");
#endif
} else if (memcmp(config, "radio.init_status", 17) == 0) {
sprintf(reply, "> %d", (int)g_last_radio_init_status);
} else if (memcmp(config, "radio.init_attempts", 19) == 0) {
sprintf(reply, "> %u", (unsigned)g_radio_init_attempts);
} else if (memcmp(config, "diag.boot", 9) == 0) {
RadioInitBootRecord cur = radioInitCurrentBootRecord();
RadioInitBootRecord prev = radioInitPreviousBootRecord();
sprintf(reply, "> cur_rr=0x%08lX cur_sd=0x%02X cur_st=0x%02X cur_radio=%d cur_att=%u prev_rr=0x%08lX prev_sd=0x%02X prev_st=0x%02X prev_radio=%d prev_att=%u",
(unsigned long)cur.reset_reason,
(unsigned)cur.shutdown_reason,
(unsigned)cur.boot_stage,
(int)cur.radio_status,
(unsigned)cur.attempts,
(unsigned long)prev.reset_reason,
(unsigned)prev.shutdown_reason,
(unsigned)prev.boot_stage,
(int)prev.radio_status,
(unsigned)prev.attempts);
} else {
sprintf(reply, "??: %s", config);
}
Expand Down
Loading