feat: silent-restart defrag on section-build double failure + BLE debug flags

- EpubReaderActivity: when a section build fails even after the BLE
  teardown/retry, silentRestartToReader() as last-resort heap defrag,
  guarded by bootWasSilentRestart() to prevent reboot loops
- main/SilentRestart.h: expose bootWasSilentRestart()
- platformio.ini: enable FREEINK_BLE_HID_REPORT_DEBUG in env:default
This commit is contained in:
Nick
2026-07-02 17:20:51 -05:00
committed by Nick McCarthy
parent c463da994e
commit 06aa1ac2f7
4 changed files with 23 additions and 0 deletions
+4
View File
@@ -6,3 +6,7 @@
void silentRestart(); // home screen
void silentRestartToReader(); // currently-open EPUB (APP_STATE.openEpubPath)
// True when this boot itself came from a silent restart. Callers that restart
// as a last-resort defrag must check this so a failure that survives the
// restart degrades to an error instead of a reboot loop.
bool bootWasSilentRestart();
@@ -33,6 +33,7 @@
#include "QrDisplayActivity.h"
#include "ReaderUtils.h"
#include "RecentBooksStore.h"
#include "SilentRestart.h"
#include "components/UITheme.h"
#include "fontIds.h"
#include "util/BookmarkUtil.h"
@@ -883,6 +884,16 @@ void EpubReaderActivity::render(RenderLock&& lock) {
bleinput::showConnectingUntilLinked(renderer, mappedInput);
requestGhostCleanup();
}
if (!built && !bootWasSilentRestart()) {
// Even with BLE freed, the build can fail when this session's parse churn has
// fragmented the heap beyond in-place recovery. A silent restart is the only
// real defrag on this heap (no compaction); it resumes into this book and
// rebuilds the section on a fresh heap. Guarded by bootWasSilentRestart() so a
// build that fails again after the restart degrades to the error popup below
// instead of reboot-looping.
LOG_ERR("ERS", "Section build failed after BLE recovery; silent restart to defrag heap");
silentRestartToReader();
}
if (!built) {
LOG_ERR("ERS", "Failed to persist page data to SD");
section.reset();
+7
View File
@@ -128,6 +128,12 @@ enum class BootResume : uint8_t {
QuickResume, // wake from a quick-resume deep sleep (SD flag; survives power loss)
};
// Latched in setup() from the read-and-clear of the RTC flag, so the reboot-loop
// guard in bootWasSilentRestart() has the answer for the whole session.
static bool bootWasSilentRestartFlag = false;
bool bootWasSilentRestart() { return bootWasSilentRestartFlag; }
// Latched true once enterDeepSleep() commits to sleeping, before it tears down
// the current activity. WiFi activities call silentRestart() in onExit() to
// clear heap fragmentation on the way out, but deep sleep is a full chip reset
@@ -330,6 +336,7 @@ void setup() {
(isSilentReboot && silentRebootTarget <= SILENT_REBOOT_TARGET_READER) ? silentRebootTarget : 0;
silentRebootMagic = 0;
silentRebootTarget = 0;
bootWasSilentRestartFlag = isSilentReboot;
gpio.begin();
powerManager.begin();