Repair constrained nRF52 release builds and retain size-failure diagnostics
This commit is contained in:
1 parent
dd64eae4f9
commit
5e10a319ab
4 files changed
+157
-14
No files matched your search
@@ -116,6 +116,7 @@ jobs:
|
||||
|
||||
- name: Verify firmware memory budgets and nRF52 Bluetooth startup
|
||||
run: |
|
||||
bash test/test_build_size_detection.sh
|
||||
python3 -B test/test_firmware_ram.py
|
||||
python3 -B test/test_cascade_release_package.py
|
||||
python3 -B test/test_t096_full_memory.py
|
||||
|
||||
@@ -2696,6 +2696,9 @@ requires_dram_limited_neighbors() {
|
||||
# 8 KiB static reserve at 254 neighbors. Use their board-declared 50-entry
|
||||
# tables when the OTA manager is included.
|
||||
case "${1,,}" in
|
||||
heltec_t096_repeater_lora_ota_no_external_sensors|\
|
||||
heltec_t1_repeater_lora_ota_no_external_sensors)
|
||||
return 0 ;;
|
||||
generic_e22_sx1262_repeater_lora_ota_no_external_sensors|\
|
||||
generic_e22_sx1268_repeater_lora_ota_no_external_sensors|\
|
||||
heltec_v2_repeater_lora_ota_no_external_sensors|\
|
||||
@@ -3266,7 +3269,8 @@ apply_nrf52_size_profile() {
|
||||
if [ "${PIO_ENV_PLATFORM_BY_NAME[$env_name]:-}" != "NRF52_PLATFORM" ]; then
|
||||
return 0
|
||||
fi
|
||||
if ! is_nrf52_companion_radio_full_target "$env_name" \
|
||||
if ! is_repeater_role_target "$env_name" \
|
||||
&& ! is_nrf52_companion_radio_full_target "$env_name" \
|
||||
&& { ! is_lora_ota_build "$env_name" \
|
||||
|| ! is_lora_ota_only_target "$env_name"; }; then
|
||||
return 0
|
||||
@@ -3276,10 +3280,26 @@ apply_nrf52_size_profile() {
|
||||
# runtime software Ed25519 fallback is linked alongside CC310, that setting
|
||||
# fully expands repeated Curve25519 arithmetic and wastes tens of kilobytes.
|
||||
# Keep hardware crypto, RNG mixing, the software fallback, and board features;
|
||||
# select the size optimizer for both constrained self-updating images and
|
||||
# Full Companion source images, especially their diagnostic profile.
|
||||
# select the size optimizer for repeaters, constrained self-updating images
|
||||
# and Full Companion source images, especially their diagnostic profile.
|
||||
# Full-sensor repeaters also need this after adding the second radio profile;
|
||||
# changing optimization preserves their sensors and protocol features.
|
||||
append_platformio_build_unflags "-Ofast"
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -Os"
|
||||
|
||||
# These color-display repeaters reserve a 64 KiB reset-retained OTA arena
|
||||
# plus a 25 KiB framebuffer. Keep their board-declared 50 neighbours and
|
||||
# the complete flood-rule engine with a smaller table so runtime startup
|
||||
# allocations also fit; do not lower the heap qualification requirement.
|
||||
case "${env_name,,}" in
|
||||
heltec_t096_repeater_lora_ota_no_external_sensors|\
|
||||
heltec_t1_repeater_lora_ota_no_external_sensors)
|
||||
append_platformio_build_unflags "-DFLOOD_PACKET_FILTER_SLOTS=63"
|
||||
export PLATFORMIO_BUILD_FLAGS="${PLATFORMIO_BUILD_FLAGS} -DFLOOD_PACKET_FILTER_SLOTS=16"
|
||||
record_build_reduction \
|
||||
"mesh.flood_rules limited to 16 by measured internal RAM; complete rule engine, color display, GPS, and OTA retained"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
apply_lora_ota_no_external_sensors_profile() {
|
||||
@@ -4029,6 +4049,29 @@ restore_platformio_build_flags() {
|
||||
fi
|
||||
}
|
||||
|
||||
run_pio_with_size_detection() {
|
||||
local build_output_log
|
||||
local build_status
|
||||
local -a output_statuses
|
||||
# SCons can delete the environment's build directory when flags change.
|
||||
# A tee log inside that directory is then unlinked while still open, hiding
|
||||
# the size error from the measured-size fallback after PlatformIO exits.
|
||||
build_output_log=$(mktemp "${TMPDIR:-/tmp}/meshcore-build-XXXXXX.log") || return 1
|
||||
pio "$@" 2>&1 | tee "$build_output_log"
|
||||
output_statuses=("${PIPESTATUS[@]}")
|
||||
build_status=${output_statuses[0]}
|
||||
if [ "${output_statuses[1]}" -ne 0 ]; then
|
||||
build_status=1
|
||||
elif [ "$build_status" -ne 0 ] \
|
||||
&& grep -Eiq \
|
||||
'will not fit in region|region .+ overflowed by|section .+ will not fit|sketch too big|program size is greater than maximum|exceed(s|ing).*(flash|partition|app)' \
|
||||
"$build_output_log"; then
|
||||
build_status=42
|
||||
fi
|
||||
rm -f -- "$build_output_log"
|
||||
return "$build_status"
|
||||
}
|
||||
|
||||
build_firmware() {
|
||||
local env_name=$1
|
||||
local pio_env_name
|
||||
@@ -4271,17 +4314,8 @@ build_firmware() {
|
||||
pio_run_args+=(-t mergebin)
|
||||
fi
|
||||
if [ "$build_status" -eq 0 ]; then
|
||||
local build_output_dir="${PIO_BUILD_DIR_OVERRIDE:-${PLATFORMIO_BUILD_DIR:-.pio/build}}/${pio_env_name}"
|
||||
local build_output_log="${build_output_dir}/.meshcore-build-output.log"
|
||||
mkdir -p -- "$build_output_dir"
|
||||
pio "${pio_run_args[@]}" 2>&1 | tee "$build_output_log"
|
||||
build_status=${PIPESTATUS[0]}
|
||||
if [ "$build_status" -ne 0 ] \
|
||||
&& grep -Eiq \
|
||||
'will not fit in region|region .+ overflowed by|section .+ will not fit|sketch too big|program size is greater than maximum|exceed(s|ing).*(flash|partition|app)' \
|
||||
"$build_output_log"; then
|
||||
build_status=42
|
||||
fi
|
||||
run_pio_with_size_detection "${pio_run_args[@]}"
|
||||
build_status=$?
|
||||
fi
|
||||
if [ "$build_status" -eq 0 ]; then
|
||||
collect_build_artifacts "$env_name" "$env_platform" "$pio_env_name" "$firmware_filename"
|
||||
|
||||
@@ -95,6 +95,20 @@ before choosing an update method.
|
||||
|
||||
## Reproduce the release
|
||||
|
||||
Follow-up builds repair the constrained profiles without relaxing qualification:
|
||||
|
||||
- nRF52 repeaters use `-Os` instead of `-Ofast`, retaining their sensor drivers
|
||||
and protocol features while reducing flash use.
|
||||
- T096 and T1 LoRa OTA repeaters retain their board-defined 50 neighbors and
|
||||
use 16 flood-rule slots. The complete rule engine, color display, GPS and OTA
|
||||
remain enabled. The T096's available startup heap rises from 72,492 to 81,468
|
||||
bytes, and the T1's from 72,868 to 81,844 bytes. Required startup allocations
|
||||
fall from 88,410 to 79,010 bytes. These are linked capacity checks, not soak
|
||||
measurements. Full Companion capacities are unchanged.
|
||||
- Size-failure detection keeps its temporary output log outside PlatformIO's
|
||||
build tree, so SCons cleanup cannot erase the evidence needed by the measured
|
||||
size fallback. CI exercises cleanup, ordinary compiler failures and log errors.
|
||||
|
||||
Use a clean checkout of the release commit and a fresh output directory:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
source build.sh
|
||||
|
||||
fail() { echo "test_build_size_detection: $*" >&2; exit 1; }
|
||||
test_root=$(mktemp -d "${TMPDIR:-/tmp}/meshcore-size-tests.XXXXXX")
|
||||
test_root=$(realpath "$test_root")
|
||||
[[ "$test_root" == /*/meshcore-size-tests.* ]] || fail "unexpected temporary path"
|
||||
trap 'rm -rf -- "$test_root"' EXIT
|
||||
export TMPDIR=$test_root
|
||||
managed_dir=$test_root/build/test
|
||||
pio() {
|
||||
# Model the real SCons cleanup that previously unlinked the tee log.
|
||||
[[ "$managed_dir" == "$test_root/"* ]] || return 99
|
||||
rm -rf -- "$managed_dir"
|
||||
touch "$test_root/pio-called"
|
||||
printf '%s\n' "$pio_message"
|
||||
return "$pio_result"
|
||||
}
|
||||
|
||||
check_status() {
|
||||
local expected=$1 actual=0
|
||||
mkdir -p "$managed_dir"
|
||||
if run_pio_with_size_detection run -e test > "$test_root/output" 2>&1; then
|
||||
actual=0
|
||||
else
|
||||
actual=$?
|
||||
fi
|
||||
[ "$actual" -eq "$expected" ] || fail "expected status $expected, got $actual"
|
||||
[ ! -d "$managed_dir" ] || fail "fake PlatformIO did not clean its build directory"
|
||||
if compgen -G "$test_root/meshcore-build-*.log" > /dev/null; then
|
||||
fail "temporary build-output log was not released"
|
||||
fi
|
||||
}
|
||||
|
||||
pio_result=1
|
||||
for pio_message in \
|
||||
"firmware.elf section .text will not fit in region FLASH" \
|
||||
"region FLASH overflowed by 43080 bytes" \
|
||||
"Error: The program size is greater than maximum allowed"; do
|
||||
check_status 42
|
||||
grep -Fq "$pio_message" "$test_root/output" || fail "compiler output was lost"
|
||||
done
|
||||
pio_message='error: missing declaration'
|
||||
check_status 1
|
||||
pio_result=2
|
||||
check_status 2
|
||||
pio_result=0
|
||||
pio_message='compilation succeeded'
|
||||
check_status 0
|
||||
|
||||
# An output failure must not look like a successful or merely oversized build.
|
||||
tee() { cat > /dev/null; return 1; }
|
||||
check_status 1
|
||||
unset -f tee
|
||||
rm -f "$test_root/pio-called"
|
||||
TMPDIR=$test_root/missing
|
||||
if run_pio_with_size_detection run -e test > /dev/null 2>&1; then
|
||||
fail "missing log directory was accepted"
|
||||
fi
|
||||
[ ! -e "$test_root/pio-called" ] || fail "PIO ran without diagnostic storage"
|
||||
|
||||
# Keep sensors and protocol features while shrinking nRF52 repeater code.
|
||||
PIO_ENV_PLATFORM_BY_NAME[ikoka_nano_nrf_22dbm_repeater]=NRF52_PLATFORM
|
||||
PLATFORMIO_BUILD_FLAGS=''
|
||||
PLATFORMIO_BUILD_UNFLAGS=''
|
||||
apply_nrf52_size_profile ikoka_nano_nrf_22dbm_repeater
|
||||
[[ "$PLATFORMIO_BUILD_FLAGS" == *' -Os'* ]] || fail "full-sensor repeater omitted size optimization"
|
||||
[[ "$PLATFORMIO_BUILD_UNFLAGS" == *'-Ofast'* ]] || fail "aggressive optimization was not removed"
|
||||
[[ "$PLATFORMIO_BUILD_FLAGS" != *'-UENV_INCLUDE_'* ]] || fail "sensor support was reduced"
|
||||
for target in Heltec_t096_repeater_lora_ota_no_external_sensors Heltec_t1_repeater_lora_ota_no_external_sensors; do
|
||||
PIO_ENV_PLATFORM_BY_NAME[$target]=NRF52_PLATFORM
|
||||
PLATFORMIO_BUILD_FLAGS=''
|
||||
PLATFORMIO_BUILD_UNFLAGS=''
|
||||
apply_repeater_neighbor_capacity "$target"
|
||||
apply_nrf52_size_profile "$target"
|
||||
[[ "$PLATFORMIO_BUILD_FLAGS" == *'-DMAX_NEIGHBOURS=50'* ]] || fail "$target omitted RAM-safe neighbours"
|
||||
[[ "$PLATFORMIO_BUILD_FLAGS" == *'-DFLOOD_PACKET_FILTER_SLOTS=16'* ]] || fail "$target omitted RAM-safe rule table"
|
||||
[[ "$PLATFORMIO_BUILD_FLAGS" != *'MESH_MIN_RUNTIME_HEAP'* ]] || fail "runtime RAM guard was overridden"
|
||||
done
|
||||
for target in Heltec_t096_companion_radio_full_femon RAK_4631_repeater; do
|
||||
PIO_ENV_PLATFORM_BY_NAME[$target]=NRF52_PLATFORM
|
||||
PLATFORMIO_BUILD_FLAGS=''
|
||||
PLATFORMIO_BUILD_UNFLAGS=''
|
||||
apply_nrf52_size_profile "$target"
|
||||
[[ "$PLATFORMIO_BUILD_FLAGS" != *'FLOOD_PACKET_FILTER_SLOTS'* ]] || fail "$target received unrelated table reductions"
|
||||
[[ "$PLATFORMIO_BUILD_FLAGS" != *'MAX_NEIGHBOURS'* ]] || fail "$target received unrelated neighbour reductions"
|
||||
done
|
||||
PIO_ENV_PLATFORM_BY_NAME[Heltec_v4_repeater]=ESP32_PLATFORM
|
||||
PLATFORMIO_BUILD_FLAGS=''
|
||||
apply_nrf52_size_profile Heltec_v4_repeater
|
||||
[ -z "$PLATFORMIO_BUILD_FLAGS" ] || fail "nRF52 policy changed an ESP32 target"
|
||||
echo 'Build-size diagnostics and constrained nRF52 recipes passed.'
|
||||
Reference in new issue
Block a user