sim: Modbus RTU slave model (ModbusSlave) on the RS-485 seam

The device counterpart to warden-modbus's master/scanner: request-frame in,
response-frame out, in host memory. CRC16 is byte-identical to the master
(poly 0xA001, low-first; known vector 01 03 00 00 00 01 -> 84 0A verified).
Implements the data plane — read/write holding & input registers, coils,
discrete inputs (FC 0x01-0x06, 0x0F, 0x10) + Report Slave ID (0x11) — with
exception replies (illegal function/address/value) and the two real-world
faults the master must survive: a device that silently ignores a request
(drop_next) and one that NAKs everything (force_exception). This is what the
modbus-master MC/DC harness drives against; MEI (0x2B/0x0E) is a follow-up.

11 tests, sim crate 25/25 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017wB8KB3MMQztRDXCMCkPrf
This commit is contained in:
BFE Engineering
2026-08-24 18:04:38 -06:00
co-authored by Claude Opus 4.8
parent 4a1ec1d84e
commit 435953799c
3 changed files with 447 additions and 6 deletions
+12 -4
View File
@@ -61,10 +61,18 @@ supervisor logic runs in CI with no panel.
bench unit (though the *layout* fault — a load address in unreserved kernel RAM —
is a target-config check, §5, not a sim property).
- **`cru` — reset ladder.** Done. `CruSim` on `MemBus` (so `flared::devmem::hard_reset`'s
ladder is host-tested against the known glb_srst_fst / DW-watchdog registers); an
**NPU** load model behind the path seam; a **GPIO/relay** sysfs model; a **modbus
device** model unifying the existing `mbsim.py` corpus into the same framework;
an **RGA** recording fake.
ladder is host-tested against the known glb_srst_fst / DW-watchdog registers), plus
the boot-mode register's survives-warm-reset / cleared-by-POR behaviour (the MaskRom
recovery maneuver). flared's `devmem` now has a matching `Bus` seam and unit tests
that assert the shipped ladder pokes the confirmed offset, never the wrong-SoC one.
- **`modbus` — RS-485 device end.** Done. `ModbusSlave`: a byte-in/byte-out RTU slave
(CRC16 byte-identical to the master, FC 0x010x06/0x0F/0x10/0x11, exception replies,
and fault injection — silent-drop and forced-NAK) so `warden-modbus`'s master can be
hardened to MC/DC against realistic device behaviour with no serial hardware. MEI
(0x2B/0x0E) identification is the documented follow-up.
- **Next:** an **NPU** load model behind the path seam (deferred — no NPU feature
ships soon); a **GPIO/relay** sysfs model (largely covered by the `WARDEN_GPIO_ROOT`
seam in flare-edge's `tests/relays-mcdc/`); an **RGA** recording fake.
Integration with flare-edge: flared implements `MemBus` for `/dev/mem` and gains
`#[cfg(test)]` tests driving its real arm/beat logic against `HpmcuSim`. This needs