Persistent Settings Defaults: Distinguish Missing, Corrupt and Explicitly Cleared Values

Apply a default only when the setting’s documented policy permits it. A missing record, a malformed or integrity-failing record, and an explicitly cleared value carry different information. If firmware maps all three to the same fallback, it can silently undo an operator’s choice or conceal a storage fault.

This article defines an original six-byte application envelope with three persisted semantic modes: DEFAULT, VALUE and CLEARED. Storage absence and invalid input remain separate read outcomes. Zephyr v4.2.0 NVS supplies the concrete deletion boundary; the envelope is not an NVS on-media format.

1. Do not use physical absence to represent every intention

The NVS v4.2.0 API treats a zero-length write as deletion. It cannot represent an ordinary zero-length stored value separately from deletion. In the pinned read implementation, absent and selected deletion entries can produce -ENOENT.

That outcome does not reveal whether a setting was never provisioned, deliberately removed, or lost through another process. If deliberate clearing must survive restart as a distinct product instruction, store an explicit nonempty representation of that instruction.

Keep actual I/O errors separate from absence. A wrapper that turns every negative result into “not configured” destroys the evidence needed to make a safe default decision. Capture storage status before interpreting bytes.

Storage absence and errors are handled before a valid envelope selects DEFAULT, VALUE or CLEARED semantics.
Original application representation. A missing record is not evidence of a deliberate clear, and invalid bytes do not authorize a default.

2. Define the persisted representation precisely

The illustrative setting is an optional reporting interval, not an actuator limit or safety threshold. Its six bytes are: format version, mode, default-policy revision, reserved byte, and a two-byte unsigned little-endian value. The reserved byte must be zero.

Mode Encoding rule Meaning
0: DEFAULT. Known default-policy revision; value zero. Use that specific approved default policy.
1: VALUE. Policy revision zero; value 1 through 3,600. Use the explicitly stored interval in seconds.
2: CLEARED. Policy revision zero; value zero. The optional interval is intentionally unset; do not reapply a default.

All three modes occupy a nonempty six-byte record. The zero value in DEFAULT or CLEARED is a constrained encoding field, not an interval of zero seconds. Unknown modes, nonzero reserved bytes and inconsistent combinations are rejected.

Validate the complete storage representation and its configured integrity protection before interpreting this envelope. The host model checks length and semantics but does not implement a checksum or authentication. No claim is made that every possible corruption can be detected by these fields.

3. Keep read outcomes separate from valid modes

Read or decode outcome Permitted decision Forbidden shortcut
MISSING. Apply the documented provisioning policy, which may require configuration or permit an initial default. Assume an operator explicitly cleared it.
Valid DEFAULT. Apply its known policy revision. Substitute today’s default without checking its saved meaning.
Valid VALUE. Apply the validated explicit value. Replace it because a new default is preferred.
Valid CLEARED. Keep the optional setting unset. Repopulate it from a fallback.
Invalid, integrity failure or I/O error. Report the defined configuration/storage fault and follow the approved degraded policy. Pretend the record was simply absent.
Unsupported format or policy revision. Report incompatibility and use its explicit recovery policy. Call unfamiliar data corrupt or reinterpret it as an older format.

Absence can justify a default only when the product has approved that behavior for the specific setting and lifecycle state. A factory-new optional preference and missing calibration on an already commissioned unit should not share an automatic fallback merely because both reads found no value.

4. Version the meaning of “default”

In the hypothetical policy registry, revision 1 means ten seconds and revision 2 means thirty seconds. New firmware supports both. An existing DEFAULT record referring to revision 1 therefore stays at ten seconds after the update.

An older reader that knows only revision 1 must reject a DEFAULT record naming revision 2 as unsupported policy. It must not silently use ten seconds because that is the only default it knows. This is a narrow interpretation rule, not a complete firmware migration strategy.

Alternatively, a product may intentionally define a mode that follows the current release’s default. If so, name and test that behavior explicitly. Do not accidentally create it by omitting a policy revision from a representation whose meaning was expected to remain stable.

5. Use exact-byte interpretation fixtures

The following hexadecimal examples exercise the invented version-1 envelope. They are synthetic and contain no real device configuration.

  • 01 00 01 00 00 00: DEFAULT policy 1, ten seconds in both supported readers.
  • 01 00 02 00 00 00: DEFAULT policy 2, thirty seconds in the new reader and unsupported in the old reader.
  • 01 01 00 00 14 00: explicit VALUE of twenty seconds.
  • 01 02 00 00 00 00: CLEARED, with no fallback interval.
  • 01 02 00 00 01 00: invalid, because CLEARED requires a zero value field.
  • 02 02 00 00 00 00: unsupported format version, not an accepted clear instruction.

Observed host result: fifteen representation cases and two versioned-default checks passed under Python 3.12.14. The sanitized runner includes missing input, empty malformed bytes, unknown mode/policy, reserved-bit misuse and value bounds. It does not execute NVS, a flash driver, power-loss tests or product safety logic.

6. Qualify update and reset behavior separately

On a disposable store, test each valid mode across restart and every permitted firmware reader. Then interrupt a settings replacement and verify that the recovered result follows the storage contract and remains one of the deliberately handled outcomes. No such target tests were performed here.

Define whether “reset preferences” writes an explicit DEFAULT, writes CLEARED, or removes the record and invokes provisioning policy later. Those are different product actions. Make the UI and support procedure describe the selected meaning, and check that background caches do not repopulate a cleared value.

Preserve invalid evidence before an authorized repair. Do not overwrite an unreadable record with defaults merely to make the next boot quiet. For safety-relevant settings, use the product’s approved safe-state and configuration requirements rather than adapting this optional-interval example blindly.

Hypothetical update surprise

An operator clears optional periodic reporting. If firmware merely deletes the ID, a later release may interpret absence as first-use setup and enable its new default interval. An explicit CLEARED envelope preserves the operator’s intended state, while versioned DEFAULT records keep their own defined behavior.

Release the encoding, policy registry and exact-byte fixtures together. The useful guarantee is that missing, invalid and deliberately cleared inputs lead to different, reviewable decisions.

Similar Posts