Initial commit.
This commit is contained in:
104
AGENTS.md
Normal file
104
AGENTS.md
Normal file
@@ -0,0 +1,104 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user