Fix rak_wismeshtag low‑voltage reboot hang after App configuration (#9897)

* Fix TAG low‑voltage reboot hang after App configuration

* nRF52: Move low-VDD System OFF logic to variant hook

* Addressed review

* serialize SAADC access with shared mutex for VDD and battery reads

* raise LPCOMP wake threshold to ensure rising-edge wake

* Trunk fmt

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
This commit is contained in:
Ethac.chen
2026-03-27 06:56:19 -05:00
committed by GitHub
co-authored by GitHub Ben Meadors
parent 33e7f16c05
commit c36ae159ed
6 changed files with 129 additions and 6 deletions
@@ -19,7 +19,11 @@
*/
#include "variant.h"
#include "Arduino.h"
#include "FreeRTOS.h"
#include "nrf.h"
#include "power/PowerHAL.h"
#include "sleep.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
@@ -40,3 +44,39 @@ void initVariant()
pinMode(PIN_3V3_EN, OUTPUT);
digitalWrite(PIN_3V3_EN, HIGH);
}
#ifdef LOW_VDD_SYSTEMOFF_DELAY_MS
void variant_nrf52LoopHook(void)
{
// If VDD stays unsafe for a while (brownout), force System OFF.
// Skip when VBUS present to allow recovery while USB-powered.
if (!powerHAL_isVBUSConnected()) {
// Rate-limit VDD safety checks: powerHAL_isPowerLevelSafe() calls getVDDVoltage() each time.
static constexpr uint32_t POWER_LEVEL_CHECK_INTERVAL_MS = 100;
static uint32_t last_vdd_check_ms = 0;
static bool last_power_level_safe = true;
const uint32_t now = millis();
if (last_vdd_check_ms == 0 || (uint32_t)(now - last_vdd_check_ms) >= POWER_LEVEL_CHECK_INTERVAL_MS) {
last_vdd_check_ms = now;
last_power_level_safe = powerHAL_isPowerLevelSafe();
}
// Do not use millis()==0 as a sentinel: at boot, millis() may be 0 while VDD is unsafe.
static bool low_vdd_timer_armed = false;
static uint32_t low_vdd_since_ms = 0;
if (!last_power_level_safe) {
if (!low_vdd_timer_armed) {
low_vdd_since_ms = now;
low_vdd_timer_armed = true;
}
if ((uint32_t)(now - low_vdd_since_ms) >= (uint32_t)LOW_VDD_SYSTEMOFF_DELAY_MS) {
cpuDeepSleep(portMAX_DELAY);
}
} else {
low_vdd_timer_armed = false;
}
}
}
#endif
+35 -1
View File
@@ -225,7 +225,41 @@ SO GPIO 39/TXEN MAY NOT BE DEFINED FOR SUCCESSFUL OPERATION OF THE SX1262 - TG
#define AREF_VOLTAGE 3.0
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER 1.73
#define OCV_ARRAY 4240, 4112, 4029, 3970, 3906, 3846, 3824, 3802, 3776, 3650, 3072
#define OCV_ARRAY 4160, 4020, 3940, 3870, 3810, 3760, 3740, 3720, 3680, 3620, 2990 // updated OCV array for rak_wismeshtag
// Wake from System OFF when battery rises again (LPCOMP).
// BAT_ADC divider: R22=1M (top), R24=1.5M (bottom) => V_BAT_ADC = VBAT * (1.5 / (1.0 + 1.5)) = 0.6 * VBAT
// RAK4630 module: AIN0 = nrf52840 AIN3 = Pin 5 (A0/BATTERY_PIN)
#define BATTERY_LPCOMP_INPUT NRF_LPCOMP_INPUT_3
// LPCOMP compares the selected input to a fraction of VDD (here 5/8 of VDD at the LPCOMP input).
// With VDD ≈ 3.3 V: threshold at input ≈ (5/8) * 3.3 V ≈ 2.06 V.
// BAT_ADC divider: V_BAT_ADC = 0.6 * VBAT → equivalent VBAT ≈ 2.06 / 0.6 ≈ 3.4 V (wake when battery recovers).
//
// Note: if VDD is drooping/tracking VBAT in the low-voltage region, using a fraction >= divider ratio helps ensure the
// input is below the threshold at shutdown; the intended wake event happens when the supply recovers enough for a rising
// crossing to occur.
#define BATTERY_LPCOMP_THRESHOLD NRF_LPCOMP_REF_SUPPLY_5_8
// Low voltage protection:
// If VDD is below SAFE_VDD_VOLTAGE_THRESHOLD for longer than this delay (and no USB VBUS),
// the device will enter System OFF to avoid brownout loops and flash corruption.
#ifndef LOW_VDD_SYSTEMOFF_DELAY_MS
#define LOW_VDD_SYSTEMOFF_DELAY_MS 5000
#endif
// Prefer integer mV so platform code avoids float→int truncation quirks (e.g. 0.1 V → 99 vs 100 mV).
#ifndef SAFE_VDD_VOLTAGE_THRESHOLD_MV
#define SAFE_VDD_VOLTAGE_THRESHOLD_MV 2900
#endif
#ifndef SAFE_VDD_VOLTAGE_THRESHOLD_HYST_MV
#define SAFE_VDD_VOLTAGE_THRESHOLD_HYST_MV 100
#endif
#ifndef SAFE_VDD_VOLTAGE_THRESHOLD
#define SAFE_VDD_VOLTAGE_THRESHOLD (SAFE_VDD_VOLTAGE_THRESHOLD_MV / 1000.0f)
#endif
#ifndef SAFE_VDD_VOLTAGE_THRESHOLD_HYST
#define SAFE_VDD_VOLTAGE_THRESHOLD_HYST (SAFE_VDD_VOLTAGE_THRESHOLD_HYST_MV / 1000.0f)
#endif
#define RAK_4631 1