AUDIT-S10 (commit `58154a6`) split the FPGA's six-flag aggregate
gpio_dig5 into two MCU-visible bits: gpio_dig5 keeps signal-saturation
(AGC reacts), gpio_dig7 (PD15) carries control-fault classes
(range_decim_watchdog | cic_fir_overrun). Until now the MCU did NOT
poll PD15, so DSP control faults were invisible to the recovery
dispatcher.
Changes:
- New `ERROR_FPGA_DSP_STALL` enum value placed AFTER ERROR_WATCHDOG_TIMEOUT
so the dispatcher routes to attemptErrorRecovery (FPGA reset pulse) not
Emergency_Stop. Updated error_strings[] in lockstep (static_assert
enforces).
- checkSystemHealth section 10 polls PD15 at 1 Hz with 2-sample debounce.
`last_dsp_check` is committed BEFORE the early return per AUDIT-CAL
pattern, so a flapping fault never bypasses the rate-limit. Streak
counter resets to 0 after firing (armed for next post-recovery
assertion) AND resets naturally when PD15 returns LOW.
- attemptErrorRecovery: ERROR_FPGA_DSP_STALL fans into the existing
ERROR_FPGA_COMM PD12 reset case (stacked case labels, same body). No
MCU-driven reset_monitors path exists; full bitstream reload clears
all sticky monitors as a side effect.
Tests:
- tests/test_audit_s10_dsp_stall_polling.c (NEW, 7 scenarios, 7/7 PASS):
T1 healthy 60s, T2 single-sample glitch blocked by debounce, T3
sustained fault fires once, T4 post-fire rate-limit holds within
window, T5 sustained fault rate bounded (29 errors / 60s -- MCU-N1
latch at error_count>10 fires in ~22s, gives operator time to
intervene), T6 counter-test demos no-debounce false-positive on
glitch, T7 HAL_GetTick 32-bit wrap.
- MCU host suite 35/35 PASS (was 34/34; +1 new, 0 regressions).