You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add persistent store-and-forward to the FreeRTOS demo by introducing a FatFs–backed SolidSyslogFile, so the existing SolidSyslogFileBlockDevice / SolidSyslogBlockStore ecosystem runs unchanged on the QEMU target with messages surviving an oracle outage and a power cycle.
Why FatFs (ChaN), not FreeRTOS-Plus-FAT: FatFs is the de facto embedded filesystem — used by Zephyr, NuttX, MicroPython, CircuitPython, STM32 HAL, ESP-IDF, the Arduino SD ecosystem. FreeRTOS-Plus-FAT is an AWS Lab project, untagged, AWS-tied. For a library aimed at the broader embedded market, FatFs is what integrators already have. FatFs's disk I/O port (diskio.c) is a minimal 4-function interface — disk_initialize / disk_read / disk_write / disk_ioctl — which makes the QEMU storage substrate simpler than Plus-FAT's media-driver vtable.
New public surface:
Platform/FatFs/Interface/SolidSyslogFatFsFile.h — FatFs-backed implementation of the SolidSyslogFile extension point. Mirrors SolidSyslogPosixFile.h / SolidSyslogWindowsFile.h.
Platform/FatFs/Source/SolidSyslogFatFsFile.c — implementation against the FatFs API (f_open / f_close / f_read / f_write / f_lseek / f_size / f_truncate / f_stat / f_unlink).
Why a new Platform/FatFs/ platform pack, not under Platform/FreeRtos/: FatFs is filesystem-agnostic to the RTOS — it runs on bare-metal, FreeRTOS, Zephyr, NuttX, anywhere. A new Platform/FatFs/ is the right home, peer to Platform/Posix/, Platform/Windows/, Platform/FreeRtos/, Platform/OpenSsl/. Reusable by any integrator who picks FatFs.
Prerequisite — out-of-channel container bump
Story #270 depends on FatFs sources being present in the cpputest-freertos and cpputest-freertos-cross images at $FATFS_PATH (proposed /opt/fatfs). That change lives in the CppUTestFreertosDocker repo and must land first as a separate chore: bump container image to <sha> PR per docs/containers.md. Pin FatFs to R0.15 (current stable) by tarball SHA-256.
QEMU storage substrate
mps2-an385 has no built-in mass-storage device. Proposal: write a small semihosting-backed FatFs diskio.c (host-file-as-disk-image) and mount FatFs on top of it. Each disk_read / disk_write routes through SYS_READ / SYS_WRITE to a host-resident image file, giving continuous byte-for-byte persistence across QEMU restart and surviving an unannounced kill — the prerequisite for power_cycle_replay.feature. The semihosting diskio.c lives in BDD-target glue (Bdd/Targets/FreeRtos/SemihostingDiskIo.c), not in Platform/FatFs/ — production integrators supply their own flash / SD / eMMC diskio.c.
FatFs also needs OS glue (ffsystem.c) when FF_FS_REENTRANT=1. On the BDD target this wraps FreeRTOS mutexes; on host TDD we set FF_FS_REENTRANT=0 and the OS glue is a no-op. ffconf.h is per-consumer per the header-configured platform pattern (see CLAUDE.md and the project_header_configured_platforms memory).
Final storage shape locked at the slice-5 review gate.
Slicing (8 slices, one PR, one commit per slice)
#
Slice
Commit
Review gate
1
Plumb FatFs into the host TDD build + smoke test
chore: S08.05 slice 1 plumb FatFs host TDD build
CMake wiring, host-side diskio.c (RAM-disk in Tests/Support/FatFsFakes/)
Slices 1-4 land via build-freertos-host-tdd CI. Slices 5-8 land via bdd-freertos-qemu. The PR opens after slice 1 and gets force-updated as slices land; CI runs the full matrix on every push.
The discard-policy trap (slice 8)
max-block-size 520 in store_capacity.feature is sized for Linux / Windows (MAX=2048 → clamped up to ~2057). On FreeRTOS with MAX=512 the clamp lands at ~521, essentially unchanged. Combined with the message-body sizing SOLIDSYSLOG_MAX_MESSAGE_SIZE // 5 - 50 in syslog_steps.py (≈52 chars on FreeRTOS vs ≈359 on Linux), per-block record packing shifts dramatically. First action in slice 8 is a diagnostic print of actual per-record bytes and per-block packing on FreeRTOS — assertions follow the measurement, not a guess.
Acceptance criteria — BDD scenarios pass against QEMU
store_and_forward.feature — messages delivered after sender outage.
power_cycle_replay.feature — stored messages replayed after restart.
store_capacity.feature — overflow / discard-oldest / discard-newest / halt policies.
Platform/FatFs/ platform pack (peer to Posix / Windows / FreeRtos / OpenSsl) added.
CLAUDE.md "Public header audiences" — new row.
DEVLOG entry noting FatFs ChaN-license compatibility with PolyForm Noncommercial 1.0.0 (permissive component flowing into more-restrictive parent — only obligation is preserving ChaN's notice in ff.c, which is untouched).
Cross-cuts
E05 E05: Store and Forward #7Store and Forward — this story adds a FatFs-backed SolidSyslogFile to the existing file / block-device / store stack rather than reinventing it.
Container bump in CppUTestFreertosDocker must land first (separate PR, separate repo).
Parent epic: #10 (E08: RTOS Examples)
Scope
Add persistent store-and-forward to the FreeRTOS demo by introducing a FatFs–backed
SolidSyslogFile, so the existingSolidSyslogFileBlockDevice/SolidSyslogBlockStoreecosystem runs unchanged on the QEMU target with messages surviving an oracle outage and a power cycle.Why FatFs (ChaN), not FreeRTOS-Plus-FAT: FatFs is the de facto embedded filesystem — used by Zephyr, NuttX, MicroPython, CircuitPython, STM32 HAL, ESP-IDF, the Arduino SD ecosystem. FreeRTOS-Plus-FAT is an AWS Lab project, untagged, AWS-tied. For a library aimed at the broader embedded market, FatFs is what integrators already have. FatFs's disk I/O port (
diskio.c) is a minimal 4-function interface —disk_initialize/disk_read/disk_write/disk_ioctl— which makes the QEMU storage substrate simpler than Plus-FAT's media-driver vtable.New public surface:
Platform/FatFs/Interface/SolidSyslogFatFsFile.h— FatFs-backed implementation of theSolidSyslogFileextension point. MirrorsSolidSyslogPosixFile.h/SolidSyslogWindowsFile.h.Platform/FatFs/Source/SolidSyslogFatFsFile.c— implementation against the FatFs API (f_open/f_close/f_read/f_write/f_lseek/f_size/f_truncate/f_stat/f_unlink).Why a new
Platform/FatFs/platform pack, not underPlatform/FreeRtos/: FatFs is filesystem-agnostic to the RTOS — it runs on bare-metal, FreeRTOS, Zephyr, NuttX, anywhere. A newPlatform/FatFs/is the right home, peer toPlatform/Posix/,Platform/Windows/,Platform/FreeRtos/,Platform/OpenSsl/. Reusable by any integrator who picks FatFs.Prerequisite — out-of-channel container bump
Story #270 depends on FatFs sources being present in the
cpputest-freertosandcpputest-freertos-crossimages at$FATFS_PATH(proposed/opt/fatfs). That change lives in theCppUTestFreertosDockerrepo and must land first as a separatechore: bump container image to <sha>PR per docs/containers.md. Pin FatFs to R0.15 (current stable) by tarball SHA-256.QEMU storage substrate
mps2-an385 has no built-in mass-storage device. Proposal: write a small semihosting-backed FatFs
diskio.c(host-file-as-disk-image) and mount FatFs on top of it. Eachdisk_read/disk_writeroutes throughSYS_READ/SYS_WRITEto a host-resident image file, giving continuous byte-for-byte persistence across QEMU restart and surviving an unannouncedkill— the prerequisite forpower_cycle_replay.feature. The semihostingdiskio.clives in BDD-target glue (Bdd/Targets/FreeRtos/SemihostingDiskIo.c), not inPlatform/FatFs/— production integrators supply their own flash / SD / eMMCdiskio.c.FatFs also needs OS glue (
ffsystem.c) whenFF_FS_REENTRANT=1. On the BDD target this wraps FreeRTOS mutexes; on host TDD we setFF_FS_REENTRANT=0and the OS glue is a no-op.ffconf.his per-consumer per the header-configured platform pattern (see CLAUDE.md and theproject_header_configured_platformsmemory).Final storage shape locked at the slice-5 review gate.
Slicing (8 slices, one PR, one commit per slice)
chore: S08.05 slice 1 plumb FatFs host TDD builddiskio.c(RAM-disk inTests/Support/FatFsFakes/)SolidSyslogFatFsFile— Create/Destroy + Open/Close/IsOpenfeat: S08.05 slice 2 SolidSyslogFatFsFile Create + Open/Closef_openmode flagsfeat: S08.05 slice 3 FatFsFile Read/Write/Seek/Size/Truncatefeat: S08.05 slice 4 FatFsFile Exists/Deletef_stat/f_unlinkerror returnsdiskio.c+ FreeRTOSffsystem.c+ BDD target wires BlockStorefeat: S08.05 slice 5 QEMU diskio + BlockStore wiring for FreeRTOS BDD targetdiskio.cdesign + FreeRTOS-mutexffsystem.c+settranslations for--store/--max-blocks/--max-block-size/--discard-policy/--message/--halt-exitstore_and_forward.featuregreen on QEMUfeat: S08.05 slice 6 store_and_forward feature green on FreeRTOS QEMUpower_cycle_replay.featuregreen on QEMUfeat: S08.05 slice 7 power_cycle_replay feature green on FreeRTOS QEMUstore_capacity.feature— all 4 scenarios green on QEMUfeat: S08.05 slice 8 store_capacity feature green on FreeRTOS QEMUSlices 1-4 land via
build-freertos-host-tddCI. Slices 5-8 land viabdd-freertos-qemu. The PR opens after slice 1 and gets force-updated as slices land; CI runs the full matrix on every push.The discard-policy trap (slice 8)
max-block-size 520instore_capacity.featureis sized for Linux / Windows (MAX=2048 → clamped up to ~2057). On FreeRTOS with MAX=512 the clamp lands at ~521, essentially unchanged. Combined with the message-body sizingSOLIDSYSLOG_MAX_MESSAGE_SIZE // 5 - 50insyslog_steps.py(≈52 chars on FreeRTOS vs ≈359 on Linux), per-block record packing shifts dramatically. First action in slice 8 is a diagnostic print of actual per-record bytes and per-block packing on FreeRTOS — assertions follow the measurement, not a guess.Acceptance criteria — BDD scenarios pass against QEMU
store_and_forward.feature— messages delivered after sender outage.power_cycle_replay.feature— stored messages replayed after restart.store_capacity.feature— overflow / discard-oldest / discard-newest / halt policies.Docs and header surface
Platform/FatFs/Interface/SolidSyslogFatFsFile.hadded.Platform/FatFs/platform pack (peer toPosix/Windows/FreeRtos/OpenSsl) added.CLAUDE.md"Public header audiences" — new row.ff.c, which is untouched).Cross-cuts
SolidSyslogFileto the existing file / block-device / store stack rather than reinventing it.CppUTestFreertosDockermust land first (separate PR, separate repo).References
SolidSyslogPosixFile+SolidSyslogFileBlockDevice+SolidSyslogBlockStore.diskio.cinterface contract: http://elm-chan.org/fsw/ff/doc/dstat.html