mcu(bmp180): replace in-band sentinel + fix uint16->int16 narrowing (AUDIT-C17)

BMP180_ERROR=255 was an in-band sentinel returned by uint16_t I/O helpers
(read16, readRawTemperature) on I2C failure. 255 is also a valid uint16
register reading (0x00FF appears across the calibration block and is
reachable as a raw temperature/pressure sample), so a sensor failure was
indistinguishable from a real reading.

getTemperature() additionally narrowed the uint16_t raw read to int16_t
before passing to computeB5(). Raw bit-patterns >= 0x8000 (reachable across
the BMP180 -40..+85 C operating window) flipped to negative int16_t and
sign-extended into computeB5(), producing temperature errors of order
100s of C (e.g. -347 C instead of +51 C for raw UT = 0x8000).

Fix:
  - Internal I/O helpers (read8/read16/readRawTemperature/readRawPressure)
    now return bool and pass the value through an out-param. None of the
    new sentinels collide with valid sensor output:
      * getTemperature       -> NaN          on error
      * getPressure          -> INT32_MIN    on error
      * getSeaLevelPressure  -> INT32_MIN    on error
  - getTemperature() keeps raw as uint16_t and widens value-preservingly
    via (int32_t)raw before computeB5().
  - readRawPressure() reads XLSB through the bool-out-param contract;
    previously OR'd in 0xFF on I2C fail, silently corrupting the LSB.

Verification: test_audit_c17_bmp180_sentinel_and_cast 4/4 PASS, including
datasheet UT=27898 -> 15.0 C reproduction and 64/64 finite outputs across
a full uint16 sweep (vs 32/32 collapses in the upper half under the buggy
narrowing). Full MCU regression 32/32 PASS.

Caller-side: no external code references BMP180_ERROR; main.cpp's existing
range check at the health-watchdog catches INT32_MIN via the < 30000.0
branch.
This commit is contained in:
Jason
2026-04-29 18:55:48 +05:45
parent ea2615ef84
commit 4b142166be
5 changed files with 337 additions and 59 deletions
@@ -72,6 +72,7 @@ TESTS_STANDALONE := test_bug12_pa_cal_loop_inverted \
test_mcu_a6_recovery_dispatch \
test_mcu_a2_mag_declination \
test_mcu_a4_ocxo_warm_restart \
test_audit_c17_bmp180_sentinel_and_cast \
test_gap3_iwdg_config \
test_gap3_temperature_max \
test_gap3_idq_periodic_reread \
@@ -183,6 +184,9 @@ test_mcu_a2_mag_declination: test_mcu_a2_mag_declination.c
test_mcu_a4_ocxo_warm_restart: test_mcu_a4_ocxo_warm_restart.c
$(CC) $(CFLAGS) $< -o $@
test_audit_c17_bmp180_sentinel_and_cast: test_audit_c17_bmp180_sentinel_and_cast.c
$(CC) $(CFLAGS) $< -lm -o $@
# Gap-3 safety tests -- mock-only (needs spy log for GPIO sequence)
test_gap3_emergency_stop_rails: test_gap3_emergency_stop_rails.c $(MOCK_OBJS)
$(CC) $(CFLAGS) $(INCLUDES) $< $(MOCK_OBJS) -o $@