diff --git a/src/helpers/NRF52Board.cpp b/src/helpers/NRF52Board.cpp index 17265f045..982bd1dce 100644 --- a/src/helpers/NRF52Board.cpp +++ b/src/helpers/NRF52Board.cpp @@ -116,10 +116,17 @@ bool NRF52Board::checkBootVoltage(const PowerMgtConfig* config) { // Only trigger shutdown if reading is valid (>1000mV) AND below threshold // This prevents spurious shutdowns on ADC glitches or uninitialized reads if (boot_voltage_mv > 1000 && boot_voltage_mv < config->voltage_bootlock) { - MESH_DEBUG_PRINTLN("PWRMGT: Boot voltage too low - entering protective shutdown"); + // First reading below threshold - wait for DCDC to stabilize and re-read + delay(50); + boot_voltage_mv = getBattMilliVolts(); + MESH_DEBUG_PRINTLN("PWRMGT: Boot voltage (confirmed) = %u mV (threshold = %u mV)", + boot_voltage_mv, config->voltage_bootlock); - initiateShutdown(SHUTDOWN_REASON_BOOT_PROTECT); - return false; // Should never reach this + if (boot_voltage_mv > 1000 && boot_voltage_mv < config->voltage_bootlock) { + MESH_DEBUG_PRINTLN("PWRMGT: Boot voltage too low - entering protective shutdown"); + initiateShutdown(SHUTDOWN_REASON_BOOT_PROTECT); + return false; // Should never reach this + } } return true; @@ -163,7 +170,7 @@ void NRF52Board::enterSystemOff(uint8_t reason) { NVIC_SystemReset(); } -void NRF52Board::configureVoltageWake(uint8_t ain_channel, uint8_t refsel) { +bool NRF52Board::configureVoltageWake(uint8_t ain_channel, uint8_t refsel) { // LPCOMP is not managed by SoftDevice - direct register access required // Halt and disable before reconfiguration NRF_LPCOMP->TASKS_STOP = 1; @@ -199,6 +206,14 @@ void NRF52Board::configureVoltageWake(uint8_t ain_channel, uint8_t refsel) { delayMicroseconds(50); } + // Safety: if voltage is already above threshold, UP detection will never fire + if (NRF_LPCOMP->RESULT & LPCOMP_RESULT_RESULT_Msk) { + MESH_DEBUG_PRINTLN("PWRMGT: LPCOMP shows voltage above threshold - unsafe for SYSTEMOFF"); + NRF_LPCOMP->TASKS_STOP = 1; + NRF_LPCOMP->ENABLE = LPCOMP_ENABLE_ENABLE_Disabled; + return false; + } + if (refsel == 7) { MESH_DEBUG_PRINTLN("PWRMGT: LPCOMP wake configured (AIN%d, ref=ARef)", ain_channel); } else if (refsel <= 6) { @@ -221,6 +236,8 @@ void NRF52Board::configureVoltageWake(uint8_t ain_channel, uint8_t refsel) { } MESH_DEBUG_PRINTLN("PWRMGT: VBUS wake configured"); + + return true; } #endif diff --git a/src/helpers/NRF52Board.h b/src/helpers/NRF52Board.h index 17065cf44..510d3417d 100644 --- a/src/helpers/NRF52Board.h +++ b/src/helpers/NRF52Board.h @@ -40,7 +40,7 @@ protected: bool checkBootVoltage(const PowerMgtConfig* config); void enterSystemOff(uint8_t reason); - void configureVoltageWake(uint8_t ain_channel, uint8_t refsel); + bool configureVoltageWake(uint8_t ain_channel, uint8_t refsel); virtual void initiateShutdown(uint8_t reason); #endif diff --git a/variants/heltec_t114/T114Board.cpp b/variants/heltec_t114/T114Board.cpp index c03d39afb..10fb33290 100644 --- a/variants/heltec_t114/T114Board.cpp +++ b/variants/heltec_t114/T114Board.cpp @@ -25,7 +25,9 @@ void T114Board::initiateShutdown(uint8_t reason) { digitalWrite(PIN_BAT_CTL, enable_lpcomp ? HIGH : LOW); if (enable_lpcomp) { - configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel); + if (!configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel)) { + NVIC_SystemReset(); + } } enterSystemOff(reason); diff --git a/variants/rak4631/RAK4631Board.cpp b/variants/rak4631/RAK4631Board.cpp index 9fb47b432..83c450297 100644 --- a/variants/rak4631/RAK4631Board.cpp +++ b/variants/rak4631/RAK4631Board.cpp @@ -18,7 +18,9 @@ void RAK4631Board::initiateShutdown(uint8_t reason) { if (reason == SHUTDOWN_REASON_LOW_VOLTAGE || reason == SHUTDOWN_REASON_BOOT_PROTECT) { - configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel); + if (!configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel)) { + NVIC_SystemReset(); + } } enterSystemOff(reason); diff --git a/variants/xiao_nrf52/XiaoNrf52Board.cpp b/variants/xiao_nrf52/XiaoNrf52Board.cpp index 42ee6a87f..85e02627c 100644 --- a/variants/xiao_nrf52/XiaoNrf52Board.cpp +++ b/variants/xiao_nrf52/XiaoNrf52Board.cpp @@ -22,7 +22,9 @@ void XiaoNrf52Board::initiateShutdown(uint8_t reason) { digitalWrite(VBAT_ENABLE, enable_lpcomp ? LOW : HIGH); if (enable_lpcomp) { - configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel); + if (!configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel)) { + NVIC_SystemReset(); + } } enterSystemOff(reason);