fix(parameters): self-initialize blank parameter storage at boot (#27623)

Flashing PX4 over another firmware (e.g. ArduPilot on an ARK FPV) or
first-booting a board with blank parameter storage played the error tune
on every boot: the param layer treated a blank store as corruption, and
the rcS recovery persisted with a file cp that is a no-op on
FLASH_BASED_PARAMS boards, so the store never became valid.

- param_import()/param_load() return 1 ("not yet stored") for a blank
  source - empty file, zeroed FRAM, or erased flash - on both the file
  and flash backends; a store that holds data but no valid entry (torn
  write, bit-rot, foreign data) is still reported as corrupt (-EILSEQ).
  The file backend detects a zero-length file via fstat (NuttX FAT
  cannot read() a 0-byte file: no cluster chain returns an error, not
  EOF) and otherwise inspects the leading BSON document length; the
  flash backend scans the whole store
- new 'param load-or-init <backup>' command: loads from the default
  storage; a blank store is seeded from the SD backup (or firmware
  defaults) and persisted so the next boot loads normally. A corrupt
  store, a backup that exists but cannot be opened or imported, or a
  result that cannot be persisted returns failure. The three-way
  loaded/blank/corrupt logic lives in C because nsh $? is a binary
  success flag. A failed backup seed does not reset to defaults, which
  preserves parameters loaded earlier in boot (e.g. factory calibration
  from /fs/mtd_caldata)
- rcS uses 'param load-or-init' instead of 'param import', and the
  corrupt-store recovery persists via 'param save' (works on
  flash-backed boards) only when the backup actually imported, so a
  corrupt backup keeps alerting the operator on the next boot
- commander ParamLoadDefault treats blank storage (1) as success and
  warns the GCS that parameters were reset to defaults, instead of
  reporting "Error loading settings"
- parameter_flashfs_init() in flashfs.c no longer reports a successful
  erase byte count as a failure (parity with flashfs32.c)

Tested with new blankImport and corruptImport cases in 'tests
parameters' (empty/zeroed/erased sources import as "not yet stored",
garbage fails to import); the CustomDefaults test now restores the
firmware default so the suite is repeatable within one boot.

The STM32H7 flash-erase DCACHE invalidate fix this depends on
(PX4/NuttX#381) is already in main's NuttX submodule.

Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
This commit is contained in:
Jacob Dahl
2026-06-11 22:06:10 -04:00
committed by GitHub
parent 6fddba4037
commit 88951f01e9
10 changed files with 388 additions and 13 deletions

View File

@@ -195,10 +195,15 @@ else
param load /fs/mtd_caldata
fi
# Load parameters from storage. A blank store (first boot, or after
# switching firmware) is seeded from the backup or defaults and persisted
# by 'load-or-init' itself - that is not an error and does not beep. A
# corrupt or unwritable store, or a backup that fails to import, returns
# failure.
param select $PARAM_FILE
if ! param import
if ! param load-or-init $PARAM_BACKUP_FILE
then
echo "ERROR [init] param import failed"
echo "ERROR [init] param load-or-init failed"
set STARTUP_TUNE 2 # tune 2 = ERROR_TUNE
bsondump $PARAM_FILE
@@ -219,10 +224,13 @@ else
# dump current backup file contents for comparison
bsondump $PARAM_BACKUP_FILE
param import $PARAM_BACKUP_FILE
# overwrite invalid $PARAM_FILE with backup
cp $PARAM_BACKUP_FILE $PARAM_FILE
# only persist when the backup actually imported, so a
# corrupt backup keeps the storage invalid and the
# operator keeps being alerted on the next boot
if param import $PARAM_BACKUP_FILE
then
param save
fi
fi
param status