Files
firmware/extra_scripts
Ben MeadorsandJonathan Bennett 87a009da63 fix(nrf52): LTO was dropping the board variant's weak hook overrides (#11415)
* fix(nrf52): LTO was dropping the board variant's weak hook overrides

Whole-image LTO (enabled arch-wide for nrf52840 in #10655) inlines the empty
weak body of earlyInitVariant()/lateInitVariant()/variant_shutdown()/
variant_nrf52LoopHook()/variantDefault*Config() at the call site, because the
weak default and the call site live in the SAME translation unit. The strong
override in variants/<arch>/<board>/variant.cpp is then never linked, and the
board's hardware setup silently does not run.

nrf52_lto.py's -fno-lto variant recompile does not help here: the caller is the
problem, not the variant object.

Needs both ingredients, so this only affects 2.8: the earlyInitVariant()
indirection landed in #9438 and is present in v2.7.26 too, but v2.7.26 has no
-flto, so the override linked normally.

Found on the muzi R1 Neo, whose earlyInitVariant() drives DCDC_EN_HOLD (P0.13,
the DC-DC hold after the user button) and NRF_ON (P0.29, "tells IO controller
device is on"). Both were dropped from the image, so the companion MCU never saw
the nRF application come up and stayed in its DFU indication (purple LED).
Verified in the ELF: pre-fix setup() runs straight from waitUntilPowerLevelSafe()
to the LED_NOTIFICATION block with no earlyInitVariant symbol in the binary and
no pinMode/digitalWrite on P0.13 or P0.29 anywhere; post-fix it calls the real
override. HW-confirmed on an R1 Neo.

Also affected on nrf52840: earlyInitVariant() on 10 variants (incl. t-echo-card,
which sequences its RT9080 3V3 rail there), variant_shutdown() on 18 variants
(t114, t-echo, ThinkNode M1-M8, meshlink, wio-tracker-L1 ... - sleep pin parking,
so deep-sleep leakage), variant_nrf52LoopHook() on 3 RAK variants. Confirmed
dropped on heltec-mesh-node-t114 by build, not just by inspection.

Fix is __attribute__((noinline)) on both the weak declaration and definition -
the same guard already carried by loopCanSleep(), preFSBegin(), PowerHAL and
variant_enableBatteryLpcompWake(), whose comment in main-nrf52.cpp already
documents this exact failure mode.

Also extend _VARIANT_OVERRIDES in extra_scripts/nrf52_lto.py from just
_Z11initVariantv to all eight hooks. That post-link guard already had the right
logic and would have caught this on every PR - it simply was not listing
Meshtastic's own weak variant hooks, only the core's. With the list extended it
goes red on both r1-neo and heltec-mesh-node-t114 when the noinline is reverted,
and green with it. Its failure message now names both possible causes.

* review: trim the noinline rationale comments to two lines

Per AGENTS.md ("keep code comments minimal - one or two lines, max"), the
incident detail and extended background belong in the PR description, not the
source. Keeps the LTO/noinline rationale and the pointer to the guard.

---------

Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2026-08-11 22:57:45 +00:00
..
2026-07-01 19:01:27 -05:00
2026-07-01 19:01:27 -05:00
2026-07-01 19:01:27 -05:00

extra_scripts

This directory contains special scripts that are used to modify the platformio environment in rare cases.