fix(firmware): route SPI2 MISO to GPIO35 so the SD card mounts#575
Conversation
#552 added the per-transaction output-enable flip on GPIO35 (shared LCD DC / SD MISO pin) but never connected SPI2's FSPIQ input signal to the pin, so the peripheral read an unconnected input (0x00) and embedded-sdmmc spun in its CMD0 loop until CardInit failed. Make GPIO35 a Flex with its input buffer live and route FSPIQ to it via InputSignal::connect_to; the sd_spi OE flip still hands the line to the card during reads.
Greptile SummaryThis PR fixes a missing half of the GPIO35 dual-purpose pin setup that caused SD card initialisation to fail.
Confidence Score: 5/5Safe to merge — the change is a focused, well-understood hardware fix with on-device confirmation that both the LCD and SD card work correctly after it. The fix is minimal and surgical: one pin type change, one InputSignal routing call, a type alias update, and a doc rewrite. The root cause is clearly explained, the on-device test plan covers both affected peripherals (LCD still renders, SD now mounts), and the Flex / InputSignal::FSPIQ approach is the supported esp-hal surface. No logic in the OE-flip path changed. No files require special attention. Important Files Changed
Reviews (1): Last reviewed commit: "fix(firmware): route SPI2 MISO to GPIO35..." | Re-trigger Greptile |
🤖 I have created a release *beep* *boop* --- <details><summary>stackchan-firmware: 0.113.2</summary> ## [0.113.2](stackchan-firmware-v0.113.1...stackchan-firmware-v0.113.2) (2026-05-29) ### Bug Fixes * **firmware:** route SPI2 MISO to GPIO35 so the SD card mounts ([#575](#575)) ([791341e](791341e)) </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>
…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
FSPIQ(MISO) input signal to the pin in the GPIO matrix. The peripheral therefore read an unconnected input (0x00),embedded-sdmmcspun in itsCMD0retry loop, and the card init failed withCardInit— the SD never mounted.Flexwith its input buffer kept live, and routeFSPIQto it via the supportedInputSignal::FSPIQ.connect_to(&dc).sd_spi's OE flip still hands the line to the card during reads. Both halves (OE flip + MISO route) are now present; updated thesd_spimodule doc and theLcdDisplaytype alias accordingly.Test plan
just check-firmware— clean (exit 0).just clippy-firmware(-D warnings) — clean (exit 0).--releaseand watched the defmt boot log:Got response: 0retries: 51 → 1 (one normal init retry, then success).SD: mount failed (CardInit)— gone.SD: read /sd/STACKCHAN.RON failed (FileNotFound); using defaults(card mounts; config file simply absent on the blank card),runtime store: ... seeding from boot config,ble: bonds: 0 persisted bond(s) registered(was "no SD mounted; bonds disabled").ILI9342C ready+render task: 33 ms tick+boot complete— LCD still renders fine through theFlexDC pin; no panic.Greptile: please review.