105 lines
4.9 KiB
Markdown
105 lines
4.9 KiB
Markdown
# AGENTS.md
|
|
|
|
PlatformIO / Arduino-framework firmware for a NUCLEO-F042K6 reading two MS5611
|
|
barometers (one I2C, one SPI) and emitting validated CSV over the ST-LINK VCP.
|
|
See `README.md` for wiring tables, CSV format and status codes.
|
|
|
|
## Commands
|
|
|
|
```sh
|
|
pio run # build (the only real verification gate)
|
|
pio run -t upload # flash over ST-LINK
|
|
pio device monitor # 115200 baud
|
|
pio run -t clean
|
|
```
|
|
|
|
There is one env, `nucleo_f042k6`. No lint, format, or typecheck step exists.
|
|
|
|
**Always read the size report at the end of `pio run`.** It is the acceptance
|
|
criterion for any change (see below). Current: flash 88.8% (29108 / 32768),
|
|
RAM 32.6% (2004 / 6144).
|
|
|
|
## Flash budget is the dominant constraint
|
|
|
|
3.6 KB of flash headroom. This shapes almost every design decision here, and it
|
|
is the single easiest thing to break without noticing.
|
|
|
|
`-flto` and `-fsingle-precision-constant` in `platformio.ini` are load-bearing.
|
|
Verified: building without them overflows `FLASH` by **7252 bytes** and fails to
|
|
link. Both MS5611 driver libraries write their compensation maths with unsuffixed
|
|
double literals, which otherwise links the double soft-float helpers.
|
|
|
|
Consequences for new code:
|
|
|
|
- Never introduce `double`, unsuffixed floating literals, or `<math.h>` calls on
|
|
doubles. Use `float` and `f`-suffixed constants.
|
|
- Never call `Serial.print(someFloat, digits)` — it resolves to
|
|
`Print::print(double, int)` and pulls in soft-float. `main.cpp::printFixed2()`
|
|
exists solely to format floats via scaled integers; use it.
|
|
- Wrap string literals in `F()` so they stay in flash.
|
|
- No `String`, no `new`/`delete`. `~BaroChannel()` is deliberately non-virtual
|
|
and `protected` to keep a destructor slot out of the vtable and avoid linking
|
|
`operator delete`. Do not "fix" this into a virtual destructor.
|
|
- `lib_deps` pin exact driver tags (`MS5611#0.5.2`, `MS5611_SPI#0.4.3`). Bumping
|
|
them can blow the budget; rebuild and check size if you do.
|
|
|
|
## Architecture
|
|
|
|
- `include/config.h` — every pin, address, rate, threshold and validation limit.
|
|
Change hardware behaviour **here**, not in the `.cpp` files.
|
|
- `include/baro_channel.h` / `src/baro_channel.cpp` — `BaroChannel`, the shared
|
|
state machine: init + PROM/CRC handshake, per-poll validation, error streaks,
|
|
re-init, and the 1 s error LED pulse. Five pure-virtual `driver*()` hooks are
|
|
the only per-bus surface.
|
|
- `src/baro_i2c.cpp` / `src/baro_spi.cpp` — one concrete subclass each, plus a
|
|
file-static instance exposed through `baroI2cChannel()` / `baroSpiChannel()`.
|
|
- `src/ms5611_crc.cpp` — standalone PROM CRC-4 (AN520).
|
|
- `src/main.cpp` — `setup()`/`loop()`, CSV formatting, 10 Hz report scheduling.
|
|
|
|
**The two-file split is mandatory, not stylistic.** `MS5611.h` and
|
|
`MS5611_SPI.h` each define their own `enum osr_t` and `MS5611_READ_OK`, so they
|
|
cannot be included in the same translation unit. `baro_channel.h` therefore
|
|
includes neither driver header, and the channels are handed out via accessor
|
|
functions. Do not merge these TUs or hoist a driver include into the header.
|
|
|
|
## Conventions that differ from defaults
|
|
|
|
- **millis() rollover safety**: deadline comparisons use a signed difference —
|
|
`if ((int32_t)(now - deadline) >= 0)`. Never write `now >= deadline`.
|
|
- **`poll()` blocks** for ~2 ADC conversions (~5 ms/sensor at OSR 1024).
|
|
`main.cpp` re-reads `millis()` after polling before evaluating LED and report
|
|
deadlines. Preserve that if you touch the loop.
|
|
- **Validation belongs in `BaroChannel`, not the drivers.** Neither library
|
|
checks the PROM CRC, and `MS5611::read()` returns `MS5611_READ_OK` for an ADC
|
|
read taken before the conversion completed (which yields 0). Do not simplify
|
|
the range / stale / all-zero-PROM checks away by trusting driver return codes.
|
|
- Style is Allman braces, 2-space indent, `_camelCase` private members, `// `
|
|
(two spaces) block comments. There is **no `.clang-format`** in the repo —
|
|
running `clang-format` would reformat everything into LLVM style. Don't.
|
|
- `SPI` and `I2C` appear in `lib_deps`, but the code uses `Wire` directly and
|
|
nothing includes the third-party `I2C` library.
|
|
|
|
## Testing
|
|
|
|
There is no automated test suite. `test/` holds only the stock PlatformIO
|
|
README, and `pio test` collects 0 cases. Do not claim tests pass.
|
|
|
|
`ms5611_crc.{h,cpp}` is intentionally free of Arduino headers so it can be
|
|
exercised on the host:
|
|
|
|
```sh
|
|
clang++ -std=c++17 -Wall -Wextra -c src/ms5611_crc.cpp -Iinclude -o /tmp/crc.o
|
|
```
|
|
|
|
The differential check against the NuttX reference described in `README.md` was
|
|
a host-side exercise and is not committed.
|
|
|
|
Anything beyond the CRC needs real hardware: build, flash, and watch the CSV
|
|
stream. Unplugging a sensor is the quick way to exercise the error paths
|
|
(`ERR_INIT` / `ERR_CRC`, LED pulse, auto re-init after 10 consecutive failures).
|
|
|
|
## Notes
|
|
|
|
`.pio/`, `.omo/`, `.junie/` and `.idea/` are gitignored tooling state, not
|
|
project sources.
|