diff --git a/chat-summaries/2026-03-09_06-00-summary.md b/chat-summaries/2026-03-09_06-00-summary.md new file mode 100644 index 00000000..c551db52 --- /dev/null +++ b/chat-summaries/2026-03-09_06-00-summary.md @@ -0,0 +1,28 @@ +# Fix Idle Freeze: NTP Power Lock and Clock Refresh Hardening + +**Date**: 2026-03-09 + +## Task Description + +Fix device freeze during idle, where the device stops responding to button presses after idling on the Home screen and requires a hard reset. Root cause was the mod-specific clock refresh logic in the main loop triggering a display render while the CPU is at reduced frequency (10 MHz low-power mode), combined with the background BootNtpSync task running WiFi/NTP operations without holding a power lock. + +## Root Cause + +The freeze coincides with the clock minute boundary. The mod's clock refresh code detects the minute change and calls `activityManager.requestUpdate()`, triggering a Home screen render while the CPU is at 10 MHz. SPI display operations at reduced APB frequency can deadlock the display communication. Additionally, `BootNtpSync` runs WiFi/NTP on a background task with no power lock, risking instability during WiFi teardown when the main loop may enter low-power mode. + +## Changes Made + +### 1. `src/util/BootNtpSync.cpp` +- Added `#include ` +- Added `HalPowerManager::Lock powerLock;` at the top of `taskFunc()` to keep the CPU at full speed for the entire duration of WiFi scanning, connection, NTP sync, and teardown + +### 2. `src/main.cpp` (clock refresh block, ~lines 408-428) +- In the `sawInvalidTime` branch: added `lastActivityTime = millis()` and `powerManager.setPowerSaving(false)` before calling `requestUpdate()` +- In the minute-change branch: added `lastActivityTime = millis()` and `powerManager.setPowerSaving(false)` before calling `requestUpdate()` +- This ensures the CPU is restored to 160 MHz before any render-related code executes and prevents immediate re-entry into low-power mode + +## Follow-up Items + +- Verify on device that the freeze no longer occurs after idling for extended periods +- Monitor heap usage to confirm the power lock doesn't introduce memory issues +- Test that NTP sync still completes successfully with the power lock in place diff --git a/src/main.cpp b/src/main.cpp index 0924681f..110e95d7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -416,9 +416,13 @@ void loop() { if (lastRenderedMinute < 0) { lastRenderedMinute = currentMinute; if (sawInvalidTime) { + lastActivityTime = millis(); + powerManager.setPowerSaving(false); activityManager.requestUpdate(); } } else if (currentMinute != lastRenderedMinute) { + lastActivityTime = millis(); + powerManager.setPowerSaving(false); activityManager.requestUpdate(); lastRenderedMinute = currentMinute; } diff --git a/src/util/BootNtpSync.cpp b/src/util/BootNtpSync.cpp index c4627201..61ef904c 100644 --- a/src/util/BootNtpSync.cpp +++ b/src/util/BootNtpSync.cpp @@ -10,6 +10,7 @@ #include "CrossPointSettings.h" #include "WifiCredentialStore.h" +#include #include "util/TimeSync.h" namespace BootNtpSync { @@ -93,6 +94,7 @@ static bool tryConnectToSavedNetwork(const TaskParams& params) { } static void taskFunc(void* param) { + HalPowerManager::Lock powerLock; auto* params = static_cast(param); bool connected = tryConnectToSavedNetwork(*params);