summaryrefslogtreecommitdiff
path: root/docs/superpowers/followup
diff options
context:
space:
mode:
authorHa Thach <[email protected]>2026-08-28 14:16:02 +0700
committerGitHub <[email protected]>2026-08-28 14:16:02 +0700
commiteca6caf673452c8ec940e2acf5e46d0631fb72bf (patch)
treece197bf019b29712095c3768c0fc23b26499cc79 /docs/superpowers/followup
parent4c7bb3ced98cb7262dd8eefd6c9f7df6e42ffcee (diff)
Add RTT console/capture tooling (tools/rtt.py), rtt skill, and HIL harness support (#3853)
Promote SEGGER RTT from an inline debugging technique to a standalone skill backed by one stdlib-only implementation in tools/rtt.py: a CLI and importable module for console/capture over J-Link (RTTTelnetPort) and OpenOCD (rtt server) probes, with probe selection by serial or VID:PID, control-block address via --elf or --addr, bidirectional console, post-mortem ring dump, and --reset-before-attach for boot-time capture. The HIL harness reads a board's console over RTT when its probe has no VCOM ("logger": "rtt" plus a LOGGER=rtt variant define), covering device_info, pool-check aliveness, and CI wiring. Validated on 22 boards across both backends; 26 unit tests run in pre-commit.
Diffstat (limited to 'docs/superpowers/followup')
-rw-r--r--docs/superpowers/followup/pr3853-board-putchar-logger.md57
-rw-r--r--docs/superpowers/followup/pr3853-rtt-harness-adoption.md62
2 files changed, 119 insertions, 0 deletions
diff --git a/docs/superpowers/followup/pr3853-board-putchar-logger.md b/docs/superpowers/followup/pr3853-board-putchar-logger.md
new file mode 100644
index 000000000..46a4417bd
--- /dev/null
+++ b/docs/superpowers/followup/pr3853-board-putchar-logger.md
@@ -0,0 +1,57 @@
+# `board_putchar` is not LOGGER-aware
+
+**Origin:** surfaced while validating the RTT console in PR #3853 (the `rtt` skill
+promotion), which is harness-only scope. This is a src-level fix to `hw/bsp/board.c`
+that touches every board/logger combination, so it needs its own build sweep rather
+than a drive-by. Delete this file when its own PR lands.
+
+## Established (with evidence)
+
+`hw/bsp/board.c` retargets stdio through `sys_write`/`sys_read`, which are compiled
+per logger: `SEGGER_RTT_Write`/`SEGGER_RTT_Read` under `LOGGER_RTT`, ITM under
+`LOGGER_SWO`, `board_uart_write`/`board_uart_read` by default. The two board-level
+character helpers do not agree:
+
+```c
+168: int board_getchar(void) {
+169: char c;
+170: return (sys_read(0, &c, 1) > 0) ? (int) c : (-1);
+171: }
+172:
+173: int board_putchar(int c) {
+174: if (board_uart_write((const char *)&c, 1) > 0) {
+```
+
+`board_getchar` follows the logger; `board_putchar` always goes to the UART. So with
+`LOGGER=rtt` console input arrives over RTT while the echo goes out the UART.
+
+Measured on ea4088_quickstart (`LOGGER=rtt`, `board_uart_write` is a `-1` stub on
+lpc40): the `board_test` echo vanishes entirely while a `printf` echo — same console,
+same keystroke — comes back byte-for-byte. `LOGGER=swo` has the same asymmetry by
+construction (ITM out of `sys_write`, UART out of `board_putchar`), unverified on
+hardware.
+
+## What remains
+
+Candidate fix: route `board_putchar` through `sys_write(0, ...)` for symmetry with
+`board_getchar`. Two things to settle while doing it:
+
+- `board_putchar` currently passes `&c` of an `int` to a `const char*` — it writes
+ the low byte only on little-endian. Narrow to a `char` local as part of the change.
+- The default (UART) path must keep its current return contract: `board_uart_write`
+ returns negative when the UART is a stub, and the default `sys_write` breaks out of
+ its retry loop on that, returning a short count — so `board_putchar` still has to
+ map "wrote nothing" to `-1`.
+
+## Validation
+
+Build sweep across loggers and families — at minimum one UART board, one
+`LOGGER=rtt` board and one `LOGGER=swo` board — plus a hardware check that the
+`board_test` echo comes back on an RTT board (ea4088_quickstart reproduces the bug
+today) and that a plain UART board's echo is unchanged.
+
+## Why it was split out
+
+PR #3853 promotes a debug-tooling skill and touches `test/hil/*.py` and
+`tools/rtt.py`. A `hw/bsp/board.c` change lands in every example on every board and
+belongs in a review that carries the build evidence for it.
diff --git a/docs/superpowers/followup/pr3853-rtt-harness-adoption.md b/docs/superpowers/followup/pr3853-rtt-harness-adoption.md
new file mode 100644
index 000000000..8f3eae16b
--- /dev/null
+++ b/docs/superpowers/followup/pr3853-rtt-harness-adoption.md
@@ -0,0 +1,62 @@
+# Follow-up: finish RTT-console adoption in the HIL harness
+
+Split out of the `rtt` skill-promotion PR #3853. That PR deliberately ships the skill + CLI and leaves the harness's remaining
+VCOM assumptions in place — converting them is separate test-infra scope that
+deserves its own review and HIL runs. Scope here is `test/hil/*.py` only; the
+src-level `board_putchar` asymmetry this work surfaced has its own handoff
+(`pr3853-board-putchar-logger.md`).
+
+## Established (with evidence)
+
+- `hil_util.JlinkRtt` + `open_board_console()` work end-to-end:
+ ea4088_quickstart runs its host suite over RTT (16 passed / 0 failed / 3
+ skipped, the 'hil: read the host console over RTT when the probe has no VCOM' commit), and the `rtt` skill's boards.md carries the
+ validated matrix.
+- `test_host_device_info` honors `"logger": "rtt"` (hil_test.py, `test_host_device_info`; the eof fail-fast assert sits in its read loop):
+ in RTT mode it resets via the flasher BEFORE opening the console (which
+ then owns the probe; Commander delivers the buffered boot burst) and its
+ read loop fails fast on `JlinkRtt.eof` instead of blaming the board.
+
+## Remaining gaps
+
+1. **`test_host_cdc_msc_hid` and `test_host_msc_file_explorer` (hil_test.py) still call `hil_util.get_serial_dev(flasher["uid"], ...)`
+ directly** — on a `logger: rtt` board with `is_cdc`/`is_msc` fixtures they
+ would fail with the same "No serial device found" the console work fixed
+ for device_info (an interim load-time gate in `hil_test.py` now rejects
+ that combination up front; delete the gate when this lands). Fix: route
+ both through `open_board_console(board)` — but design the conversion
+ reset-aware rather than hand-copying device_info's dual branch: hoist a
+ `reset=` parameter into `open_board_console` that does the per-console
+ ordering itself (RTT: reset via flasher BEFORE opening — the console owns
+ the probe; VCOM: reset after open to catch the banner), and REMOVE the
+ existing post-open `# reset device to catch mount messages` blocks in both
+ tests (grep the marker — line numbers churn) — kept as-is on an RTT board they reset
+ while the console holds the probe. `JlinkRtt` carries input for their
+ menus and implements the `reset_input_buffer()` those tests call.
+2. **`hil_pool_check.check_host_serial` carries its own inline RTT branch**
+ (reset → `JlinkRtt` → poll through `hil_util.strip_banner`) — RTT boards
+ ARE health-checkable today, but the console-opening logic now lives in
+ two places (`open_board_console` in hil_test.py and this branch), each
+ with its own reset-ordering. Fix: hoist `open_board_console()` into
+ `hil_util.py` with the `reset=` parameter from item 1 and collapse
+ pool_check's branch onto it; keep the `do_reset` flush semantics for the
+ VCOM path intact.
+3. **OpenOCD console backend in the harness**: the skill's CLI
+ (`tools/rtt.py --backend openocd`, class
+ `OpenocdRtt` in the same module) is built, deduplicated behind a shared
+ base class next to `JlinkRtt` in `tools/rtt.py`, re-exported by
+ `hil_util`, and hardware-validated (all 20 rig boards through the CLI on
+ both backends, incl. the 8 native-probe ones). What remains is only the
+ `open_board_console` plumbing: choosing `OpenocdRtt` for a
+ `"logger": "rtt"` board with an openocd/stlink flasher needs the per-test
+ flashed-ELF path (for the control-block address) and, for stlink
+ flashers, an openocd target-cfg mapping the roster doesn't carry — until
+ then the config-load gate keeps rejecting non-jlink rtt boards.
+
+## Validation for this follow-up
+
+Run the ea4088 local host suite (a board with a `is_cdc`+`is_msc` capable
+device attached to J3, or the rig's frdm_k64f/mimxrt1064 with a temporary
+`logger: rtt` entry) so cdc_msc_hid and msc_file_explorer actually execute
+over RTT; then a `hil_pool_check.py` pass on a no-VCOM board. Delete this doc
+when the follow-up PR lands.