Skip to content

S29.04: Platform/PlusFat/ adapter pack + PlusFatFake + 100% host TDD #522

Description

@DavidCozens

Parent epic: #512 (E29) · Depends on: S29.02 (#517, done — FREERTOS_PLUS_FAT_PATH provisioned in both images). Independent of S29.03 (#520). Unblocks: S29.05 (media driver + PlusTCP-target swap).

Motivation

E29 needs a SolidSyslogFile implementation backed by FreeRTOS-Plus-FAT so the PlusTCP target can run a real FS-backed store (S29.05), proving the SolidSyslogFile seam is FS-vendor-portable the same way E28 proved the transport seam is TCP-vendor-portable. This story builds only the host-tested adapter pack — no media driver, no QEMU, no target wiring (all S29.05). Pure host TDD against a fake, mirroring the existing Platform/FatFs/ pack 1:1.

Note on the epic wording: the epic lists this pack as "3-TU split + Errors + Messages". S12.26 (#514) deleted all 43 *Messages.c tables — the library is codes-only now — so this pack has no Messages TU. The current Platform/FatFs/ pack (3 source files + 1 Errors header) is the correct template. (Epic body corrected to match.)

Scope — mirror Platform/FatFs/ exactly

New pack, same 3-TU split as SolidSyslogFatFsFile:

File Role
Platform/PlusFat/Interface/SolidSyslogPlusFatFile.h _Create(void) / _Destroy(base)
Platform/PlusFat/Interface/SolidSyslogPlusFatFileErrors.h enum SolidSyslogPlusFatFileErrors (PLUSFATFILE_ERROR_POOL_EXHAUSTED, _UNKNOWN_DESTROY, _MAX) + extern …PlusFatFileErrorSource
Platform/PlusFat/Source/SolidSyslogPlusFatFile.c vtable + Initialise/Cleanup, the ff_* ops, PlusFatFileErrorSource = {"PlusFatFile"}
Platform/PlusFat/Source/SolidSyslogPlusFatFilePrivate.h struct (Base + FF_FILE* Fp + bool IsOpen) + _Report static-inline
Platform/PlusFat/Source/SolidSyslogPlusFatFileStatic.c pool + _Create/_Destroy via SolidSyslogPoolAllocator
Platform/PlusFat/Source/.clang-tidy copy from FatFs
Platform/PlusFat/CMakeLists.txt INTERFACE library (header-configured — the integrator's FreeRTOSFATConfig.h flows into each consumer's compile, same rationale as FatFs)

Pool tunable reuses the role-named SOLIDSYSLOG_FILE_POOL_SIZE (one File impl links per build).

ff_*SolidSyslogFile vtable mapping (epic-locked; pin-check at TDD time)

Plus-FAT's ff_stdio is a FILE*-style handle API (FF_FILE*), unlike ChaN FatFs's caller-owned FIL, so the struct holds an FF_FILE* (NULL when closed):

vtable op FatFs (today) Plus-FAT (this story)
Open f_open(&Fp, path, FA_READ|FA_WRITE|FA_OPEN_ALWAYS) ff_fopen(path,"r+"), fall back to "w+" on NULL (no OPEN_ALWAYS flag)
Close f_close(&Fp) ff_fclose(Fp)
IsOpen tracked bool tracked bool (Fp != NULL)
Read f_read ff_fread
Write f_write + f_sync ff_fwrite + ff_fflush (durability after every write — same contract)
SeekTo f_lseek ff_fseek(Fp, off, FF_SEEK_SET)
Size f_size ff_filelength(Fp)
Truncate f_lseek(0) + f_truncate ff_fseek(0) + ff_seteof(Fp)
Exists f_stat(path, NULL) ff_stat(path, …)
Delete f_unlink(path) ff_remove(path)

Pin-check at TDD time that ff_seteof, ff_stat, ff_remove exist with these signatures in the pinned Plus-FAT SHA 8d38036 (S29.02 already pin-checked ff_seteof).

PlusFatFake + host test

Tests/Support/PlusFatFakes/ — host fake implementing the ff_* functions the adapter calls, with the same set/spy surface as FatFsFake (result injection, call counts, last-path/last-mode/last-bytes capture, programmable read source + file size). New test exe Tests/PlusFat/ (SolidSyslogPlusFatFileTest.cpp behavioural + SolidSyslogPlusFatFilePoolTest.cpp pool + main.cpp), gated on FREERTOS_PLUS_FAT_PATH in CMakeLists.txt + Tests/CMakeLists.txt. 100% host line+branch (CI gate 90%, TDD target 100%).

FreeRTOS coupling — handled honestly, not hidden

Unlike ChaN FatFs (OS-agnostic), Plus-FAT's ff_stdio.h/ff_headers.h reference FreeRTOS types (FF_IOManager uses semaphores). Plus-FAT is FreeRTOS-coupled and we surface that rather than papering over it: the host test recompiles the adapter against the real Plus-FAT headers from $FREERTOS_PLUS_FAT_PATH + FreeRtosFakes for kernel types + a test-local FreeRTOSFATConfig.h, with PlusFatFake providing the ff_* impls. (Same real-headers-first stance as FatFsFake.)

CI / build wiring

Add Platform/PlusFat/ alongside FatFs in the freertos analysis lanes: -IPlatform/PlusFat/Interface + Platform/PlusFat/Source/ in cppcheck + cppcheck-misra, and the freertos analyze-tidy / analyze-iwyu source+include lists. New SolidSyslogPlusFatFileTest runs in the freertos host lane. CLAUDE.md gets the SolidSyslogPlusFatFile.h / …Errors.h public-header rows (headers are born here; the docs/integrating-plusfat.md guide stays in S29.05).

Acceptance criteria

  • Platform/PlusFat/ pack exists (3-TU split + Errors header, no Messages), structurally identical to Platform/FatFs/.
  • SolidSyslogPlusFatFile implements all 10 SolidSyslogFile vtable ops via ff_*; write durability via ff_fflush.
  • PlusFatFake + Tests/PlusFat/ at 100% host line+branch, gated on FREERTOS_PLUS_FAT_PATH.
  • Pool-exhaustion falls back to shared SolidSyslogNullFile; Cleanup closes any open handle before release.
  • ff_seteof / ff_stat / ff_remove pin-checked in SHA 8d38036.
  • All freertos analysis lanes (tidy / iwyu / cppcheck / cppcheck-misra) green with Platform/PlusFat/ added; no new MISRA findings vs main.
  • CLAUDE.md public-header rows added; DEVLOG entry committed on the work branch.
  • No Core / Tier-1 / Tier-2 change; FatFs untouched.

Out of scope

  • FF_Disk_t semihosting media driver, PlusTCP-target FatFs→PlusFAT swap, @store BDD on the target, docs/integrating-plusfat.mdall S29.05.

Environments

freertos host TDD (cpputest-freertos image, FREERTOS_PLUS_FAT_PATH); freertos analysis lanes (tidy/iwyu/cppcheck).

Metadata

Metadata

Assignees

No one assigned

    Labels

    storyStory issue

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions