mirror of
https://github.com/meshtastic/firmware.git
synced 2026-06-14 22:36:12 +00:00
Add LTO support for nrf52840 while preserving interrupt handlers
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python3
|
||||
# trunk-ignore-all(ruff/F821)
|
||||
# trunk-ignore-all(flake8/F821)
|
||||
#
|
||||
# Whole-image LTO for nrf52840, EXCEPT the interrupt handlers.
|
||||
#
|
||||
# Every interrupt/exception handler is referenced only from the assembly vector
|
||||
# table (gcc_startup_nrf52840.S), which LTO cannot see. So whole-program LTO judges
|
||||
# the handlers dead, removes them, and the weak `b .` Default_Handler stubs prevail
|
||||
# -> the first IRQ (FreeRTOS scheduler-start SVC, then GPIOTE/RTC/USBD/...) lands in
|
||||
# an infinite loop and the chip hangs. Compiling the handler-bearing objects WITHOUT
|
||||
# LTO lets ordinary linking keep the strong handlers (exactly like a non-LTO build):
|
||||
# - framework core (/FrameworkArduino/, /cores/nRF5/): every nrfx ISR + the
|
||||
# FreeRTOS SVC/PendSV port (vPortSVCHandler / xPortPendSVHandler).
|
||||
# - TinyUSB's nrf port: USBD_IRQHandler -- without it USB enumerates but the data
|
||||
# path hangs (the host's first transfer interrupt is never serviced).
|
||||
# Everything else (app src + RadioLib/Crypto/nanopb/sensor libs/...) stays LTO'd.
|
||||
import os
|
||||
|
||||
Import("env")
|
||||
|
||||
env.Append(LINKFLAGS=["-flto", "-flto-partition=1to1"])
|
||||
|
||||
# Private include dir for the TinyUSB nrf-port re-compile below (tusb_option.h etc.).
|
||||
_fw = env.PioPlatform().get_package_dir("framework-arduinoadafruitnrf52") or ""
|
||||
_tinyusb_src = os.path.join(_fw, "libraries", "Adafruit_TinyUSB_Arduino", "src")
|
||||
|
||||
FRAMEWORK = ("/FrameworkArduino/", "/cores/nRF5/")
|
||||
USB_ISR = "Adafruit_TinyUSB_nrf" # defines USBD_IRQHandler
|
||||
|
||||
|
||||
def _no_lto(node):
|
||||
try:
|
||||
path = node.get_abspath()
|
||||
except Exception:
|
||||
path = str(node)
|
||||
if USB_ISR in path:
|
||||
return env.Object(
|
||||
node,
|
||||
CCFLAGS=env["CCFLAGS"] + ["-fno-lto"],
|
||||
CPPPATH=env["CPPPATH"] + [_tinyusb_src],
|
||||
)
|
||||
if any(s in path for s in FRAMEWORK):
|
||||
return env.Object(node, CCFLAGS=env["CCFLAGS"] + ["-fno-lto"])
|
||||
return node
|
||||
|
||||
|
||||
env.AddBuildMiddleware(_no_lto)
|
||||
@@ -22,6 +22,10 @@ build_flags = ${nrf52840_base.build_flags}
|
||||
-DRADIOLIB_EXCLUDE_SX127X=1
|
||||
-DRADIOLIB_EXCLUDE_LR11X0=1
|
||||
-DRADIOLIB_EXCLUDE_LR2021=1
|
||||
-fmerge-all-constants ; fold identical constants across the image (~0.7KB; same flag stm32 uses)
|
||||
-flto ; whole-image LTO (~-57KB); nrf52_lto.py keeps the hardware layer out of LTO so the vector ISRs survive
|
||||
extra_scripts = ${nrf52_base.extra_scripts}
|
||||
pre:extra_scripts/nrf52_lto.py
|
||||
build_src_filter = ${nrf52_base.build_src_filter} \
|
||||
+<../variants/nrf52840/rak4631> \
|
||||
+<mesh/eth/> \
|
||||
|
||||
Reference in New Issue
Block a user