Publish flashable images with each release - #72
Merged
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Answers a user's question — can we ship the files needed to flash a board? Today
v0.1is 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.ymlruns that same build on a tag push (and onworkflow_dispatch, which builds the identical set as workflow artifacts so a release can be rehearsed without tagging), then attaches:hiveinside-nrf54lm20a-v<version>-<variant>.signed.binhiveinside-nrf54lm20a-v<version>-<variant>-factory.hex0x0plus the signed app in slot 0, merged in CI because upstream Zephyr sysbuild emits nomerged.hexmanifest.txt,SHA256SUMSBEGINframe carries), commit, Zephyr revision, signing-key caveatwest-manifest-frozen.yml,build-info-<variant>.ziphiveinside-flash-tools.zip,hiveinside-enclosure.zipBoth variants are built, so
-bringupand-lowpowerare published side by side under names that say which is which.Two guard rails:
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, andmanifest.txtrecords both.--clobber).build.ymlnow 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.ps1drive the on-board CMSIS-DAP debugger with OpenOCD alone — no toolchain, no west workspace, no external probe — running the same OpenOCD sequencewest flash --verifyruns for this board, verified againstrunners/openocd.pyand the board'sboard.cmakeat the pinned revision.They correct the board's RRAM loader before flashing. Upstream is
mww 0x5004e500 0x101—WEN=1plus 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 reportsE: Image in the primary slot is not valid!, silently, on a dark device.docs/flashing.mdalready documents this for people building from source; handing out binaries would have made it the first support ticket. The scripts write0x1into 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 at0x0.The bundle ships the board's
openocd.cfgunmodified, taken from the same Zephyr revision the images were built against, with its Apache-2.0 SPDX header and the source commit inopenocd/ZEPHYR_REVISION.Docs
docs/flashing.mdgains 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.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.cmakeregistersopenocd,jlinkandnrfutilonly — there is noprobe-rsorpyocdrunner, so the docs sent readers at a runner that does not exist for this board.support/openocd.cfgsources the genericinterface/cmsis-dap.cfgwith 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.
flash.shpassesbash -n.hive_config.h, the hexmerge (verified to produce exactly two segments,0x0–0x874cand0x10000–0x35138), size/CRC-32, build-info collection, the flash-tools bundle, manifest, andSHA256SUMSall produce the expected output.hiveinside-flash-tools.zip, dropped a factory hex beside it, and ranflash.shagainst a stubopenocd— it auto-detected the image, applied the RRAM fix (0x101→0x1), and emitted exactly the argvwest flash --verifywould.flash.ps1could 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