Repository navigation
Tracking: hw hardware-report command — state and handoff #10
Description
Living state for the hw work. Updated as it progresses; read this first when picking the task back up.
Current state
PR #1 (work/hw-cli → dev) — the single iteration branch. Everything lands here; clean upstream branches get cherry-picked out later.
Review loop: 7 rounds driven to zero unresolved threads, every suppressed finding answered in the PR conversation. 15 findings total, all judged against the code — 14 fixed, 1 declined with evidence.
What hw does
Reports what the firmware is and what hardware it actually found, on a stock release build where every MESH_DEBUG_* call is compiled away.
hw summary
hw board board target, SoC, Zephyr + firmware version, role, bootloader, reset cause, device id
hw rtc declared RTC candidates and the boot probe outcome for each
hw i2c devicetree-declared I2C inventory (no bus traffic)
hw i2c scan live 0x08-0x77 bus scan, naming declared addresses
hw gps GNSS driver, transport and wiring
hw sensors sensor availability and channels
hw all every section
Because ZephCore's companion routes through CommonCLI rather than carrying its own command table, one implementation reaches all four roles.
Validation
| Path | Status |
|---|---|
| nRF52 repeater, local USB serial | validated on hardware |
| nRF52 repeater, remote admin over the mesh | validated on hardware |
| ESP32-S3 companion, app CLI | validated on hardware |
| rak4631 / rak4631 companion / seeed_lr2021_evk / native_sim / heltec_v4_r8 | builds clean |
Cost on a rak4631 repeater build: +4.2 KB flash, +0 B RAM.
The two transports truncate at different points, which is the point of the CLI_REPLY_SIZE (256) / CLI_REMOTE_REPLY_SIZE (161) split: the same hw i2c pages at 5 entries locally and 2 remotely, and hw i2c 3 resumes continuously.
Spun out as separate issues
Each is independent of hw by design and cherry-pickable on its own:
- Reset cause is consumed by one role and never cleared by the others #2 — reset cause consumed by one role, never cleared by the others (fixed)
- Companion CLI replies over 175 bytes are truncated silently #3 — companion CLI replies over 175 bytes truncated silently (fixed)
- RAK4631 never uses a fitted RAK12002 RTC #4 — RAK4631 never uses a fitted RAK12002 RTC (fixed)
- No board definition for the Heltec WiFi LoRa 32 V4-R8 #5 — no board definition for the Heltec V4-R8 (added)
- First CLI command after opening the USB serial port returns "Unknown command" #6 — first CLI command after port open returns
Unknown command(open) - ZephyrBoard never implements the reset-reason abstraction it inherits #7 —
ZephyrBoardnever implements the reset-reason abstraction (open) - Resolved on investigation: Heltec V4 Vext polarity is not a ZephCore defect #8 — MeshCore/ZephCore disagree on Heltec V4 Vext polarity (open question)
- QIO flash mode is a no-op on ESP32 targets #9 — QIO flash mode is a no-op on ESP32 (note)
Design decisions, settled — do not re-litigate
- Named
hw, nothwinfo—<zephyr/drivers/hwinfo.h>is a Zephyr subsystem this tree already uses. hw i2candhw i2c scananswer different questions and say which. A devicetree enumeration cannot see an undeclared chip; a scan sees the wire but knows no names.- Zephyr extras folded in — reset cause and device id, which the Arduino version cannot produce.
- The report never infers. GNSS model comes from the bound driver, not the overlay comment; a board declaring no RTC says exactly that; an unreached probe candidate is
unprobed, notabsent.
Environment notes
- Toolchain:
westviauv, Zephyr 4.4.2, ARM and Xtensa SDK (west sdk install -t xtensa-espressif_esp32s3_zephyr-elf),west blobs fetch hal_espressif,esptool>=5.0.2in the venv. - Flashing ZephCore changes a board's USB identity. nRF52:
239a:8029→2fe3:0004. ESP32-S3:303a:1001→2fe3:0006. Each needs its ownusbipd bind+attach --auto-attach(Windows admin). Bootloader identities are unchanged, so the flash loop keeps working even while the running firmware is unreachable. - Reflashing ESP32 once ZephCore is running needs
cli "start dfu"first — esptool cannot reset it, because the port is the application's CDC rather than the ROM's. - A fresh node is loud: 869.618 MHz at 22 dBm with an advert 10 s after boot,
repeaton. Build first-boot images with safe defaults rather than racing that window. The frequency default lives ininitNodePrefs()for repeater/room-server and inLoRaConfig::FREQ_HZfor the companion — patching the wrong one silently does nothing.
Activity
ptr727 commentedon Sep 18, 2026
State at 50aa8b6
Review loop: 9 rounds, 18 findings, 17 fixed, 1 declined with evidence. Zero unresolved threads; every suppressed finding answered in the PR conversation.
Commits on
work/hw-cli1ae9d2a2f5873ee6a61a3hwcommand06207ab6c3f0b1439277d912670b786b1a5d84acfb05c9c6b1820b90b86ec0f8dd7a83aecbc4296bbb83a89745050aa8b6Validation
Cost: +4.2 KB flash, +0 B RAM on a rak4631 repeater build.
Recurring failure mode, recorded because it recurred
Three separate findings were the same mistake: the report asserting something the firmware had not established — a not-ready I2C bus recorded as
ABSENT, an unconditionalgeneric NMEAmodel line, and the summary printingrtc none presentwhen discovery had not run. Each was in code written immediately after arguing the opposite principle in a commit message.The three-valued RTC outcome then justified itself on hardware: the same board reports
0x32 absentwhen the RTC holds no time and0x32 unprobedwhen it does, because discovery returns early in the second case. A two-valued design would have saidabsentfor a run that never looked.Still open
#6 (first CLI command after port open), #7 (
ZephyrBoardreset-reason abstraction), #8 (resolved — no ZephCore change), #9 (note only).ptr727 commentedon Sep 18, 2026
Green at 22b0f38 — review loop complete
13 rounds, 21 findings, 20 fixed, 1 declined with evidence. Round 13 raised nothing against the current head.
Not merged. The merge gate's last condition is explicit maintainer permission, which has not been given and is not mine to assume.
Final commits on
work/hw-cliRounds 10-12 added: docs coverage contradiction (
7f93422), page-index ceiling matching its own comment (f1130d4), and a scan that could drop a present chip (22b0f38).That last one is worth flagging for whoever reviews this:
section_i2c_scan()'s retry path had noelse, so an address that would not fit even after a line flush was dropped whilefound++had already counted it — under a comment of mine saying that is the one thing a scan must never do. Unreachable on any board in this tree (longest real token is 23 characters into a 128-byte line), which is why it survived twelve rounds and hardware testing on two boards. Now restructured so the guarantee is a property of the shape rather than of handling a third case.I had recommended stopping after round 11 on the grounds that the loop looked like it was only finding churn in its own repairs. That was wrong, and round 12 was the counterexample. The findings that survive longest are exactly the ones ordinary inputs never reach, so judging remaining risk by the size of recent findings is not safe.
Next, when you want it
Cherry-pick #2, #3, #4 and #5 onto clean single-purpose branches for upstream PRs. Each was written to stand alone and none depends on
hw. #6 and #7 remain open and unstarted; #8 resolved with no ZephCore change; #9 is a note only.ptr727 commentedon Sep 18, 2026
Protocol correction + a defect found while prepping the cherry-picks
PR #1 stays open. It is the working branch; upstream only ever sees the clean branches cherry-picked out of it. My earlier note said "ready for your review, merge is yours" — that was the wrong frame. Nothing here gets merged.
A defect the review loop could not have caught
While mapping commits to branches I found that two files came back from my edits with their line endings rewritten:
boards/nrf52840/rak4631/board.overlaydocs/Repeater_CLI_commands.mdHarmless on this branch and fatal to a contribution: the RAK4631 overlay diff read as 236 insertions / 218 deletions for an 18-line addition. Nobody can review that, and no upstream maintainer should be asked to.
Fixed in
fe9b346. Both files now carry exactly whatupstream/devhas — the overlay CRLF throughout, the docs file LF apart from the same threeget cad.*rows that were already CRLF. Both diffs are now pure additions, zero deletions.Two things worth carrying forward:
git show --statagainstgit show -w --stat; a large gap is whitespace churn.file(1)is the wrong instrument. It reported "with CRLF line terminators" for a file with 3 CRLF lines out of 404, which sent me to fix the wrong thing first — I converted all 485 lines to CRLF and made that diff worse before measuring properly. Count\r\nagainst\n.Re-check after every cherry-pick or squash, since a rewrite can reintroduce it.
Branch mapping for the clean PRs
2f5873eaecbc42d84acfb8dd7a83+ R8 hunks of96bbb83,a897450hwcommand1ae9d2a,e6a61a3,06207ab+ review rounds1ae9d2a(RTC accessors) is a prerequisiteptr727 commentedon Oct 2, 2026
State for this work now lives in the handoff chain on track
hw-cli, starting at #22 (2026-10-02). This issue is left as the earlier record; #22 lists what changed since:devmerged into #1 and #16, thehwCLI ported and reviewed, and the RAK4631 RTC change narrowed to the RV3028 (see the correction on #4).