|
ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
|
Layer: L7 Application ยท Build flags: PC_ENABLE_HOTSWAP
An SD card is a connector, so it can leave while you are writing to it. What makes that dangerous is how quiet it is: the driver still reports a mounted volume, every write fails into nothing, and code that does not check the return carries on believing it has storage. Logs vanish, uploads truncate, and nothing anywhere says why.
services/hotswap turns that into a state machine with one job - never let a caller write into storage that is not there:
The contract for callers is two lines:
A single failed write is not proof a card left - it can be a transient bus error or a full volume - and tearing down a working mount over one error would be its own bug. So PC_HOTSWAP_FAIL_THRESHOLD (default 3) consecutive failures declare removal, and any success resets the run, which is what stops intermittent noise from slowly accumulating into a false removal.
Two more choices worth naming:
Mounting is the application's business, not this owner's, so it supplies three callbacks:
| Callback | Job | Optional? |
|---|---|---|
mount | SD_MMC.begin() - bring the volume up | no |
unmount | SD_MMC.end() - drop the mount and its handles | no |
present | read a card-detect GPIO | yes - nullptr lets mount decide |
If your board wires a card-detect pin, supply present: it is far cheaper than a failed mount attempt every probe interval.
| Route | What it does |
|---|---|
/storage | {"storage":"ready","mounts":1,"faults":0} for a health panel |
/write | appends a line, gated on ready() and reporting the outcome |
/yank | unmounts underneath the app, so the fault path can be watched without a card |
/yank is not a mock. It calls SD_MMC.end(), so the writes that follow really do fail at the driver - the same failures a physical removal produces.
HW-verified (2026-07-19) on an ESP32-P4 (wired Ethernet, real SD card). The full cycle:
Note the two numbers that prove the design rather than just the happy path: it faulted on the third consecutive failure (not the first), and the fourth write was refused with storage not ready instead of being attempted against a dead mount.
/yank reproduces removal as the filesystem sees it, which is the case the safeties exist for. It does not reproduce the electrical transient of pulling a card mid-DMA-burst - that needs a hand on the card. If you have the board in front of you, physically pull it during a /write loop: the expected result is identical (a run of failures, then FAULTED), and reinserting should return it to READY within PC_HOTSWAP_PROBE_MS.
| Flag | Default | Meaning |
|---|---|---|
PC_HOTSWAP_FAIL_THRESHOLD | 3 | consecutive I/O errors that declare the medium gone |
PC_HOTSWAP_PROBE_MS | 2000 | minimum gap between remount attempts while not READY |
| Board | Flash |
|---|---|
| ESP32-P4 | 735,242 B (56%) |
The flags must reach the library build, so pass them as build flags: