mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 04:49:54 +00:00
- boards/**/zephcore.yml: one manifest per board/preset (release roles, variants, catalog metadata, capabilities); scripts/board_manifest.py validates and serves them to build.sh, gen_provider_catalog.py and docs/supported_boards.md - cmake/zephcore_board.cmake: board dir -> platform, shared by app and sysbuild; removes the board-name regex lists and 7 separate globs - conf chain: exact-name role/debug classification checked against Kconfig, idempotent across non-pristine reconfigures, version string single-sourced (BT DIS rev generated), day-granular build epoch - Doom easter egg: Kconfig default for the wio_tracker_l1 companion instead of a build.sh-only flag - catalog: maker for the LR2021 EVK (KeyError before); CI installs PyYAML - user -DEXTRA_DTC_OVERLAY_FILE overlays now take precedence over derived overlays Verified: identical .config, DTS and source lists for 97 board/role configs; identical images for 4 reference builds; identical build.sh command/artifact set and catalog content.
141 lines
6.4 KiB
Bash
141 lines
6.4 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# Release matrix.
|
|
#
|
|
# ./build.sh nrf | nrf54l | mg24 | stm32wl | linux
|
|
# ./build.sh esp32 companions | repeaters
|
|
#
|
|
# WHICH boards are built, in which roles and variants, lives in the board
|
|
# manifests (zephcore/boards/<platform>/<board>/zephcore.yml and
|
|
# zephcore/boards/linux_native/<preset>.zephcore.yml; schema and validator in
|
|
# zephcore/scripts/board_manifest.py). This script only knows how each platform
|
|
# packages its images. A board without a `release:` section is not published.
|
|
#
|
|
# Everything a release build puts in the firmware comes from the build config,
|
|
# never from extra -D flags here, so a local build of the same board + role is
|
|
# the same firmware. Release-only differences are layout and packaging.
|
|
|
|
set -euo pipefail
|
|
mkdir -p firmware
|
|
|
|
COMMIT_HASH=$(git rev-parse --short HEAD)
|
|
GROUP="${1:?usage: build.sh <nrf|nrf54l|mg24|stm32wl|linux> | build.sh esp32 <companions|repeaters>}"
|
|
ROLE_FILTER="${2:-}"
|
|
if [[ $GROUP == "esp32" && -z $ROLE_FILTER ]]; then
|
|
echo "build.sh esp32 needs 'companions' or 'repeaters'" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Move the finished image(s) of one build into firmware/ under the published name.
|
|
package() {
|
|
local platform=$1 target=$2 stem=$3 tag=$4
|
|
local out="firmware/$stem-$tag-$COMMIT_HASH"
|
|
case $platform in
|
|
nrf)
|
|
# UF2 for drag-and-drop, DFU .zip for the configurator.
|
|
mv build/zephyr/zephyr.uf2 "$out.uf2"
|
|
mv build/zephyr/zephyr.zip "$out.zip"
|
|
;;
|
|
nrf54l | mg24 | stm32wl)
|
|
# No USB bootloader on these SoCs (nRF54L15, EFR32MG24 and STM32WL
|
|
# have no USB device peripheral): zephyr.hex links at the flash origin,
|
|
# IS the whole image, and is flashed over SWD. Download-only in the
|
|
# Mesh America catalog.
|
|
mv build/zephyr/zephyr.hex "$out.hex"
|
|
;;
|
|
linux)
|
|
# native_sim emits zephcore_native_linux.exe; ship it extension-less.
|
|
mv build/zephyr/zephcore_native_linux.exe "$out"
|
|
;;
|
|
esp32)
|
|
[[ $target =~ (esp32[^/]*) ]] || { echo "Unknown chip for: $target" >&2; exit 1; }
|
|
local chip=${BASH_REMATCH[1]}
|
|
if [[ $chip == "esp32" ]]; then
|
|
# Classic ESP32 (T-Beam, PICO-D4): simple boot for both roles. The
|
|
# companion's BLE controller leaves no DRAM for MCUboot and the
|
|
# repeater is CLI-only (WiFi OTA overflows DRAM by ~10 KB), so
|
|
# zephyr.bin is the complete bootable image at the 0x1000 ROM
|
|
# bootloader offset; also wrapped as a full-flash merged image.
|
|
python -m esptool --chip "$chip" merge-bin \
|
|
--output "$out-merged.bin" \
|
|
--flash-mode dio --flash-freq 40m --flash-size 4MB \
|
|
0x1000 build/zephyr/zephyr.bin
|
|
cp build/zephyr/zephyr.bin "$out.bin"
|
|
else
|
|
# S3/C-series: sysbuild + MCUboot. Only the merged image (MCUboot @
|
|
# 0x0 + signed app @ 0x10000) is bootable on a bare chip. The signed
|
|
# app alone is the app-only update payload (configurator
|
|
# "flash-update" at 0x10000, WiFi-OTA upload) and is NOT bootable
|
|
# standalone -- never publish it as a plain .bin (bricked boards when
|
|
# flashed like classic-ESP32's image, GH #42).
|
|
local flash_size
|
|
flash_size=$(python3 zephcore/scripts/dts_flash_size.py \
|
|
"${ZEPHYR_DTS:-build/zephcore/zephyr/zephyr.dts}")
|
|
python -m esptool --chip "$chip" merge-bin \
|
|
--output "$out-merged.bin" \
|
|
--flash-mode dio --flash-freq 40m --flash-size "$flash_size" \
|
|
0x00000 build/mcuboot/zephyr/zephyr.bin \
|
|
0x10000 build/zephcore/zephyr/zephyr.signed.bin
|
|
cp build/zephcore/zephyr/zephyr.signed.bin "$out-update.bin"
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# One manifest row: target|role|variant|confs|stem|sysbuild|host|cross_compile
|
|
build_row() {
|
|
local target=$1 role=$2 variant=$3 confs=$4 stem=$5 sysbuild=$6 host=$7 cross=$8
|
|
local tag="$role${variant:+-$variant}"
|
|
local cmd=(west build -b "$target" zephcore --pristine)
|
|
[[ -n $sysbuild ]] && cmd+=("--$sysbuild")
|
|
local extra=()
|
|
if [[ -n $host ]]; then
|
|
# Native-Linux presets are cross-compiled for their SBC's arch.
|
|
extra+=(-DZEPHYR_TOOLCHAIN_VARIANT=cross-compile
|
|
-DNATIVE_TARGET_HOST="$host" -DCROSS_COMPILE="$cross")
|
|
fi
|
|
[[ -n $confs ]] && extra+=(-DEXTRA_CONF_FILE="$confs")
|
|
((${#extra[@]})) && cmd+=(-- "${extra[@]}")
|
|
|
|
echo "Now building $target $tag"
|
|
"${cmd[@]}"
|
|
package "$GROUP" "$target" "$stem" "$tag"
|
|
}
|
|
|
|
python3 zephcore/scripts/board_manifest.py check
|
|
mapfile -t ROWS < <(python3 zephcore/scripts/board_manifest.py matrix "$GROUP" $ROLE_FILTER)
|
|
for row in "${ROWS[@]}"; do
|
|
row=${row%$'\r'} # Python on Windows prints CRLF
|
|
IFS='|' read -r target role variant confs stem sysbuild host cross <<<"$row"
|
|
build_row "$target" "$role" "$variant" "$confs" "$stem" "$sysbuild" "$host" "$cross"
|
|
done
|
|
|
|
if [[ $GROUP == "nrf" ]]; then
|
|
# ZephCore's storage formatter, published as the `erase` package for the
|
|
# Mesh America configurator (spec §4a). MeshCore's official erase targets a
|
|
# different flash layout and only partially wipes a ZephCore node, so each
|
|
# nRF52 board points `erase` at the formatter for its SoftDevice (v6/v7 have
|
|
# different partition maps). Copied under stable, un-hashed names so the
|
|
# catalog's erase URLs stay stable. The .zip drives the configurator's
|
|
# automated DFU erase flow; the .uf2 is the manual drag-and-drop fallback.
|
|
for sd in 6 7; do
|
|
for ext in zip uf2; do
|
|
f="formatter/SoftDevice_v${sd}_formatter.${ext}"
|
|
if [[ -f "$f" ]]; then
|
|
cp "$f" firmware/
|
|
echo "Published formatter: $f"
|
|
else
|
|
echo "NOTE: $f not present — erase package for SoftDevice v${sd} will 404"
|
|
fi
|
|
done
|
|
done
|
|
|
|
# Device art we ship ourselves (`own_img` in the manifests). Published
|
|
# alongside the firmware so the catalog resolves it against the same
|
|
# --url-base as everything else, rather than hardcoding a host.
|
|
if compgen -G "img/*" > /dev/null; then
|
|
cp img/* firmware/
|
|
echo "Published device art: $(ls img/ | tr '\n' ' ')"
|
|
fi
|
|
fi
|