Storage: the SD card refuses a write about once in five 1.7 MB uploads #21
Closed
opened 2026-10-05 19:40:12 +00:00 by twisla
·
3 comments
No Branch/Tag Specified
Labels
Clear labels
area/apps
area/audio
area/build
area/cluster
area/gemini
area/gitea
area/gnss
area/ir
area/irc
area/lora
area/ota-debug
area/power
area/scripting
area/ssh
area/storage
area/ui
area/vpn
area/website
area/wifi
concern/memory
concern/security
Launcher and the apps in src/apps
Microphone, speaker, the codec, recording and playback
PlatformIO, Docker, scripts, partitions, sdkconfig
AtomS3 co-processors on Grove and the link protocol
GeminiService, the Gemini App, Saved Pages
The Gitea client: issues, releases, its TLS and its token
GnssService, the GNSS App, Tracks
The infrared LED and the IR Remote
IrcService and the IRC App
The Cap LoRa-1262 radio and the mesh
Updates, Probation, Safe Mode, Debug Console, crash reports
Battery, PowerService, sleep
Lua Apps from the SD card and their API
The SSH client and its terminal
StorageService, the SD card, Storage page
Canvas, widgets, dialogs, Toasts, fonts, keyboard
The WireGuard tunnel
The project website and its docs
WifiService, Wi-Fi Settings, Wi-Fi Tools
May push the heap towards its floors; measure on the device
TLS, signing, the debug token, trust on first use
kind
bug
Something that doesn't work as it should
kind
chore
Refactors, tooling, CI, scripts
kind
docs
README, CONTEXT, milestones, ADRs
kind
feature
Something new the device can do
priority
high
Next up
priority
low
Some day
priority
medium
Soon
status
blocked
Waiting on something else
status
needs-design
Needs a question round (Qnn) before code
status
ready
Designed; can be started
Milestone
No items
No Milestone
S1 System basics
Assignees
twisla (Clément Martin)
Clear assignees
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: twisla/roro9stack#21
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What happens
The SD card now and then refuses a write: about once in five 1.7 MB uploads over the Debug Console (
rdbg.py put), with the LoRa radio listening or asleep. The file's write fails partway (put: write failed at <offset>, retry 1on the console).Since M3 the upload notices: a retry that finds the card lost earlier data gives up, and the finished file is read back and its SHA-256 compared before it's renamed. Before that fix, the retry extended the file with zeros and reported success (3,072 bytes of zeros, twice).
The refusal itself is not explained, and other writers don't check. Logs, Tracks, Gemini pages streamed to the cache, Saved Pages, Captures and Update Files installed from the card all write through FATFS the same way. A refused write there is either dropped silently or, for an Update File, caught only by its signature check.
Measured (M3, 2026-10-05)
src/services/storage_service.cpp,sdcard_init(..., 20000000)).What's known
Questions
sd list, Settings > Storage, the System Monitor in #11)?Related
src/services/debug_console.cpp(put),lib/ota/src/file_receiver.cpp(cardChecked),src/services/storage_service.cpp,docs/milestones/M3.md(step 3), #1 (USB drive), #3 (Files).Cause found and fixed on the
s1branch (3f2650c, ADR 0007). It was never the card, the bus speed or the radio: it's the SD driver that ships with Arduino-ESP32.What was measured
lib/SD,sd_fault.h): 4 failures in 12 uploads, all at the same step. Every data block was accepted, the write was ended with Stop Tran, and the status check (CMD13) then read 0xFF or 0x1F.Why
After Stop Tran a card takes about a byte of clock to signal busy. The driver deselects, selects again and reads one byte to test for ready; read before the card has raised busy, that byte is 0xFF, "ready", and CMD13 goes out while the card is still programming. Its garbled answer is taken for an error, and FATFS is told the write failed. ChaN's reference driver sends a dummy byte after selecting the card for this reason.
The fix
A dummy byte after select, before the ready test, and one after Stop Tran. Since then: 30 uploads of 1.7 MB in a row, each read back by SHA-256, ten with the radio listening: 0 faults.
Also in the change
infoshows the driver's write faults since boot;putprints the step and the card's answer if one happens.Left alone, on purpose
The driver also tests the card's answer to a data block against 0x0A and 0x0C, values it can't take (0x05 accepted, 0x0B CRC error, 0x0D write error), so a block rejected for a CRC error is never resent. None of the failures here was that, and nothing exercises that path, so it's documented in ADR 0007 rather than changed blind. Both defects are worth reporting to Arduino-ESP32.
To close when
s1is merged.Reported upstream: https://github.com/espressif/arduino-esp32/issues/12970. The follow-up (answering the maintainers, keeping
lib/SDin step with the framework, dropping it once fixed) is #39. The card, read with the newsd cardcommand: a Samsung 8 GB SDHC from June 2013.Fixed in v0.6.1 (
s1merged intomain). The upstream report and our copy of the driver are followed in #39.