evidence · 9.2 KiB

backlight-bluetooth-rtc-board-test-plan.md

Committed at docs/evidence/backlight-bluetooth-rtc-board-test-plan.md. This is what grounds the requirements that cite it.

Open raw source

Board test plan: adjustable brightness, Bluetooth, persistent RTC

Branch feat/brightness-bt-rtc, based on master at df2dd84e. Three kernel/DT/Nix changes land together in this branch (one commit each): the-panel-brightness-is-adjustable, the-handheld-talks-bluetooth, the-clock-survives-a-reboot. All three are kernel and device-tree changes — they need a /boot install and a reboot, not just nixos-rebuild switch / activation. I have not touched the board; every command below is either a host build or something the coordinator runs on the board or over the serial console (/dev/ttyACM0). Board/serial-port reservation rules apply throughout (AGENTS.md): one operator at a time.

0. Build (host)

nix build .#kernel --max-jobs 1 --cores 6 --no-link --print-out-paths
nix build .#deviceTree --max-jobs 1 --cores 6 --no-link --print-out-paths
nix build .#sdImage-coherent --max-jobs 1 --cores 6 --no-link --print-out-paths
nix build .#nixosConfigurations.k230-coherent-shell.config.system.build.toplevel --max-jobs 1 --cores 6 --no-link --print-out-paths

Record the four store paths in the handoff. sdImage-coherent is the image to flash; toplevel is the same closure nixos-rebuild would converge to, useful for diffing what changed against the currently installed system.

1. Install and reboot

Per docs/uboot-ums.md/docs/evidence/usb-host-validation.md (already hardware-proven): flash sdImage-coherent via ums 0 mmc 1 + tools/flash-latest.sh --ums, or the card-reader fallback tools/flash-latest.sh /dev/disk/by-id/<reader-target>. Reboot. Confirm the new kernel is actually running before judging anything below:

./tools/console.py /dev/ttyACM0 --wait=3 "uname -a"

Cross-check the reported build against this branch’s commit.

2. Backlight (the-panel-brightness-is-adjustable)

./tools/console.py /dev/ttyACM0 --wait=3 "ls /sys/class/backlight"

Expected: exactly one device directory (e.g. canaan-dsi-backlight).

Failure signatures:

Write brightness at three points and camera-observe the panel each time (camera on the bench, not touch — this is a visual check, not something to judge by feel):

./tools/console.py /dev/ttyACM0 --wait=1 "cat /sys/class/backlight/*/max_brightness"
./tools/console.py /dev/ttyACM0 --wait=1 "echo 26 > /sys/class/backlight/*/brightness"   # ~10% of 255
./tools/console.py /dev/ttyACM0 --wait=1 "echo 128 > /sys/class/backlight/*/brightness"  # ~50%
./tools/console.py /dev/ttyACM0 --wait=1 "echo 255 > /sys/class/backlight/*/brightness"  # 100%

Expected: the panel visibly dims and brightens across the three writes, camera-observable.

Failure signatures:

Cycle a modeset or DPMS-style off/on and confirm the brightness set above (100%) is still in effect afterward, not the fixed 0xFE default:

./tools/console.py /dev/ttyACM0 --wait=2 "modetest -M canaan -s <connector-id>:1232x568 || true"
./tools/console.py /dev/ttyACM0 --wait=1 "cat /sys/class/backlight/*/actual_brightness"

(modetest from libdrm, already in environment.systemPackages per nix/hardware.nix; substitute the actual connector ID modetest -M canaan reports.)

Expected: actual_brightness unchanged from before the modeset, and the panel’s visible brightness matches.

Failure signature: brightness reverts to the fixed default after the cycle — the ctx->panel.backlight wiring (design.md decision 4) did not take effect, or drm_panel_enable()/disable() are not actually being called on this modeset path; check dmesg for the panel driver’s own dev_info lines around the cycle.

Also confirm the Settings stepper itself drives the device, once on real glass:

./tools/console.py /dev/ttyACM0 --wait=2 "su - shell -c 'k230-settings brightness 50'"
./tools/console.py /dev/ttyACM0 --wait=1 "cat /sys/class/backlight/*/actual_brightness"

Expected: {"state":"applied",...} from k230-settings, and actual_brightness at roughly 50% of max_brightness.

Failure signature: {"state":"failed","error":"brightness-denied",...} — the udev rule did not grant the shell group write access; check ls -l /sys/class/backlight/*/brightness for its group and mode.

3. Bluetooth (the-handheld-talks-bluetooth)

Plug the USB Bluetooth dongle into the board’s USB host port (see docs/uboot-usb-host-verdict.txt for confirmed host power/enumeration on this exact port).

./tools/console.py /dev/ttyACM0 --wait=2 "lsusb"
./tools/console.py /dev/ttyACM0 --wait=3 "bluetoothctl show"
./tools/console.py /dev/ttyACM0 --wait=12 "bluetoothctl scan on"
./tools/console.py /dev/ttyACM0 --wait=3 "btmgmt info"

Expected:

Failure signatures:

4. RTC (the-clock-survives-a-reboot)

./tools/console.py /dev/ttyACM0 --wait=2 "ls /dev/rtc0"
./tools/console.py /dev/ttyACM0 --wait=2 "hwclock -r"
./tools/console.py /dev/ttyACM0 --wait=2 "timedatectl"

Expected: /dev/rtc0 exists; hwclock -r reports a plausible current time (not an error, not the kernel’s compiled-in epoch); timedatectl shows RTC time populated and close to Universal time/Local time.

Failure signatures:

Reboot (warm reboot only — do not remove power for this step) and check again:

./tools/console.py /dev/ttyACM0 --wait=2 "reboot"
# wait for the board to come back, then:
./tools/console.py /dev/ttyACM0 --wait=3 "hwclock -r"

Expected: the time reported after reboot is consistent with (a few seconds later than) the time reported before reboot — not reset to the kernel’s compiled-in epoch.

Failure signature: the post-reboot hwclock -r jumps back to a epoch-adjacent implausible time — the RTC exists but is not actually retaining the value across even a warm reboot (a stronger negative result than the UNVERIFIED full-power-off case below); check systemctl status k230-rtc-sync from the previous boot’s journal (journalctl -b -1 -u k230-rtc-sync) to see whether it ran and succeeded before the reboot.

Left UNVERIFIED by this test plan: whether the clock survives a full power-off (main power removed, not merely a warm reboot). That needs a separate power-off-and-wait test with the result recorded against task 4.2 of the-clock-survives-a-reboot; do not infer it from the warm-reboot result above.