Skip to content

LilyGo T-Echo (nRF52840 / SX1262, lilygo_techo): corrupted external LittleFS hangs the node during boot #3401

Description

@aluminique

What I observed

A T-Echo running LilyGo_T-Echo_companion_radio_ble stopped on "Loading..." and stayed there. Reflashing the same firmware did not help: UF2 rewrites only the application region, so the filesystem survives.

Over the last day and a half of a five-day charge the BLE link to the companion dropped at least four times; after the last drop the node was in that state. I cannot say what those reboots were - the Arduino core reads and clears RESETREAS in init() (wiring.c) before setup() runs, so no reset-cause evidence was available.

What I established

Instrumented boot, after which the node recovered and has stayed up since:

Filesystem mounted
BG diag (post-fs): RESETREAS=0x00000000(POR) GPREG2=0x00 RAM=ok/0x08 src=ram
BootGuard repair: fmt: ext key kept
BootGuard: POR reset in MESH try 1 +fmt-ext

The POR label there is meaningless for the reason above. Stage 8 is the_mesh.begin(), which reads prefs and contacts from the external QSPI flash. Formatting that filesystem alone brought the node back; the internal flash was intact, so the private key and advert name survived and the contacts and channels did not.

Why the node hangs instead of reporting an error:

  • lfs_mount() is straight-line code, so the existing "format when the mount fails" recovery in InternalFileSystem::begin() and CustomLFS_QSPIFlash::begin() never runs - the mount succeeds, and the damage is only reached later, while reading files.
  • littlefs v1 has no cycle detection walking the metadata tail chain, so reading those files becomes an infinite loop.
  • nrf52_base builds with -D LFS_NO_ASSERT=1 and PlatformIO defines NDEBUG, so LFS_ASSERT and assert() both expand to nothing and littlefs reports nothing.

I have not established what corrupted the filesystem in the first place.

Related gap

lilygo_techo does not enable NRF52_POWER_MANAGEMENT; docs/nrf52_power_management.md lists it as not implemented. AUTO_SHUTDOWN_MILLIVOLTS is the only low-battery handling on this variant, and it samples once every 8 seconds. #1572 describes the boot lockout as existing to prevent flash corruption before the flash is initialised.

Branches

Two independent branches in a fork, both building on all five T-Echo environments. Not opened as PRs here yet.

The power management branch is on field test now. What I am trying to establish is not that it powers the node down, but whether doing so actually prevents the corruption. I will report the outcome either way.

Questions

  1. Is porting Phase 1 to lilygo_techo the right path here, or is Phase 2 runtime monitoring the intended answer?
  2. Is boot-time recovery of an already damaged filesystem the right path at all, or is some other approach preferred?

I can open PRs, split them differently, or drop either.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions