docs: reposition as the 86 Panel development environment
The repo's documentation framed it as a support repo for one product (WardenOS). Since going public the real audience is anyone with a Luckfox Pico 86 Panel: a maintained 6.18 kernel, an off-device development loop, and a device simulator that exist nowhere else for this board. Reframe the README and top-level docs board-first, with WardenOS documented as the downstream consumer it is (ADR-0008). Also an editorial pass over the whole doc set: - every H1/H2 is now a short title, not a sentence (ADRs, qemu/, patches/, drivers/, architecture, NPU feasibility, config-lint, payload); workflow flowchart titles fixed at the source in tools/flowgen.py and regenerated with fresh bench numbers - README Quick Start commands verified against the scripts; requirements corrected (curl, bare python, gcc >= 14) and the MC/DC gate added as a step (run green locally on gcc 14.2) - dropped the 'needs python (not python3)' vendor dig: build-kernel.sh inherited the same requirement (filed #10 to remove it) - glossed MC/DC and HPMCU on first use; marked the tests/uboot-ab reference as flare-edge; deduplicated the three-simulator list into the root README table
This commit is contained in:
@@ -5,133 +5,125 @@
|
||||

|
||||

|
||||
|
||||
The build, driver, and simulation SDK for WardenOS (the Luckfox Pico 86-Panel /
|
||||
RV1106 HMI). A from-scratch replacement for the twice-ported vendor stack
|
||||
(Rockchip SDK → Luckfox SDK → our patched fork), built to the same standard as
|
||||
the rest of the firmware: tested, benchmarked, reproducible, and honest about
|
||||
what runs on real silicon versus what we simulate.
|
||||
A modern, open development environment for the **Luckfox Pico 86 Panel**
|
||||
(Rockchip RV1106): a current Linux kernel as a reviewable patch series, a
|
||||
hermetic build, a QEMU device simulator, register-level hardware models, and
|
||||
MC/DC-hardened drivers (Modified Condition/Decision Coverage — the
|
||||
avionics-grade test bar). It replaces the vendor stack — a ~2 GB, twice-forked
|
||||
SDK pinned to Linux 5.10 — with tooling that is tested, benchmarked,
|
||||
reproducible, and honest about what runs on real silicon versus what is
|
||||
simulated.
|
||||
|
||||
> Status: **bringup.** The hardware **simulator** and its tests, the RV1106 kernel
|
||||
> forward-port as a reviewable `patches/` series, the hermetic kernel build, two
|
||||
> Tier-1 drivers at 100% MC/DC, and the **QEMU device sim** (`qemu/`, ADR-0006:
|
||||
> boots the real kernel + real userspace on `-M virt` — check-in/OTA against the
|
||||
> mock portal, watchdog, RS485-to-sim bridge, 720x720 display + touch, all
|
||||
> emulation-verified) are in. What remains before this is on the production build
|
||||
> path: having flare-edge consume warden-sdk as a dependency (maintainer-gated).
|
||||
> Until then, flare-edge still builds firmware from the vendored SDK +
|
||||
> `sdk-patches/`.
|
||||
Originally built as the SDK for WardenOS (BlueFlare Energy's wall-panel
|
||||
firmware), but nothing here requires it: if you have an 86 Panel, this repo
|
||||
gives you a modern kernel and a way to develop for the board without flashing
|
||||
it on every change.
|
||||
|
||||
## Why a new SDK
|
||||
## Why
|
||||
|
||||
The vendored SDK is a ~2 GB opaque fork of a fork. Our real changes to it lived,
|
||||
until recently, as uncommitted edits in one working copy (`flare-edge/sdk-patches/`
|
||||
is the tracked form). It bakes absolute paths, needs `python` (not python3),
|
||||
silently drops Kconfig options, and — the failure that motivated this repo — gives
|
||||
us **no way to test hardware-dependent code off the device.** Every driver change
|
||||
had to be validated by flashing a panel. That is slow, and it is dangerous: it is
|
||||
how a boot-loaded-watchdog change bricked a bench unit (the load address collided
|
||||
with unreserved kernel RAM — a mistake a target-config check or a memory-map model
|
||||
would have caught before any flash).
|
||||
The vendor SDK bakes in absolute paths, silently drops Kconfig options, and
|
||||
offers **no way to test hardware-dependent
|
||||
code off the device** — every change means flashing a panel. That is slow and
|
||||
occasionally destructive: a coprocessor load address that collided with
|
||||
unreserved kernel RAM bricked a bench unit, a mistake a static memory-map
|
||||
check would have caught before any flash (`tools/config-lint` now is that
|
||||
check). This SDK exists so the board is buildable, testable, and hardenable
|
||||
**without a panel in the loop**, on a maintained kernel.
|
||||
|
||||
The SDK's job is to make the firmware **buildable, testable, and hardenable
|
||||
without a panel in the loop**, and to move us onto a modern, maintained kernel.
|
||||
## What Works
|
||||
|
||||
## Goals (from future-features)
|
||||
A self-built **Linux 6.18.46**, forward-ported from the vendor 5.10.160 tree
|
||||
as a subsystem-split patch series (`patches/`) and hardware-verified on a
|
||||
bench panel: clk, pinctrl, eMMC, GMAC, TRNG, OTP, SARADC/TSADC, RTC, USB
|
||||
host, PWM/backlight, VOP display, GT911 touch, AIC8800 wifi, RGA, I2S audio,
|
||||
the HPMCU (RISC-V watchdog coprocessor) mailbox, the open NPU driver, and
|
||||
PVTM. Mainline alone was not
|
||||
viable (no RV1106 device tree, clock, display, RGA, NPU, or flash-boot support
|
||||
upstream); see `docs/decisions/0001-kernel-base.md`.
|
||||
|
||||
1. **Modern kernel.** A self-built **Linux 6.18.46**, forward-ported directly from
|
||||
the vendor 5.10.160 tree (no plan44/OpenWrt code) on our current Buildroot LTS
|
||||
(2025.02.x). This is **done and hardware-verified on `warden-c8a3`**: essentially
|
||||
every RV1106 block the 86-Panel uses boots and works — clk, pinctrl, eMMC, GMAC,
|
||||
TRNG, OTP, SARADC/TSADC, RTC, USB host, PWM/backlight, **VOP display**, **GT911
|
||||
touch**, **AIC8800 wifi**, **RGA**, **I2S audio**, **HPMCU mailbox**, the **open
|
||||
NPU driver**, and **PVTM**. Mainline was not viable (no DT/clk/display/RGA/NPU/
|
||||
flash-boot upstream for RV1106); the direct 5.10→6.18 forward-port reuses the
|
||||
already-in-mainline rv1126 register data where it matches and carries our deltas
|
||||
as a reviewable patch series (`patches/`).
|
||||
2. **Ported, hardened drivers → 100% MC/DC on the code we own.** "100% MC/DC on
|
||||
100% of drivers" is infeasible as literally stated: ~97% of driver LOC is
|
||||
vendor blobs (the AIC8800 wifi driver alone is 88.5K lines). So the target is
|
||||
**tiered**: real MC/DC on *our* hardware code (modbus master, relays, RGA
|
||||
wrapper, HPMCU supervisor, devmem/reset ladder); fault-injection + branch
|
||||
hardening for the vendor blobs behind a stable seam.
|
||||
3. **A proper simulator.** Simulate the hardware the vendor SDK cannot: **RGA**
|
||||
(2D blitter), the **RISC-V HPMCU** coprocessor, and the **NPU** — plus the
|
||||
register/SRAM (`/dev/mem`) and sysfs surfaces the drivers touch — so driver and
|
||||
supervisor logic runs and is tested on the host, in CI, with no panel.
|
||||
4. **Its own repo, held to firmware standards.** Tests, benchmarks, reproducible
|
||||
builds, CI. This repo.
|
||||
## Quick Start
|
||||
|
||||
## Architecture — one seam, two backends
|
||||
Requirements: `gcc-arm-linux-gnueabihf`, `qemu-system-arm`, `curl`, `cpio`,
|
||||
`mkfs.ext4`, a bare `python` on PATH (Debian/Ubuntu: `python-is-python3`),
|
||||
gcc >= 14 (for the MC/DC gate), and Rust (for the simulators' tests).
|
||||
|
||||
The organizing idea is a thin **Hardware Abstraction Seam** per hardware block.
|
||||
Firmware code talks to the seam (a trait in Rust, a function table in C); the seam
|
||||
has two backends:
|
||||
```sh
|
||||
# 1. Build the kernel: fetch pinned pristine 6.18.46, apply patches/, emit
|
||||
# zImage + rv1106-warden.dtb. WORK must sit outside any git checkout.
|
||||
WORK=$HOME/kbuild-out CROSS_COMPILE=arm-linux-gnueabihf- bash build/build-kernel.sh
|
||||
|
||||
```
|
||||
firmware / driver logic
|
||||
│
|
||||
Hardware Abstraction Seam (devmem, hpmcu, rga, npu, modbus, gpio)
|
||||
┌────┴────┐
|
||||
real backend sim backend
|
||||
(/dev/mem, ioctl, (software model,
|
||||
/proc, serial) host-testable)
|
||||
# 2. Boot it in the QEMU device simulator (no hardware needed):
|
||||
bash qemu/mkinitramfs.sh
|
||||
bash qemu/mkimage.sh
|
||||
bash qemu/run.sh --kernel $HOME/kbuild-out/linux-6.18.46/arch/arm/boot/zImage --shell
|
||||
|
||||
# 3. Run the test suites:
|
||||
for d in sim tools/config-lint qemu/rs485-bridge; do
|
||||
(cd "$d" && cargo test)
|
||||
done
|
||||
for d in drivers/*/test; do make -C "$d" check; done # 100% MC/DC gate (gcc >= 14)
|
||||
```
|
||||
|
||||
- **On-device**, the seam binds the real backend (mmap `/dev/mem`, `librga`
|
||||
ioctls, the serial port, `/proc/rknpu`).
|
||||
- **On the host**, it binds the **sim backend** — a faithful software model of the
|
||||
block. The HPMCU sim, for example, runs the SCR1 watchdog firmware's exact state
|
||||
machine (boot-grace, heartbeat-timeout, fire) against an in-memory mailbox, so
|
||||
the flared supervisor's arm/beat protocol is exercised end-to-end in a unit test.
|
||||
|
||||
The seam is the same object the driver-hardening effort measures MC/DC against,
|
||||
and the same object the simulator implements — so the two goals reinforce rather
|
||||
than duplicate each other.
|
||||
The kernel variant with the simulator's extra devices (PCI serial, watchdog,
|
||||
WireGuard, display) adds one env var to step 1:
|
||||
`WARDEN_KCONFIG_FRAGMENT=qemu/configs/virt.fragment`. See `qemu/README.md`
|
||||
for the scenario tests (portal, OTA apply, display + touch, watchdog).
|
||||
|
||||
## Layout
|
||||
|
||||
```
|
||||
sim/ the hardware simulator (Rust): membus/devmem, HPMCU, CRU, Modbus, RGA, NPU.
|
||||
qemu/ the device simulator (ADR-0006): QEMU -M virt boots the real kernel and
|
||||
real userspace; A/B disk layout, RS485 bridge into sim/, scenario tests.
|
||||
drivers/ our own hardened drivers + their seams (relays, freshness; more migrate in).
|
||||
patches/ the RV1106 kernel forward-port delta onto pristine linux-6.18.46 (subsystem-split).
|
||||
kernel/ forward-port docs + provenance (rv1106-enablement/, PROVENANCE.md).
|
||||
build/ the hermetic kernel build (fetch pristine → apply patches → zImage + dtb).
|
||||
docs/ architecture + ADRs (decisions/) + ci-cd + generated workflow flowcharts.
|
||||
tools/ dev tooling. config-lint: static target-config gates (MCU-load-vs-reserved-memory,
|
||||
the 0x40000 brick class); flowgen: the workflow-flowchart generator.
|
||||
.github/ CI (workflows/ci.yml): patches-apply, host tests, coverage, MC/DC, benchmarks, badges.
|
||||
patches/ the RV1106 forward-port onto pristine linux-6.18.46 (subsystem-split)
|
||||
build/ the hermetic kernel build (fetch pinned source -> apply patches -> zImage + dtb)
|
||||
qemu/ the device simulator: QEMU -M virt boots the real kernel and real userspace;
|
||||
A/B disk layout, RS485 bridge into sim/, scenario tests
|
||||
sim/ register-level hardware models (Rust): membus, HPMCU, CRU, Modbus, RGA, NPU
|
||||
drivers/ hardened hardware-facing drivers with HAL seams and 100% MC/DC harnesses
|
||||
kernel/ forward-port provenance and bring-up records (point-in-time; patches/ is canonical)
|
||||
tools/ config-lint (static memory-map gates) and dev tooling
|
||||
docs/ architecture, ADRs (decisions/), CI/CD
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
One thin **hardware abstraction seam** per block (a trait in Rust, a function
|
||||
table in C). Firmware logic talks to the seam; the seam binds a real backend
|
||||
on the device (`/dev/mem`, ioctls, serial, `/proc`) or a simulated backend on
|
||||
the host. The same seam is what the driver-hardening effort measures MC/DC
|
||||
against and what the simulator implements, so the two reinforce rather than
|
||||
duplicate each other. Full detail: `docs/architecture.md`.
|
||||
|
||||
Three simulators, by design not one:
|
||||
|
||||
| Simulator | What it runs | What it proves |
|
||||
|---|---|---|
|
||||
| `sim/` | register-level Rust models | driver and supervisor logic, with fault injection |
|
||||
| `qemu/` | the real kernel + real userspace on `-M virt` | boot, init, daemons, networking, OTA, watchdog, display + touch |
|
||||
| `lvglsim` (downstream) | the LVGL UI on SDL | rendering and UI flows |
|
||||
|
||||
Boots and passes under emulation are never treated as on-silicon evidence;
|
||||
the simulators narrow which claims need a panel, they do not replace it.
|
||||
|
||||
## Principles
|
||||
|
||||
Evaluated against the stack philosophy — **openness, hardness, modernness**:
|
||||
- **Open**: open tools over closed ones (`rkdeveloptool`, source-built
|
||||
components, an open simulator); GPL-2.0-only.
|
||||
- **Hard**: every seam has a fault-injection path — recovery code is tested
|
||||
against failure, not just success.
|
||||
- **Modern**: the newest kernel the hardware can run, current toolchains,
|
||||
Rust for new host-testable code, reproducible builds.
|
||||
|
||||
- **Open** over closed where we can: `rkdeveloptool` over the closed `upgrade_tool`;
|
||||
source-buildable `librga` over blobs where a source path exists; the simulator is
|
||||
fully open and ours.
|
||||
- **Hard**: every seam has a fault-injection path (a wedged SDIO link, a stalled
|
||||
MCU, an RGA timeout) so recovery code is tested against failure, not just success.
|
||||
On-device claims still need on-device evidence; the sim narrows *which* claims
|
||||
need a panel, it does not replace that rule.
|
||||
- **Modern**: newest kernel we can actually run; current Buildroot LTS; Rust for new
|
||||
host-testable code; reproducible builds.
|
||||
## Downstream
|
||||
|
||||
## Relationship to flare-edge
|
||||
|
||||
flare-edge (WardenOS: the LVGL UI + the `flared` daemon) is the product; warden-sdk
|
||||
is what builds and tests it. flare-edge is BlueFlare's private companion repo —
|
||||
not publicly available — so flare-edge issue references and checkout paths in
|
||||
this repo's docs are context, not reachable links. During bootstrap, flare-edge consumes warden-sdk piece
|
||||
by piece: first the simulator (as a dev/test dependency), later the image build.
|
||||
No flare-edge code moves here — only the SDK/build/sim/driver-seam layer.
|
||||
WardenOS (the 86 Panel firmware this SDK was born for) consumes warden-sdk
|
||||
from its own private repo, flare-edge; issue references and checkout paths
|
||||
pointing there are context, not reachable links. The QEMU simulator runs its
|
||||
production binaries unmodified — including real over-the-air updates against
|
||||
a mock portal.
|
||||
|
||||
## License
|
||||
|
||||
**GPL-2.0-only**, repo-wide (see `LICENSE`; a per-file SPDX identifier governs
|
||||
where one is present, e.g. a few GPL-2.0-or-later kernel files). The kernel
|
||||
material in `patches/` and `kernel/rv1106-enablement/` is derivative of the
|
||||
Linux kernel and of GPL-2.0 vendor code either way — per-driver origin and
|
||||
license are tracked in `kernel/rv1106-enablement/PROVENANCE.md`. Contributions
|
||||
are accepted under the same license (inbound = outbound).
|
||||
**GPL-2.0-only**, repo-wide (see `LICENSE`; a per-file SPDX identifier
|
||||
governs where present). The kernel material in `patches/` and `kernel/` is
|
||||
derivative of the Linux kernel and GPL-2.0 vendor code; per-driver origin is
|
||||
tracked in `kernel/rv1106-enablement/PROVENANCE.md`. Contributions are
|
||||
accepted under the same license (inbound = outbound).
|
||||
|
||||
Reference in New Issue
Block a user