Skip to content

Publish flashable images with each release - #72

Merged
MacNite merged 1 commit into
mainfrom
claude/flashing-files-repo-release-40wqsi
Aug 27, 2026
Merged

Publish flashable images with each release#72
MacNite merged 1 commit into
mainfrom
claude/flashing-files-repo-release-40wqsi

Conversation

@MacNite

@MacNite MacNite commented Aug 27, 2026

Copy link
Copy Markdown
Owner

Answers a user's question — can we ship the files needed to flash a board? Today v0.1 is source-only, so getting a XIAO running requires installing a Zephyr toolchain first. CI already builds exactly what a release needs (both variants, west --sysbuild, against the pinned Zephyr revision) and then throws the result away.

What gets published

New .github/workflows/release.yml runs that same build on a tag push (and on workflow_dispatch, which builds the identical set as workflow artifacts so a release can be rehearsed without tagging), then attaches:

Asset Purpose
hiveinside-nrf54lm20a-v<version>-<variant>.signed.bin BLE OTA payload — already stamped by the build; HiveHub reads target and version from the name
hiveinside-nrf54lm20a-v<version>-<variant>-factory.hex SWD image: MCUboot at 0x0 plus the signed app in slot 0, merged in CI because upstream Zephyr sysbuild emits no merged.hex
manifest.txt, SHA256SUMS each payload's byte size and CRC-32 (the two values the OTA BEGIN frame carries), commit, Zephyr revision, signing-key caveat
west-manifest-frozen.yml, build-info-<variant>.zip the frozen manifest and both images' Kconfig — the release checklist's "retain the build configuration" step
hiveinside-flash-tools.zip, hiveinside-enclosure.zip flashing bundle; enclosure without a clone

Both variants are built, so -bringup and -lowpower are published side by side under names that say which is which.

Two guard rails:

  • The stamped artifact name is asserted against src/hive_config.h, so a forgotten version bump fails the release rather than shipping two different builds under one version. The repo tag and the firmware version stay independent, as before, and manifest.txt records both.
  • A tag with no release yet gets a draft, with the assets attached — the notes for this repo are hand-written, and a draft leaves room for that. An existing release just gets its assets uploaded (--clobber).

build.yml now also keeps its images (14-day artifacts), so a change can be tried on hardware before it is tagged.

The flashing bundle (tools/flash/)

flash.sh / flash.ps1 drive the on-board CMSIS-DAP debugger with OpenOCD alone — no toolchain, no west workspace, no external probe — running the same OpenOCD sequence west flash --verify runs for this board, verified against runners/openocd.py and the board's board.cmake at the pinned revision.

They correct the board's RRAM loader before flashing. Upstream is mww 0x5004e500 0x101WEN=1 plus a 16-byte write buffer the proc never commits — so the tail of any image that isn't 16-byte aligned never reaches RRAM and MCUboot then reports E: Image in the primary slot is not valid!, silently, on a dark device. docs/flashing.md already documents this for people building from source; handing out binaries would have made it the first support ticket. The scripts write 0x1 into a temp copy of the config instead (nothing on disk is modified), and detect an upstream fix so they stop patching once it lands. They also refuse a .signed.bin, which over SWD leaves nothing at 0x0.

The bundle ships the board's openocd.cfg unmodified, taken from the same Zephyr revision the images were built against, with its Apache-2.0 SPDX header and the source commit in openocd/ZEPHYR_REVISION.

Docs

  • docs/flashing.md gains a "Flashing a prebuilt release image" section at the top: which file to pick, the variant trap, the OTA path, the SWD path (script and the equivalent by hand), and checksum verification. The build-from-source content follows unchanged.
  • The release notes and docs say plainly that these images are signed with MCUboot's development key, which is public — image formatting, not proof of origin.
  • README quick start, the website's build section, claude.md's directory list, and the OTA release checklist point at the new path.

Two corrections found while writing this, both contradicted by the board files at the pinned revision:

  • board.cmake registers openocd, jlink and nrfutil only — there is no probe-rs or pyocd runner, so the docs sent readers at a runner that does not exist for this board.
  • support/openocd.cfg sources the generic interface/cmsis-dap.cfg with no VID:PID filter, so the claim that the runner ignores other CMSIS-DAP dongles (and cannot bind to an RP2040 probe) was wrong.

Testing

No firmware change, so no version bump.

  • Both workflows validate as YAML; flash.sh passes bash -n.
  • The release workflow's shell was dry-run locally against a mock sysbuild tree: version extraction from hive_config.h, the hexmerge (verified to produce exactly two segments, 0x0–0x874c and 0x10000–0x35138), size/CRC-32, build-info collection, the flash-tools bundle, manifest, and SHA256SUMS all produce the expected output.
  • End-to-end: unzipped the produced hiveinside-flash-tools.zip, dropped a factory hex beside it, and ran flash.sh against a stub openocd — it auto-detected the image, applied the RRAM fix (0x1010x1), and emitted exactly the argv west flash --verify would.
  • Not tested: a real CI run, and actual hardware. flash.ps1 could not be syntax-checked (no PowerShell in this environment) and has not run on Windows — worth one pass on a Windows box before the next release.

🤖 Generated with Claude Code

https://claude.ai/code/session_018va4kDycfQPyzeryPACKie


Generated by Claude Code

A user asked whether the repository could ship the files needed to flash a
board. It could not: the v0.1 release is source-only, so getting a XIAO
running meant installing a Zephyr toolchain first. CI already builds exactly
what a release needs — both variants, `west --sysbuild`, against the pinned
Zephyr revision — and then threw the result away.

Add `release.yml`, which runs that same build on a tag and keeps the files:

* `hiveinside-nrf54lm20a-v<version>-<variant>.signed.bin` — the BLE OTA
  payload, already stamped by the build;
* `hiveinside-nrf54lm20a-v<version>-<variant>-factory.hex` — MCUboot plus the
  signed application merged into one SWD image, because upstream Zephyr
  sysbuild emits no `merged.hex`;
* `manifest.txt` / `SHA256SUMS` — each payload's size and CRC-32 (what the OTA
  BEGIN frame carries), the commit, the Zephyr revision, the signing-key
  caveat — plus the frozen west manifest and both images' Kconfig, which is
  the release checklist's "retain the build configuration" step;
* `hiveinside-flash-tools.zip` and `hiveinside-enclosure.zip`.

The stamped name is asserted against `src/hive_config.h`, so a forgotten
version bump fails the release instead of shipping two builds under one
version. A tag with no release yet gets a draft, so the notes stay hand-written.

`tools/flash/` is the flashing bundle: OpenOCD-only scripts that run the same
sequence `west flash --verify` runs, for people with no west workspace. They
correct the board's RRAM loader first — upstream leaves the 16-byte write
buffer enabled and never commits it, so the tail of an unaligned image is
silently dropped and MCUboot then rejects slot 0. The scripts refuse a
`.signed.bin`, which over SWD leaves nothing at 0x0 and bricks the boot.

`build.yml` now also keeps its images, so a change can be tried on hardware
before it is tagged.

While documenting the standalone path, two claims in `docs/flashing.md` turned
out not to match the board definition at the pinned revision: it registers
`openocd`, `jlink` and `nrfutil` only — no `probe-rs` or `pyocd` runner — and
its `openocd.cfg` sources the generic CMSIS-DAP interface without filtering on
VID:PID. Both corrected.

No firmware change, so no version bump.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018va4kDycfQPyzeryPACKie
@MacNite
MacNite merged commit 6aa497f into main Aug 27, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant