From b7c80794b4ee6cdb56218349c2c5f5ebc3f2c705 Mon Sep 17 00:00:00 2001 From: pgdalmeida Date: Wed, 23 Sep 2026 23:39:28 +0200 Subject: [PATCH] Record the flash cost on the Delta board, and the reboot check on tower 121 --- docs/hardware-config-plan.md | 2 +- docs/known-issues.md | 2 +- docs/roadmap.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/hardware-config-plan.md b/docs/hardware-config-plan.md index 6a4afa6..ad2ece8 100644 --- a/docs/hardware-config-plan.md +++ b/docs/hardware-config-plan.md @@ -466,7 +466,7 @@ after the table. | 6 | Config handshake — **firmware half** | **done, and validated on tower 121.** `NEEDCFG` state (`ST` code `C`), `NEED` emitted with the banner, `SET `, `USE DEFAULTS`, and the init block split so the residual-motion stop still runs at boot. 33 native tests pass under `pio test -e native`. On the rig: the handshake was watched live, `HOME` refused with `ERR need config`, `RESET` did not escape the state, and `USE DEFAULTS` released it | | 6 | Adoption check generalised | **done**, 9 tests. `DUMP` echoes every host-owned value plus a `cfg_rx` bitmask; `test hardware motor` checks all of them, and reports an absent field as unconfirmable rather than as a mismatch against -1. Round trip NEED -> SET -> DUMP -> PASS verified against `mock_needcfg` | | 14 | Drivetrain out of `MOTOR_CONFIG` | **done.** The struct keeps pins and `homing_kind` only; `platform_iota.h` keeps its measurement record but no longer defines this tower's values. `USE DEFAULTS` now loads a shared **limp-home** set (`LIMP_*` in `config.h`) that is deliberately nobody's real values — slow speeds, generous margins, the gentle search current — so a tower still running them fails `test hardware motor` instead of looking configured. `SW_MODE` is derived from `homing_kind` rather than shared, because disabling the hardware stops on an axis that homes on real switches would remove its last protection. Flash cost, not saved: see the porting plan. Found a real bug on the way — `DIAG` read `normal_speed` / `center_speed` from the compile-time table, so it ran at compiled speeds rather than the tower's declared ones | -| 14 | Pins and `NUM_AXES` generated from `hardware.ini` | **done, validated on tower 121** (2026-09-23): built from its `/etc` file, flashed, `DUMP` echoed `spi=2,3,0 cs=1 en=4`, `IOIN version=0x30`, and `test hardware motor` passed `yaw_pins` / `spi_pins`; a build against a copy without `[Pins]` failed with the reason. Leonardo flash cost not yet measured. New `[Pins]` section; `firmware/tools/gen_wiring.py` generates `board_wiring.h` into the build directory from the tower's own file at build time, and refuses pins the board cannot use (RP2040 SPI0 groups, the Leonardo's fixed ICSP pins, duplicates, a board/env mismatch). No compiled-in fallback: no file or no `[Pins]` fails the build. `DUMP` echoes `cs=`/`en=` per axis and `spi=` on the RP2040; `test hardware motor` compares them with `[Pins]`. The loom tables moved to `hardware//pins.ini`. 18 generator tests (run without PlatformIO), 9 host tests | +| 14 | Pins and `NUM_AXES` generated from `hardware.ini` | **done, validated on tower 121** (2026-09-23): built from its `/etc` file, flashed, `DUMP` echoed `spi=2,3,0 cs=1 en=4`, `IOIN version=0x30`, and `test hardware motor` passed `yaw_pins` / `spi_pins`; a build against a copy without `[Pins]` failed with the reason. Leonardo: builds against a generated Delta `hardware.ini`; the pin echo costs **170 B of flash** (22,876 -> 23,046 B, 79.8% -> 80.4%, 5,626 B free) and no RAM - measured 2026-09-23, compile only, not yet flashed to a Delta. New `[Pins]` section; `firmware/tools/gen_wiring.py` generates `board_wiring.h` into the build directory from the tower's own file at build time, and refuses pins the board cannot use (RP2040 SPI0 groups, the Leonardo's fixed ICSP pins, duplicates, a board/env mismatch). No compiled-in fallback: no file or no `[Pins]` fails the build. `DUMP` echoes `cs=`/`en=` per axis and `spi=` on the RP2040; `test hardware motor` compares them with `[Pins]`. The loom tables moved to `hardware//pins.ini`. 18 generator tests (run without PlatformIO), 9 host tests | | 6 | `NEEDCFG` understood host-side | **done**, 5 tests. `AxisState::NeedConfig` parsed from `ST` `C`, named in `DUMP` and the dashboard, and counted as telemetry arriving rather than as a dead link. The firmware enum APPENDS the state (5) rather than inserting it — inserting renumbered every later state and made a READY axis read back as ERROR | **Validated on tower 121.** The handshake was watched live on the rig, not inferred: diff --git a/docs/known-issues.md b/docs/known-issues.md index 04cd886..0bafa7b 100644 --- a/docs/known-issues.md +++ b/docs/known-issues.md @@ -31,7 +31,7 @@ doctest unit-test suite (`ctest`). | 14 | Capture sweep on hardware | **Mechanically verified on the rig (2026-08-07).** A full `--init --start` run homed both axes and completed `MOVE → settle → trigger` for 15/15 waypoints with 0 dropped frames, 0 stalls and 0 acquisition failures. `kSettleTolCounts` (600) and the per-interval timing in [CaptureScheduler.cpp](../src/core/CaptureScheduler.cpp) have **not** been tuned against observed `ST` behaviour yet, and the settle tolerance has not been checked against a sharp image (see #16). | | 15 | **Camera profiles unverified on a lit scene** | The `standard`/`night` profiles must be exported from the VimbaX Viewer (see `config/camera_profiles/rgb/README.md`) and have not been measured against real light. Confirm on the rig that `LoadSettings` succeeds, that `standard` sustains 10 fps with `frames_dropped` at 0, and that the auto-exposure lands on a sensible `ExposureTime` outdoors. The only previous rig test ran with the lens covered. | | 16 | **`settle_wait_ms` untuned** | `standard` waits 1 s and `night` 2.5 s after standstill before keeping a frame. Both are reasoned (≫ one frame period; long enough for the auto-exposure to see the new scene) but not measured. Check on a lit scene that the kept frame shows no slew blur and that its exposure has actually converged for that heading, and shorten the wait if it has. | -| 19 | **USB preconditions do not survive a reboot** | `usbcore.usbfs_memory_mb` reverts to 16 (needs 1000) and USB3 LPM re-enables on the camera's port. **Both were wrong on the LattePanda when tested on 2026-08-07**, and frame delivery stalls without them regardless of application code. **Solved on tower 121 by the setup kit** (`hardware/lattepanda-iota/preconditions/`): a systemd-tmpfiles drop-in for usbfs and two udev rules, all installed by `install.sh --preconditions`. Verified 2026-09-23 — `usbfs_memory_mb` reads 1000 after **6 days of uptime**, so it survived the boot, and both rules are in `/etc/udev/rules.d/`. Note it is **tmpfiles, not the kernel cmdline** the original entry proposed. **Still open on the Delta fleet**, which has not had the kit applied. | +| 19 | **USB preconditions do not survive a reboot** | `usbcore.usbfs_memory_mb` reverts to 16 (needs 1000) and USB3 LPM re-enables on the camera's port. **Both were wrong on the LattePanda when tested on 2026-08-07**, and frame delivery stalls without them regardless of application code. **Solved on tower 121 by the setup kit** (`hardware/lattepanda-iota/preconditions/`): a systemd-tmpfiles drop-in for usbfs and two udev rules, all installed by `install.sh --preconditions`. Verified 2026-09-23 — `usbfs_memory_mb` reads 1000 after **6 days of uptime**, so it survived the boot, and both rules are in `/etc/udev/rules.d/`; and again across a deliberate reboot the same day, when `install-tower --verify` read `usbfs_memory_mb` 1000 and the camera port's `usb3_lpm_permit` 0 (a check `test hardware camera` now makes too, once `[Test] usb3_lpm_path` is set - the installer sets it). Note it is **tmpfiles, not the kernel cmdline** the original entry proposed. **Still open on the Delta fleet**: tower 111 read 16 and `u1_u2` on 2026-09-23. The Delta kit (`hardware/lattepanda-3-delta/`) carries the same two files, not yet applied. | ## Camera acquisition (USB3) — root cause + approach diff --git a/docs/roadmap.md b/docs/roadmap.md index 88904b1..d249307 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -19,9 +19,9 @@ Keep entries dated; move shipped items into the reference docs. metrics come off the firmware clock instead of host `ST` sampling; plus a `PING`/`PONG` link-health command for `test system link`. - ⚠️ **This collides with AVR flash headroom.** Three new commands are the - kind of growth the ATmega32U4 no longer has room for — it sits at **79.8 % - of its 28 KB** (5828 B free, measured 2026-09-23), up from 19254 B at the - phase 2 gate. The RP2040 is a non-issue at 0.6 % of 8 MB. So either these + kind of growth the ATmega32U4 no longer has room for — it sits at **80.4 % + of its 28 KB** (5626 B free, measured 2026-09-23 after the pin echo added + 170 B; 79.8 % before it), up from 19254 B at the phase 2 gate. The RP2040 is a non-issue at 0.6 % of 8 MB. So either these land RP2040-only behind the `platform_*.h` split, or the Delta fleet gets a deliberate answer on flash first — `PROGMEM` for the string tables, dropping a command, or accepting that the Delta is feature-frozen. Note §14 of the