77 lines
3.4 KiB
Markdown
77 lines
3.4 KiB
Markdown
# Audit Hardening — 2026-08-17
|
|
|
|
This pass addresses the findings from the independent prototype-v0 audit. It
|
|
does not add calibration, BLE, persistent storage, filtering beyond the selected
|
|
L3G4200D hardware filter, or sensor fusion.
|
|
|
|
## Git checkpoints
|
|
|
|
- `f1ac20f`: exact pre-hardening firmware and axis-validation baseline
|
|
- The verified hardening changes are committed separately after this report
|
|
|
|
No remote repository is configured; these are local history checkpoints.
|
|
|
|
## Changes
|
|
|
|
- A clean build now selects `esp32c3` from `sdkconfig.defaults`.
|
|
- ADXL345 `INT_SOURCE` and L3G4200D `STATUS_REG` are read immediately before
|
|
their corresponding six-byte XYZ reads.
|
|
- Raw status bytes and a cumulative loop-overrun count are appended to CSV.
|
|
- A delayed acquisition loop resynchronizes rather than issuing catch-up bursts.
|
|
- ADXL345 FIFO, interrupt enables, and hardware offset registers are explicitly
|
|
reset during initialization so warm MCU resets are deterministic.
|
|
- L3G4200D LPF2 is routed to the output with `CTRL_REG5=0x02`, making the
|
|
configured 25 Hz cutoff effective.
|
|
- Both sensor drivers remove their I2C device handles after an initialization
|
|
failure and expose deinitializers.
|
|
- Candidate-address loops use an element count rather than byte size.
|
|
- The capture utility auto-detects a single USB modem port, writes numeric CSV
|
|
only, and reports sequence gaps, resets, timestamp anomalies, malformed
|
|
records, and ignored non-record lines.
|
|
- Documentation now distinguishes the MCU poll timestamp and nominal scale from
|
|
sensor sample timing and measured per-axis scale.
|
|
|
|
## Build validation
|
|
|
|
- Normal incremental build: pass
|
|
- Clean temporary copy with no `sdkconfig` or `build/`: pass
|
|
- Clean configuration selected `CONFIG_IDF_TARGET="esp32c3"` from
|
|
`sdkconfig.defaults`
|
|
- Hardened binary size: `0x242d0` bytes; 86% of the application partition free
|
|
|
|
## Hardware validation
|
|
|
|
The hardened firmware was flashed to the assembled XIAO ESP32-C3 prototype.
|
|
Both devices initialized successfully after a USB-triggered warm reset, including
|
|
all new register writes and the L3G4200D CTRL5 readback.
|
|
|
|
The capture `captures/hardening_freshness.csv` contains:
|
|
|
|
- 3,796 consecutive records
|
|
- Sequence gaps: 0
|
|
- Sequence resets: 0
|
|
- Timestamp anomalies: 0
|
|
- Timestamp interval: 10,000 us for all 3,795 intervals
|
|
- Rejected records: 0
|
|
- Acquisition loop overruns: 0
|
|
- ADXL345 DATA_READY clear at status time: 192 records (5.058%)
|
|
- ADXL345 overrun set: 0 records
|
|
- L3G4200D ZYXDA clear: 0 records
|
|
- L3G4200D ZYXOR set: 112 records (2.950%)
|
|
|
|
The ADXL345 clear events have a coherent 27/28-poll pattern, including adjacent
|
|
clear events when a device update likely occurs between the separate status and
|
|
data transactions. A clear bit is therefore conservatively treated as
|
|
stale/untrusted; a set bit proves unread data existed before the read. The gyro
|
|
overrun pattern directly confirms that its internal output clock is faster than
|
|
the MCU poll on this unit.
|
|
|
|
These results validate the audit finding that exact 100 Hz MCU polling does not
|
|
mean either sensor is synchronized to that clock. Status labeling is the scoped
|
|
prototype fix. Interrupt/FIFO-driven acquisition remains a later buffering task.
|
|
|
|
A final post-build/post-flash smoke capture added another 1,634 consecutive
|
|
records with zero gaps, timestamp anomalies, rejected records, ADXL345 overruns,
|
|
or acquisition-loop overruns. It again exposed ADXL345 DATA_READY clear on 81
|
|
polls and L3G4200D overrun on 48 polls.
|