fix(firmware): load STACKCHAN.RON via long-filename lookup#577
Conversation
"STACKCHAN" is a 9-char base name, which is not a valid FAT 8.3 short name, so embedded-sdmmc's open_file_in_dir rejected "STACKCHAN.RON" with NameTooLong — masked as FileNotFound — and the boot config never loaded even though the file was on the card (short name STACKC~1.RON + an LFN entry). Resolve the short name by matching the long name via iterate_dir_lfn, then open by that.
🤖 I have created a release *beep* *boop* --- <details><summary>stackchan-firmware: 0.113.3</summary> ## [0.113.3](stackchan-firmware-v0.113.2...stackchan-firmware-v0.113.3) (2026-05-29) ### Bug Fixes * **firmware:** load STACKCHAN.RON via long-filename lookup ([#577](#577)) ([a7e1176](a7e1176)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: release-kun[bot] <276042328+release-kun[bot]@users.noreply.github.com>
Greptile SummaryThis PR fixes the long-standing silent boot failure where
Confidence Score: 3/5The read-config fix is correct and on-device tested, but The crates/stackchan-firmware/src/storage.rs — specifically the Important Files Changed
|
…rite (#579) ## Summary Completes the SD config feature: it could mount (#575) and read (#577) but not save. `PUT /settings` writeback was broken the same way the read path was — the staging file `STACKCHAN.NEW` (9-char base) couldn't be *created* by embedded-sdmmc, and the final copy targeted the un-creatable `STACKCHAN.RON`. embedded-sdmmc cannot create long-named files at all, but it **can overwrite an existing file opened by its short name**. So: - Stage to a valid 8.3 name (`STKCFG.NEW`) the firmware can create. - Resolve the existing `STACKCHAN.RON` short name via the shared `lfn_short_name` helper (factored out of the read path). - Truncate-write the rendered config onto it — which leaves the long-name directory entry intact, so the file stays readable as `STACKCHAN.RON` next boot. Writeback updates an **existing** config (the realistic lifecycle — the file must already be present for Wi-Fi/auth to come up). If `STACKCHAN.RON` is absent, `write_config` returns `FileNotFound` with a clear log rather than silently writing a differently-named file. ## Test plan - `just clippy-firmware` (`-D warnings`) — clean. - **On-device (CoreS3, real `STACKCHAN.RON` on the card):** a temporary idempotent self-test (rewrite the just-read config, then re-read) — removed before commit — logged: - `dbg writeback: write_config OK` - `dbg writeback: re-read OK ssid=Interweb hostname=stackchan` — round-trip intact, long name preserved. ## Surfaced by config now loading (separate, not addressed here) - `sidecar session: persist failed (Write)` — a different persisted file; needs its own look. - `wifi: start_async failed (InternalError(NoMem))` — Wi-Fi now actually starts (there's an SSID); a pre-existing init path that was never exercised while config never loaded. Greptile: please review.
… pool sizing (#581) ## Summary Once a real `STACKCHAN.RON` loaded (after #575/#577), Wi-Fi never came up — `start_async` failed with `InternalError(NoMem)`. This fixes the bring-up end to end. **Root cause (measured on-device):** only **~1.5 KiB** of internal SRAM was free when the Wi-Fi MAC started. PSRAM (8 MiB free) can't back Wi-Fi DMA buffers; the bootloader-reclaimed heap is hard-capped at **~72 KiB** (already full); and the only other internal heap shares the DRAM segment with the **stack** (growing it overflowed the stack in the BLE+Wi-Fi coex path). **Fix 1 — BLE/Wi-Fi mutual exclusion.** With a Wi-Fi SSID configured, skip BLE bring-up entirely. Frees **~36 KiB** internal (1.5 KiB → 37 KiB) for the Wi-Fi stack and removes coex stack pressure. BLE (Hardware Buddy) still runs when no SSID is set, so provisioning over BLE is unaffected. **Fix 2 — socket pool.** Wi-Fi connecting then exposed a second latent bug: `STACK_SOCKETS` was 6, predating the 4-worker HTTP pool, so `smoltcp` panicked (`adding a socket to a full SocketSet`) the instant the link came up. Sized to real demand (`HTTP_WORKER_COUNT` + mDNS + SNTP + DHCP/DNS + optional outbound clients). Also reflows one `write_config` line that merged slightly un-formatted in #579. ## Test plan - `just clippy-firmware` (`-D warnings`) — clean. - **On-device (CoreS3, `STACKCHAN.RON` with `ssid=Interweb`):** flashed `--release`; defmt log shows: - `ble: skipped — Wi-Fi SSID configured` and free internal **37 KiB** before start (was 1.5 KiB). - `wifi: connecting → wifi: connected`, HTTP workers listening, **DHCP lease acquired**, and `sntp: synced via pool.ntp.org` — i.e. full internet reachability. - **Boots once, no reboot loop;** zero `NoMem`, stack-guard, or `SocketSet` panics (all three were reproduced before the fix). ## Follow-ups (noted, out of scope) - `coex` feature is now dead weight when an SSID is set (BLE never co-runs); dropping it would reclaim more internal RAM and could be revisited. - `sidecar session: persist failed (Write)` (separate file) and the BLE-only path's behavior are unchanged here. Greptile: please review.
Summary
STACKCHANis a 9-character base name, which is not a valid FAT 8.3 short name.embedded-sdmmc'sopen_file_in_dironly accepts 8.3 names, so it rejected"STACKCHAN.RON"withFilenameError(NameTooLong)— whichread_configmasked asFileNotFound. Boot config silently never loaded, even with the file present on the card (stored as short nameSTACKC~1.RON+ a long-filename entry, as any OS creates it).iterate_dir_lfn, then open by that short name. Preserves the documented/sd/STACKCHAN.RONpath and existing cards.Test plan
just clippy-firmware(-D warnings) — clean.STACKCHAN.RONon the card): flashed--release; boot log went fromSD: read /sd/STACKCHAN.RON failed (FileNotFound)tonet config: ssid=Interweb country=US hostname=stackchan.local— the 241-byte config now parses and applies. Clean boot, LCD renders.Known follow-ups (same root cause, out of scope here)
PUT /settings, atomicSTACKCHAN.NEW→STACKCHAN.RON): embedded-sdmmc cannot create long-named files, so writeback to the 9-char-base name is still impossible. Needs a separate decision (8.3 staging name, or rename).WAKE_WORD.tflitehas the same long-name (and >3-char extension) issue on the read path.Greptile: please review.