casaroli opened a new pull request, #3665:
URL: https://github.com/apache/nuttx-apps/pull/3665

   ## Summary
   
   The applications that go with **XIPFS**, the writable execute-in-place file
   system added in the companion PR:
   
   **Companion PR: apache/nuttx#19536**
   
   This one depends on that one and cannot be built without it: every Kconfig
   option here depends on `CONFIG_FS_XIPFS`.
   
   Three additions:
   
   * **`system/xipfs`** — a command that compacts a volume and reports how its
     erase blocks are laid out. Because a XIPFS file is a single contiguous
     extent, an allocation can fail for lack of a contiguous run while plenty of
     free space remains, and compaction is never automatic: the file system
     returns `-ENOSPC` and the caller decides. This command is that decision 
made
     by hand. `-n` surveys without moving anything and prints the per-file 
table,
     a block map, and the share of free space a single allocation cannot reach —
     which is the number a caller facing `-ENOSPC` actually wants. The pass is
     asked for through a descriptor for the mountpoint directory, so no file is
     held open while it runs and one pass reaches every extent.
   
   * **`testing/fs/xipfs`** — the test suite, 14 sections selectable by name
     because the power-loss sweeps run for minutes while everything else runs in
     seconds. Beyond the routine VFS paths it aims at the properties that are
     easy to get wrong and quiet when they are: that a pin taken by a task that
     then *dies without unmapping* is still released, and that failing the Nth
     flash operation and remounting always yields a consistent volume with every
     committed file intact. The sweeps cover create, unlink, mkdir/rmdir and
     defragmentation, each with the failing operation left torn as well as
     cleanly refused.
   
   * **`examples/nxflatxip`** — the end-to-end demonstration: write an NXFLAT
     module into the volume at run time the way a download would, confirm the
     file system hands out a real flash pointer for it, and run two instances
     concurrently. Both report the same text address, inside the flash window,
     while their stacks differ. Two subcommands cover the file system rather 
than
     the module: `bench` times a bulk read out of mapped flash before and after 
a
     write, and `defrag` fragments the volume until an allocation genuinely
     cannot be satisfied, compacts, retries, then verifies every relocated file
     byte-for-byte and again after a remount.
   
   ### A note on the demo module
   
   The module is built in-tree exactly the way `examples/nxflat` builds its test
   programs, so it needs the same two host tools, `mknxflat` and `ldnxflat`.
   
   It deliberately has **no static data and no string constants**, and reports
   through a callback into the firmware instead of formatting its own output.
   That is not stylistic. The `ldnxflat` in circulation resolves the GOT entries
   for `.bss` objects into the import table — so the module overwrites the
   addresses of the functions it imports and branches into nothing on its next
   call out — and drops the addend already in the instruction when resolving the
   PC-relative references to `.rodata`, so every string pointer lands in the
   middle of the code. Both were diagnosed on hardware; the comment at the top 
of
   `module/xipmod.c` records them. The callback also exercises the other
   direction of the interface: firmware code entered with the module's data base
   still live in its PIC register.
   
   ## Impact
   
   * **New applications, all off by default**, and all depending on
     `CONFIG_FS_XIPFS`, so nothing changes for existing configurations.
   * `examples/nxflatxip` additionally depends on `NXFLAT` and `LIBC_EXECFUNCS`,
     and its build needs `mknxflat`/`ldnxflat` and a board `Make.defs` that 
names
     them — the same requirement `examples/nxflat` already has.
   * `testing/fs/xipfs` writes and erases its volume continuously, the 
power-loss
     sections most of all. The Kconfig help and the documentation both say to
     point it at a volume whose contents do not matter.
   * No existing file is modified.
   
   ## Testing
   
   Host: macOS 15 (arm64), `arm-none-eabi-gcc 14.2.rel1`.
   
   Targets:
   
   * `sim:xipfs` — XIPFS on `rammtd`.
   * `pimoroni-pico-2-plus:xipfs` — XIPFS on real QSPI NOR via `/dev/rpflash`.
   
   Every hardware run was bracketed by a `uname -a` check of the git revision 
and
   board name, before the first command and after the last, so the logs cannot 
be
   from a different build.
   
   ### Full suite on real flash
   
   ```
   [identity ok before] rev 0e9e189444, board pimoroni-pico-2-plus
   -- basic VFS --                      -- directories --
   -- write-once enforcement --         -- defragmentation --
   -- strict mapping semantics --       -- power loss during create (clean) --
   -- XIP mapping --                    -- power loss during create (torn) --
   -- concurrent mappings --            -- power loss during unlink --
   -- cross-task pin refcounting --     -- power loss during mkdir and rmdir --
   -- pin release on task exit --       -- power loss during defrag --
       swept 110 injection points, covering every operation of the whole pass
   ==== 90 passed, 0 failed ====
   [identity ok after] rev 0e9e189444, board pimoroni-pico-2-plus
   ```
   
   Same suite on `sim:xipfs`: `==== 90 passed, 0 failed ====`.
   
   ### `nxflatxip` on hardware
   
   ```
   === NXFLAT module executed in place from xipfs ===
   staged 268 bytes to /mnt/xipfs/xipmod
   extent: block 97 x1, size 268, flash addr 0x10161000
   running two concurrent instances...
   [while running] pin count on the shared text = 2
     instance seed 1: text 0x10161070, stack 0x20006980, sum 2080 -- data 
private and intact
     instance seed 2: text 0x10161070, stack 0x20007588, sum 4160 -- data 
private and intact
   [after exit]    pin count on the shared text = 2 (released when this task 
exits)
   === done ===
   ```
   
   ### `nxflatxip defrag` on hardware
   
   ```
   [1] writing 55 files...
   [2] deleting every other file to fragment it...
   [3] requesting a 209-block (836 KB) contiguous file
       result: FAILED -ENOSPC (free space is not contiguous)
   [4] compacting...
       elapsed          : 1230 ms
       extents relocated: 27
       blocks reclaimed : 27
       largest free run : 913408 bytes (223 blocks)
       stop reason      : 0 (done)
   [5] retrying, sized to the reported largest run (223 blocks)
       result: OK -- allocation now fits
   [6] verifying every relocated file byte-for-byte
       all survivors intact
   [7] remounting to prove it is durable
       all files intact after remount
   === defrag complete ===
   ```
   
   ### `nxflatxip bench` on hardware
   
   ```
   XIP read benchmark (256 KB)
     before any flash write : 30 ms
     after  a flash write   : 20 ms
   ```
   
   ### `xipfs` command on hardware
   
   ```
   nsh> xipfs -n
   /mnt/xipfs: 250 blocks of 4096 bytes (1000 KB)
     file                             start  blocks    bytes  pin
     bin/greet                            0       1        6    0
     bin/sub/deep                         1       1        5    0
        0 |##................................................|
     '.' free   '#' in use   'P' pinned by a live mapping
     used 2, free 248, largest free run 248 blocks (992 KB)
     1 free run, fragmentation 0%
     nothing to gain: all free space is already contiguous
   ```
   
   `tools/checkpatch.sh -c -u -m -g` passes on every commit in the branch.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to