Status: Proposed Date: 2026-07-08
All fallible flight code returns Result<T> = std::expected<T, Error>,
where Error was a bare uint8 enum. A latched fault reached the ground
as a SENSOR_FAILED gap marker with the LED fault code smuggled into
first_missing_tick — it said that a device failed, but not where
in the call chain, which of a driver's many bus transactions, or
when. Debugging a flight anomaly from that is guesswork.
Errorbecomes a record that carries its own trace. Fields: cause (ErrorCode), fixedtrace[6]ofStepentries (trace[0]= origin, then outward),depth,truncated, origin__LINE__(uint16) and origintimestamp_us.fail(code, step, __LINE__)creates the origin (stamps the time via theErrorClockhook, set once at boot to the platform µs clock).mark(err, step)is called by each semantic level while the expected propagates outward; when the array is full it setstruncatedinstead of writing past the end.- Pure pass-through helpers do not mark, keeping real chains within depth 6 (deepest observed: origin → bus API → driver helper → driver op → caller).
- Fixed depth 6, no allocation. A growing container would cost
heap (banned in the tick loop) and unbounded WCET. 9 bytes of trace
in every
Resulterror path is the deal;sizeof(Error) <= 16is static-asserted. __LINE__as an explicit parameter — no macro (clang-tidy), and nostd::source_location, which would embed file/function strings into flash at every origin site.- Latching devices keep their death trace.
DeviceBase::register_failure(err)/disable(err)store the causingError; polled reporting (poll_device_fault()) ships it later with exact origin time and line. - New FAULT packet (0xF1) replaces the SENSOR_FAILED gap-marker
convention: fault code (= LED blink code), error code,
depth/truncated, origin line, 6 steps. Header timestamp = moment of
occurrence; header tick = report time.
GapReason::SENSOR_FAILEDstays wire-stable but is no longer emitted. Dictionary: docs/handbook/fault-trace-codes.md (append-only values). - The report hook was renamed
on_sensor_failed→report_fault: UART/CAN ring latches use the same path and are not sensors.