diff options
| author | Ha Thach <[email protected]> | 2026-08-28 14:16:02 +0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-08-28 14:16:02 +0700 |
| commit | eca6caf673452c8ec940e2acf5e46d0631fb72bf (patch) | |
| tree | ce197bf019b29712095c3768c0fc23b26499cc79 /docs/superpowers/followup | |
| parent | 4c7bb3ced98cb7262dd8eefd6c9f7df6e42ffcee (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.md | 57 | ||||
| -rw-r--r-- | docs/superpowers/followup/pr3853-rtt-harness-adoption.md | 62 |
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. |
