docs: ASCII typography and style normalization across all repo text
Replace every em dash with real punctuation (rewrites, not hyphen swaps) in docs, code comments, scripts, configs, and the port records; convert en dashes, curly quotes, ellipsis glyphs, arrows, and section signs to ASCII; drop machine-writing tell phrases from living docs. ADR titles now use a colon. The M2 bring-up DTS model string carried an em dash into the patch series and its record echoes; fixed at both, and the full series re-verified to apply cleanly onto pristine 6.18.46. One comment in freshness.h deliberately names the em dash glyph the UI renders as the unknown mark; that is data, kept as prose naming it. Verified: cargo tests (sim, config-lint, rs485-bridge), shellcheck, both driver MC/DC harnesses, patches-apply.
This commit is contained in:
+36
-36
@@ -2,7 +2,7 @@
|
||||
|
||||
How the SDK makes the 86 Panel buildable, testable, and hardenable without a
|
||||
board in the loop. The seam inventory below comes from a full survey of the
|
||||
downstream WardenOS firmware — the SDK's first consumer — not aspiration; the
|
||||
downstream WardenOS firmware (the SDK's first consumer), not aspiration; the
|
||||
file paths in it point into that (private) codebase and serve as engineering
|
||||
context.
|
||||
|
||||
@@ -13,19 +13,19 @@ tested (or not) differently. Today:
|
||||
|
||||
| Block | Where | Access | Test seam today | Fails on host by |
|
||||
|---|---|---|---|---|
|
||||
| Registers / SRAM (CRU reset, HPMCU mailbox) | `flared/src/devmem.rs`, `hpmcu.rs` | `/dev/mem` mmap `peek/poke32` | **none** — zero tests | (would fault; not exercised) |
|
||||
| Registers / SRAM (CRU reset, HPMCU mailbox) | `flared/src/devmem.rs`, `hpmcu.rs` | `/dev/mem` mmap `peek/poke32` | **none**, zero tests | (would fault; not exercised) |
|
||||
| HPMCU / RISC-V coproc | `flared/src/hpmcu.rs` | via devmem + firmware blob load | `WARDEN_HPMCU_FW` redirects the blob path only | env gate disables it |
|
||||
| NPU load | `ui-src/.../sysmon.c` | read `/proc/rknpu/load` | **none** — literal path | file absent → "NPU absent" |
|
||||
| RGA (2D blit) | `ui-src/.../warden_rga.c` | `librga improcess` + dma-heap ioctl | compile-time `#if WARDEN_USE_RGA` | `#if` off → LVGL software path |
|
||||
| NPU load | `ui-src/.../sysmon.c` | read `/proc/rknpu/load` | **none**, literal path | file absent -> "NPU absent" |
|
||||
| RGA (2D blit) | `ui-src/.../warden_rga.c` | `librga improcess` + dma-heap ioctl | compile-time `#if WARDEN_USE_RGA` | `#if` off -> LVGL software path |
|
||||
| RS485 daemon | `warden-modbus/modbus_engine.c` | `open("/dev/ttyS4")` | recompile `-DRS485_PORT=<pty>` | (recompiled for a pty) |
|
||||
| RS485 panel client | `ui-src/.../modbus.c` | `AF_UNIX` socket | `WARDEN_MODBUS_SOCK` env override | socket absent → "unavailable" |
|
||||
| Relays / GPIO | `ui-src/.../relays.c` | `/sys/class/gpio` sysfs | **none** — literal paths | path absent → "unavailable" |
|
||||
| RS485 panel client | `ui-src/.../modbus.c` | `AF_UNIX` socket | `WARDEN_MODBUS_SOCK` env override | socket absent -> "unavailable" |
|
||||
| Relays / GPIO | `ui-src/.../relays.c` | `/sys/class/gpio` sysfs | **none**, literal paths | path absent -> "unavailable" |
|
||||
| Slot metadata | `flared/src/slotctl.rs` | `misc` partition + `/proc/cmdline` | `WARDEN_MISC_DEV`, `WARDEN_CMDLINE_FILE` env overrides | (redirected to scratch files) |
|
||||
|
||||
Three patterns coexist: **compile-time `#if`** (RGA), **env-override**
|
||||
(modbus socket, misc dev, cmdline, hpmcu fw), and
|
||||
**fails-soft-when-the-path-is-absent** (NPU, relays, devmem-would-fault). The
|
||||
last is not a test seam — you can inject "absent", never "relay 1 is ON" or
|
||||
last is not a test seam: you can inject "absent", never "relay 1 is ON" or
|
||||
"NPU at 80%". The SDK's job: **one deliberate seam per block**, each with a
|
||||
real backend and a sim backend.
|
||||
|
||||
@@ -33,14 +33,14 @@ real backend and a sim backend.
|
||||
|
||||
Two seam kinds cover everything above:
|
||||
|
||||
- **Register/SRAM seam → a trait.** `MemBus` (`sim/src/membus.rs`):
|
||||
- **Register/SRAM seam -> a trait.** `MemBus` (`sim/src/membus.rs`):
|
||||
`peek32/poke32` at a physical address. Real backend = flared `devmem.rs`
|
||||
mmap; sim backend = `SimBus`. The HPMCU watchdog and the CRU reset ladder
|
||||
both ride this. **Built.**
|
||||
- **Resource-path seam → env-override + injection.** Every device/proc/sys
|
||||
- **Resource-path seam -> env-override + injection.** Every device/proc/sys
|
||||
path a driver opens resolves through one indirection
|
||||
(`warden_hw_path("npu.load")` in C, an env-overridable const in Rust) —
|
||||
generalizing the existing `WARDEN_MISC_DEV`/`WARDEN_MODBUS_SOCK` pattern —
|
||||
(`warden_hw_path("npu.load")` in C, an env-overridable const in Rust),
|
||||
generalizing the existing `WARDEN_MISC_DEV`/`WARDEN_MODBUS_SOCK` pattern,
|
||||
so a test points it at a fake file/fifo the sim writes. No LD_PRELOAD, no
|
||||
fake mounts.
|
||||
|
||||
@@ -58,36 +58,36 @@ and supervisor logic runs in CI with no panel. All models are **done**:
|
||||
|---|---|
|
||||
| `membus` | `MemBus` trait + `SimBus` in-memory bus (`Clone`, so two "cores" alias shared memory) |
|
||||
| `hpmcu` | the watchdog coprocessor's state machine (boot-grace, heartbeat-timeout, disarm, fire) on a `SimBus` mailbox with a virtual clock; 7 tests incl. the arm-within-grace no-boot-loop safety property |
|
||||
| `cru` | reset ladder against the known glb_srst_fst / DW-watchdog registers, plus boot-mode register semantics (survives warm reset, cleared by POR — the MaskRom recovery maneuver) |
|
||||
| `modbus` | byte-in/byte-out RTU slave: CRC16 byte-identical to the master, FC 0x01–0x06/0x0F/0x10/0x11, exception replies, silent-drop and forced-NAK fault injection; doubles as the QEMU sim's field bus via `qemu/rs485-bridge/` (§7) |
|
||||
| `npu` | `/proc/rknpu/load` text model behind the path seam — the load-readout UI is host-testable; NPU *compute* is out of scope |
|
||||
| `cru` | reset ladder against the known glb_srst_fst / DW-watchdog registers, plus boot-mode register semantics (survives warm reset, cleared by POR, the MaskRom recovery maneuver) |
|
||||
| `modbus` | byte-in/byte-out RTU slave: CRC16 byte-identical to the master, FC 0x01-0x06/0x0F/0x10/0x11, exception replies, silent-drop and forced-NAK fault injection; doubles as the QEMU sim's field bus via `qemu/rs485-bridge/` (section 7) |
|
||||
| `npu` | `/proc/rknpu/load` text model behind the path seam; the load-readout UI is host-testable; NPU *compute* is out of scope |
|
||||
| `rga` | recording `improcess` fake with programmable `IM_STATUS`, exercising offload-dispatch and CPU-fallback; wired into the `rga_improcess` benchmark |
|
||||
|
||||
**Next:** MEI (0x2B/0x0E) Modbus identification; the Tier-2 driver *sources*
|
||||
migrate in with the flare-edge unification (ADR-0005) — their hardware ends
|
||||
migrate in with the flare-edge unification (ADR-0005); their hardware ends
|
||||
are already modelled here.
|
||||
|
||||
**Integration with flare-edge — landed 2026-08-31** (flare-edge PR #110):
|
||||
**Integration with flare-edge, landed 2026-08-31** (flare-edge PR #110):
|
||||
`warden-sim` is a flared dev-dependency (through the vendored submodule), and
|
||||
unification tests in flared's own suite pin its real arm/beat and
|
||||
reset-ladder logic to `HpmcuSim`/`CruSim`.
|
||||
|
||||
## 4. Driver Hardening
|
||||
|
||||
"100% MC/DC on 100% of drivers" is infeasible literally — ~97% of driver LOC
|
||||
is vendor blobs (AIC8800 wifi alone is 88.5K lines) — so the target is
|
||||
"100% MC/DC on 100% of drivers" is infeasible literally (~97% of driver LOC
|
||||
is vendor blobs; AIC8800 wifi alone is 88.5K lines), so the target is
|
||||
tiered:
|
||||
|
||||
- **Tier 1 — our own hardware code → real 100% MC/DC.** Extract the unit
|
||||
- **Tier 1, our own hardware code -> real 100% MC/DC.** Extract the unit
|
||||
behind a small injectable seam, mock its world, build
|
||||
`-fcondition-coverage`, enforce via the shared `drivers/enforce-mcdc.sh`
|
||||
(gcc-14 `gcov --conditions`) in the CI `mcdc` job — the proven flare-edge
|
||||
`tests/uboot-ab` method. **Done:** `relays.c` (40/40 conditions) and
|
||||
(gcc-14 `gcov --conditions`) in the CI `mcdc` job (the proven flare-edge
|
||||
`tests/uboot-ab` method). **Done:** `relays.c` (40/40 conditions) and
|
||||
`freshness.c` (66/66). **Next in:** the modbus master and the RGA
|
||||
dispatch, with the ADR-0005 unification (`drivers/README.md`).
|
||||
- **Tier 2 — near-mainline small drivers → branch coverage + fault
|
||||
- **Tier 2, near-mainline small drivers -> branch coverage + fault
|
||||
injection.**
|
||||
- **Tier 3 — vendor blobs (AIC8800, MPP/ISP/RGA libs) → fault-injection
|
||||
- **Tier 3, vendor blobs (AIC8800, MPP/ISP/RGA libs) -> fault-injection
|
||||
hardening behind the seam**, not MC/DC: e.g. the SDIO-wedge recovery is
|
||||
tested against an injected wedge; the blob itself is untestable.
|
||||
|
||||
@@ -99,11 +99,11 @@ against failure, not just the happy path.
|
||||
|
||||
The brick was a *memory-map* fault: the boot-loaded MCU's load address
|
||||
(`0x40000`) is a reserved carve-out on Thunder-Boot boards but plain kernel
|
||||
RAM on the 86 Panel. No behavioural sim catches that — it takes a **static
|
||||
RAM on the 86 Panel. No behavioural sim catches that; it takes a **static
|
||||
check against the target devicetree**, owned here as CI gates so mistakes
|
||||
are caught before a flash, not on the bench.
|
||||
|
||||
- **Built:** `tools/config-lint` — every `LOADERn=Hpmcu` `LOAD_ADDR` in the
|
||||
- **Built:** `tools/config-lint`: every `LOADERn=Hpmcu` `LOAD_ADDR` in the
|
||||
rkbin loader `.ini` must land inside a DT `reserved-memory` range. Its
|
||||
test suite encodes the c8a3 brick itself (see its README).
|
||||
- **Next:** partition-table-vs-image-size; vermagic-vs-kernel.
|
||||
@@ -116,11 +116,11 @@ in the README's "What Works" boots.
|
||||
- **Base:** a direct forward-port of the vendor 5.10.160 tree onto pristine
|
||||
6.18.46, keeping the Buildroot LTS/uClibc userspace.
|
||||
- **Not plan44/OpenWrt 6.6** (ADR-0001): that fork swaps Buildroot for
|
||||
OpenWrt/musl and ships no AIC8800 kmod — a platform swap, not a port.
|
||||
OpenWrt/musl and ships no AIC8800 kmod; a platform swap, not a port.
|
||||
- **Not mainline alone:** no RV1106 DT/clk/display/RGA/NPU/flash-boot
|
||||
upstream; already-mainline rv1126 register data is reused where it
|
||||
matches.
|
||||
- **Dominant risk** was the struct-ABI break (the VLAN saga) — mitigated by
|
||||
- **Dominant risk** was the struct-ABI break (the VLAN saga), mitigated by
|
||||
shipping kernel moves as one matched boot+oem image, never a partial
|
||||
reflash.
|
||||
- **Kept honest** by the hermetic `build/build-kernel.sh` and the
|
||||
@@ -129,7 +129,7 @@ in the README's "What Works" boots.
|
||||
|
||||
## 7. Device Emulation
|
||||
|
||||
A QEMU VM (`-M virt,highmem=off`, one Cortex-A7, 256M — the RV1106G3's
|
||||
A QEMU VM (`-M virt,highmem=off`, one Cortex-A7, 256M: the RV1106G3's
|
||||
shape) boots the real forward-ported kernel and real userspace, entering at
|
||||
`-kernel zImage`: everything below is closed rkbin blobs plus mask ROM.
|
||||
Details, scenarios, and the emulated-vs-not table: `qemu/README.md` and
|
||||
@@ -146,21 +146,21 @@ ADR-0006.
|
||||
`sim/`, and the VM consumes it.
|
||||
- Division of labour: NPU/RGA/HPMCU *behavior* stays `sim/`; UI *rendering
|
||||
development* stays `lvglsim`; the VM is where processes, the kernel, and
|
||||
the network meet. §5 still applies — no behavioural sim catches memory-map
|
||||
faults — and "boots under emulation" is never on-silicon evidence.
|
||||
the network meet. section 5 still applies (no behavioural sim catches memory-map
|
||||
faults), and "boots under emulation" is never on-silicon evidence.
|
||||
|
||||
## 8. Order of Work
|
||||
|
||||
1. **Simulator core** — `membus`, `hpmcu`, `cru`, `modbus`, `rga`, `npu`.
|
||||
1. **Simulator core**: `membus`, `hpmcu`, `cru`, `modbus`, `rga`, `npu`.
|
||||
**Done.**
|
||||
2. **C-driver MC/DC harnesses** — `relays.c` + `freshness.c` at 100%,
|
||||
2. **C-driver MC/DC harnesses**: `relays.c` + `freshness.c` at 100%,
|
||||
CI-gated. **Done.**
|
||||
3. **flared devmem/hpmcu seam + tests** — unified with `sim/`. **Done**
|
||||
3. **flared devmem/hpmcu seam + tests**: unified with `sim/`. **Done**
|
||||
(2026-08-31, flare-edge PR #110).
|
||||
4. **Config-lint CI gates** (§5) — the brick class of bug. **Done.**
|
||||
4. **Config-lint CI gates** (section 5): the brick class of bug. **Done.**
|
||||
5. **Hermetic kernel build** + the `patches-apply` gate. **Done.**
|
||||
6. **Kernel 5.10 → 6.18.46 forward-port** (§6, ADR-0001). **Done**
|
||||
6. **Kernel 5.10 -> 6.18.46 forward-port** (section 6, ADR-0001). **Done**
|
||||
(hardware-verified).
|
||||
7. **QEMU device sim** (§7, ADR-0006) — boot smoke, A/B disk harness, RS485
|
||||
7. **QEMU device sim** (section 7, ADR-0006): boot smoke, A/B disk harness, RS485
|
||||
bridge, portal/watchdog/clock/OTA scenarios, display+touch, real-image
|
||||
boot. **Done** (emulation-verified).
|
||||
|
||||
Reference in New Issue
Block a user