fix(flashparams): append unsaved deltas and compact at boot - #28532
Draft
dakejahl wants to merge 3 commits into
Draft
fix(flashparams): append unsaved deltas and compact at boot#28532dakejahl wants to merge 3 commits into
dakejahl wants to merge 3 commits into
Conversation
Same-bank program of a full BSON snapshot stalls instruction fetch for tens of ms, which drops a high-rate IMU FIFO and DShot while disarmed. The 1 s sector erase belongs at boot, not on a wrap mid-session. Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
Contributor
🔎 FLASH Analysispx4_fmu-v5x [Total VM Diff: -424 byte (-0.02 %)]px4_fmu-v6x [Total VM Diff: -424 byte (-0.02 %)]Updated: 2026-09-04T01:47:13 |
param_reset_all() queued an autosave that could program flash during the boot compact erase. Reset without autosave under file_mutex, build the snapshot in RAM before erasing, and compact only when a burst of deltas would not fit so COM_FLIGHT_UUID is not a 1 s erase every flight. Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
Walk order was not write order on multi-sector maps, and a torn H7 header skipped the rest of the sector so a successful retry vanished. Resets encoded as the current default also came back as overrides after a firmware default change. Signed-off-by: Jacob Dahl <dahl.jakejacob@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
fixes #28529
Flash param saves now append only the params that changed since the last save. The ~1 s sector erase, if it is needed, runs at boot before sensors and DShot start.
Problem
On STM32H7 boards with
FLASH_BASED_PARAMS, a program or erase of the param sector stalls every instruction fetch from that same flash bank. Each autosave rewrote the full BSON document (tens of ms). That stall drops a high-rate IMU FIFO and DShot while the vehicle is disarmed. When the 128 KB sector filled, erasing it (~1 s) could still run after the vehicle was already up.Solution
Each save appends only unsaved params, instead of rewriting the whole document. On load, PX4 replays those records in order.
A reset appends a BSON null for that param. Replay drops the override. The next compact omits it, so a later firmware default change does not come back as a user setting.
The slow sector erase moves to boot, before sensors and DShot start. PX4 rewrites the log as a single snapshot only when the blank tail cannot hold a batch of new saves, or when dead records sit in front of the live data (the layout left by the old writer). Saving the flight UUID on disarm does not force a 1 s erase on the next boot.
Compaction builds the snapshot in RAM before it erases the sector. The param-file lock is held across reset, import, and compact so autosave cannot write flash during the erase. If a later save still cannot fit, PX4 erases the sector while running. That path is last resort.
Before and after
The firmware image holds the defaults. RAM holds only overrides. Flash only needs to remember those overrides. On STM32H7, flash is programmed in 32-byte rows that cannot be rewritten, and a 128 KB erase stalls the CPU for about a second. The param sector shares a bank with the firmware, so a program or erase halts instruction fetch.
Before. Flash held one live snapshot of every override. Each save encoded the full set, marked the previous snapshot erased, and programmed a new copy after it. Load reset RAM to defaults and imported that one record. A reset did not need a marker: the next snapshot simply omitted the param. Every autosave allocated two RAM buffers the size of the full BSON (encoder plus write buffer). A typical vehicle is about 100 overrides (~2 KB BSON, ~4 KB peak). All 1668 ARK FPV params would be ~35 KB BSON and ~71 KB peak; that bound is not new.
After. Flash is a log. A boot snapshot is followed by small records of unsaved params. Load applies every live record in order. A reset must appear in the log as a BSON null, or replay would still apply the old override. Compact at boot collapses the log to one snapshot when the tail is too small, or when the old dead-record prefix is still there, using the same two-buffer peak as the old save path. In-service saves only allocate the delta.
Compatibility. New firmware reads the old single-snapshot layout, then compact rewrites it. Parameters are kept.
Old firmware reads only the first live record. If flash is still one snapshot (new firmware booted, compact ran, no save), a downgrade loads that snapshot. After any in-service save, including
COM_FLIGHT_UUIDon disarm, later deltas are invisible. An old-firmware save then marks the snapshot erased and tries to program over the deltas. On H7 that write fails, and the complete copy is already gone. A QGC reset on old firmware takes the same save path; it does not erase the sector and will not repair it.