|
@@ -0,0 +1,213 @@
|
|
|
|
|
+# nRF52 Power Management
|
|
|
|
|
+
|
|
|
|
|
+## Overview
|
|
|
|
|
+
|
|
|
|
|
+The nRF52 Power Management module provides battery protection features to prevent over-discharge, minimise likelihood of brownout and flash corruption conditions existing, and enable safe voltage-based recovery.
|
|
|
|
|
+
|
|
|
|
|
+## Features
|
|
|
|
|
+
|
|
|
|
|
+### Boot Voltage Protection
|
|
|
|
|
+- Checks battery voltage immediately after boot and before mesh operations commence
|
|
|
|
|
+- If voltage is below a configurable threshold (e.g., 3300mV), the device configures voltage wake (LPCOMP + VBUS) and enters protective shutdown (SYSTEMOFF)
|
|
|
|
|
+- Prevents boot loops when battery is critically low
|
|
|
|
|
+- Skipped when external power (USB VBUS) is detected
|
|
|
|
|
+
|
|
|
|
|
+### Voltage Wake (LPCOMP + VBUS)
|
|
|
|
|
+- Configures the nRF52's Low Power Comparator (LPCOMP) before entering SYSTEMOFF
|
|
|
|
|
+- Enables USB VBUS detection so external power can wake the device
|
|
|
|
|
+- Device automatically wakes when battery voltage rises above recovery threshold or when VBUS is detected
|
|
|
|
|
+
|
|
|
|
|
+### Early Boot Register Capture
|
|
|
|
|
+- Captures RESETREAS (reset reason) and GPREGRET2 (shutdown reason) before SystemInit() clears them
|
|
|
|
|
+- Allows firmware to determine why it booted (cold boot, watchdog, LPCOMP wake, etc.)
|
|
|
|
|
+- Allows firmware to determine why it last shut down (user request, low voltage, boot protection)
|
|
|
|
|
+
|
|
|
|
|
+### Shutdown Reason Tracking
|
|
|
|
|
+Shutdown reason codes (stored in GPREGRET2):
|
|
|
|
|
+| Code | Name | Description |
|
|
|
|
|
+|------|------|-------------|
|
|
|
|
|
+| 0x00 | NONE | Normal boot / no previous shutdown |
|
|
|
|
|
+| 0x4C | LOW_VOLTAGE | Runtime low voltage threshold reached |
|
|
|
|
|
+| 0x55 | USER | User requested powerOff() |
|
|
|
|
|
+| 0x42 | BOOT_PROTECT | Boot voltage protection triggered |
|
|
|
|
|
+
|
|
|
|
|
+## Supported Boards
|
|
|
|
|
+
|
|
|
|
|
+| Board | Implemented | LPCOMP wake | VBUS wake |
|
|
|
|
|
+|-------|-------------|-------------|-----------|
|
|
|
|
|
+| Seeed Studio XIAO nRF52840 (`xiao_nrf52`) | Yes | Yes | Yes |
|
|
|
|
|
+| RAK4631 (`rak4631`) | Yes | Yes | Yes |
|
|
|
|
|
+| Heltec T114 (`heltec_t114`) | Yes | Yes | Yes |
|
|
|
|
|
+| Promicro nRF52840 | No | No | No |
|
|
|
|
|
+| RAK WisMesh Tag | No | No | No |
|
|
|
|
|
+| Heltec Mesh Solar | No | No | No |
|
|
|
|
|
+| LilyGo T-Echo / T-Echo Lite | No | No | No |
|
|
|
|
|
+| SenseCAP Solar | No | No | No |
|
|
|
|
|
+| WIO Tracker L1 / L1 E-Ink | No | No | No |
|
|
|
|
|
+| WIO WM1110 | No | No | No |
|
|
|
|
|
+| Mesh Pocket | No | No | No |
|
|
|
|
|
+| Nano G2 Ultra | No | No | No |
|
|
|
|
|
+| ThinkNode M1/M3/M6 | No | No | No |
|
|
|
|
|
+| T1000-E | No | No | No |
|
|
|
|
|
+| Ikoka Nano/Stick/Handheld (nRF) | No | No | No |
|
|
|
|
|
+| Keepteen LT1 | No | No | No |
|
|
|
|
|
+| Minewsemi ME25LS01 | No | No | No |
|
|
|
|
|
+
|
|
|
|
|
+Notes:
|
|
|
|
|
+- "Implemented" reflects Phase 1 (boot lockout + shutdown reason capture).
|
|
|
|
|
+- User power-off on Heltec T114 does not enable LPCOMP wake.
|
|
|
|
|
+- VBUS detection is used to skip boot lockout on external power, and VBUS wake is configured alongside LPCOMP when supported hardware exposes VBUS to the nRF52.
|
|
|
|
|
+
|
|
|
|
|
+## Technical Details
|
|
|
|
|
+
|
|
|
|
|
+### Architecture
|
|
|
|
|
+
|
|
|
|
|
+The power management functionality is integrated into the `NRF52Board` base class in `src/helpers/NRF52Board.cpp`. Board variants provide hardware-specific configuration via a `PowerMgtConfig` struct and override `initiateShutdown(uint8_t reason)` to perform board-specific power-down work and conditionally enable voltage wake (LPCOMP + VBUS).
|
|
|
|
|
+
|
|
|
|
|
+### Early Boot Capture
|
|
|
|
|
+
|
|
|
|
|
+A static constructor with priority 101 in `NRF52Board.cpp` captures the RESETREAS and GPREGRET2 registers before:
|
|
|
|
|
+- SystemInit() (priority 102) - which clears RESETREAS
|
|
|
|
|
+- Static C++ constructors (default priority 65535)
|
|
|
|
|
+
|
|
|
|
|
+This ensures we capture the true reset reason before any initialisation code runs.
|
|
|
|
|
+
|
|
|
|
|
+### Board Implementation
|
|
|
|
|
+
|
|
|
|
|
+To enable power management on a board variant:
|
|
|
|
|
+
|
|
|
|
|
+1. **Enable in platformio.ini**:
|
|
|
|
|
+ ```ini
|
|
|
|
|
+ -D NRF52_POWER_MANAGEMENT
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+2. **Define configuration in variant.h**:
|
|
|
|
|
+ ```c
|
|
|
|
|
+ #define PWRMGT_VOLTAGE_BOOTLOCK 3300 // Won't boot below this voltage (mV)
|
|
|
|
|
+ #define PWRMGT_LPCOMP_AIN 7 // AIN channel for voltage sensing
|
|
|
|
|
+ #define PWRMGT_LPCOMP_REFSEL 2 // REFSEL (0-6=1/8..7/8, 7=ARef, 8-15=1/16..15/16)
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+3. **Implement in board .cpp file**:
|
|
|
|
|
+ ```cpp
|
|
|
|
|
+ #ifdef NRF52_POWER_MANAGEMENT
|
|
|
|
|
+ const PowerMgtConfig power_config = {
|
|
|
|
|
+ .lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
|
|
|
|
|
+ .lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
|
|
|
|
|
+ .voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ void MyBoard::initiateShutdown(uint8_t reason) {
|
|
|
|
|
+ // Board-specific shutdown preparation (e.g., disable peripherals)
|
|
|
|
|
+ bool enable_lpcomp = (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
|
|
|
|
|
+ reason == SHUTDOWN_REASON_BOOT_PROTECT);
|
|
|
|
|
+
|
|
|
|
|
+ if (enable_lpcomp) {
|
|
|
|
|
+ configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ enterSystemOff(reason);
|
|
|
|
|
+ }
|
|
|
|
|
+ #endif
|
|
|
|
|
+
|
|
|
|
|
+ void MyBoard::begin() {
|
|
|
|
|
+ NRF52Board::begin(); // or NRF52BoardDCDC::begin()
|
|
|
|
|
+ // ... board setup ...
|
|
|
|
|
+
|
|
|
|
|
+ #ifdef NRF52_POWER_MANAGEMENT
|
|
|
|
|
+ checkBootVoltage(&power_config);
|
|
|
|
|
+ #endif
|
|
|
|
|
+ }
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ For user-initiated shutdowns, `powerOff()` remains board-specific. Power management only arms LPCOMP for automated shutdown reasons (boot protection/low voltage).
|
|
|
|
|
+
|
|
|
|
|
+4. **Declare override in board .h file**:
|
|
|
|
|
+ ```cpp
|
|
|
|
|
+ #ifdef NRF52_POWER_MANAGEMENT
|
|
|
|
|
+ void initiateShutdown(uint8_t reason) override;
|
|
|
|
|
+ #endif
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+### Voltage Wake Configuration
|
|
|
|
|
+
|
|
|
|
|
+The LPCOMP (Low Power Comparator) is configured to:
|
|
|
|
|
+- Monitor the specified AIN channel (0-7 corresponding to P0.02-P0.05, P0.28-P0.31)
|
|
|
|
|
+- Compare against VDD fraction reference (REFSEL: 0-6=1/8..7/8, 7=ARef, 8-15=1/16..15/16)
|
|
|
|
|
+- Detect UP events (voltage rising above threshold)
|
|
|
|
|
+- Use 50mV hysteresis for noise immunity
|
|
|
|
|
+- Wake the device from SYSTEMOFF when triggered
|
|
|
|
|
+
|
|
|
|
|
+VBUS wake is enabled via the POWER peripheral USBDETECTED event whenever `configureVoltageWake()` is used. This requires USB VBUS to be routed to the nRF52 (typical on nRF52840 boards with native USB).
|
|
|
|
|
+
|
|
|
|
|
+**LPCOMP Reference Selection (PWRMGT_LPCOMP_REFSEL)**:
|
|
|
|
|
+| REFSEL | Fraction | VBAT @ 1M/1M divider (VDD=3.0-3.3) | VBAT @ 1.5M/1M divider (VDD=3.0-3.3) |
|
|
|
|
|
+|--------|----------|------------------------------------|--------------------------------------|
|
|
|
|
|
+| 0 | 1/8 | 0.75-0.82 V | 0.94-1.03 V |
|
|
|
|
|
+| 1 | 2/8 | 1.50-1.65 V | 1.88-2.06 V |
|
|
|
|
|
+| 2 | 3/8 | 2.25-2.47 V | 2.81-3.09 V |
|
|
|
|
|
+| 3 | 4/8 | 3.00-3.30 V | 3.75-4.12 V |
|
|
|
|
|
+| 4 | 5/8 | 3.75-4.12 V | 4.69-5.16 V |
|
|
|
|
|
+| 5 | 6/8 | 4.50-4.95 V | 5.62-6.19 V |
|
|
|
|
|
+| 6 | 7/8 | 5.25-5.77 V | 6.56-7.22 V |
|
|
|
|
|
+| 7 | ARef | - | - |
|
|
|
|
|
+| 8 | 1/16 | 0.38-0.41 V | 0.47-0.52 V |
|
|
|
|
|
+| 9 | 3/16 | 1.12-1.24 V | 1.41-1.55 V |
|
|
|
|
|
+| 10 | 5/16 | 1.88-2.06 V | 2.34-2.58 V |
|
|
|
|
|
+| 11 | 7/16 | 2.62-2.89 V | 3.28-3.61 V |
|
|
|
|
|
+| 12 | 9/16 | 3.38-3.71 V | 4.22-4.64 V |
|
|
|
|
|
+| 13 | 11/16 | 4.12-4.54 V | 5.16-5.67 V |
|
|
|
|
|
+| 14 | 13/16 | 4.88-5.36 V | 6.09-6.70 V |
|
|
|
|
|
+| 15 | 15/16 | 5.62-6.19 V | 7.03-7.73 V |
|
|
|
|
|
+
|
|
|
|
|
+**Important**: For boards with a voltage divider on the battery sense pin, LPCOMP measures the divided voltage. Use:
|
|
|
|
|
+`VBAT_threshold ≈ (VDD * fraction) * divider_scale`, where `divider_scale = (Rtop + Rbottom) / Rbottom` (e.g., 2.0 for 1M/1M, 2.5 for 1.5M/1M, 3.0 for XIAO).
|
|
|
|
|
+
|
|
|
|
|
+### SoftDevice Compatibility
|
|
|
|
|
+
|
|
|
|
|
+The power management code checks whether SoftDevice is enabled and uses the appropriate API:
|
|
|
|
|
+- When SD enabled: `sd_power_*` functions
|
|
|
|
|
+- When SD disabled: Direct register access (NRF_POWER->*)
|
|
|
|
|
+
|
|
|
|
|
+This ensures compatibility regardless of BLE stack state.
|
|
|
|
|
+
|
|
|
|
|
+## CLI Commands
|
|
|
|
|
+
|
|
|
|
|
+Power management status can be queried via the CLI:
|
|
|
|
|
+
|
|
|
|
|
+| Command | Description |
|
|
|
|
|
+|---------|-------------|
|
|
|
|
|
+| `get pwrmgt.support` | Returns "supported" or "unsupported" |
|
|
|
|
|
+| `get pwrmgt.source` | Returns current power source - "battery" or "external" (5V/USB power) |
|
|
|
|
|
+| `get pwrmgt.bootreason` | Returns reset and shutdown reason strings |
|
|
|
|
|
+| `get pwrmgt.bootmv` | Returns boot voltage in millivolts |
|
|
|
|
|
+
|
|
|
|
|
+On boards without power management enabled, all commands except `get pwrmgt.support` return:
|
|
|
|
|
+```
|
|
|
|
|
+ERROR: Power management not supported
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Debug Output
|
|
|
|
|
+
|
|
|
|
|
+When `MESH_DEBUG=1` is enabled, the power management module outputs:
|
|
|
|
|
+```
|
|
|
|
|
+DEBUG: PWRMGT: Reset = Wake from LPCOMP (0x20000); Shutdown = Low Voltage (0x4C)
|
|
|
|
|
+DEBUG: PWRMGT: Boot voltage = 3450 mV (threshold = 3300 mV)
|
|
|
|
|
+DEBUG: PWRMGT: LPCOMP wake configured (AIN7, ref=3/8 VDD)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+## Phase 2 (Planned)
|
|
|
|
|
+
|
|
|
|
|
+- Runtime voltage monitoring
|
|
|
|
|
+- Voltage state machine (Normal -> Warning -> Critical -> Shutdown)
|
|
|
|
|
+- Configurable thresholds
|
|
|
|
|
+- Load shedding callbacks for power reduction
|
|
|
|
|
+- Deep sleep integration
|
|
|
|
|
+- Scheduled wake-up
|
|
|
|
|
+- Extended sleep with periodic monitoring
|
|
|
|
|
+
|
|
|
|
|
+## References
|
|
|
|
|
+
|
|
|
|
|
+- [nRF52840 Product Specification - POWER](https://infocenter.nordicsemi.com/topic/ps_nrf52840/power.html)
|
|
|
|
|
+- [nRF52840 Product Specification - LPCOMP](https://infocenter.nordicsemi.com/topic/ps_nrf52840/lpcomp.html)
|
|
|
|
|
+- [SoftDevice S140 API - Power Management](https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.1.0/group__nrf__sdm__api.html)
|