libretiny: use native section names for RTL8710B; patcher now LN882H-only

RTL8710B's stock linker already consumes *(.image2.ram.text*) into its
.ram_image2.text output (> BD_RAM), so hal.h can place IRAM_ATTR
functions directly into section(".image2.ram.text") without any linker
patching. RTL8720C already worked this way with section(".sram.text").

The patcher is now only needed for LN882H, whose stock linker has no
glob that catches ".sram.text" — we inject KEEP(*(.sram.text*)) into
.flash_copysection (> RAM0 AT> FLASH).

This removes the _RTL8710B_IMAGE2 regex, the RTL8710B entry from
_PATCHERS_BY_VARIANT, and simplifies the header comments.
This commit is contained in:
J. Nick Koston
2026-04-15 16:05:12 -10:00
parent 853782b251
commit 9fc54d30e5
3 changed files with 24 additions and 33 deletions
+5 -9
View File
@@ -467,15 +467,11 @@ async def component_to_code(config):
# it for project source files only. GCC uses the last -O flag.
build_src_flags += " -Os"
cg.add_platformio_option("build_src_flags", build_src_flags)
# IRAM_ATTR on LibreTiny expands to section(".sram.text") on families
# where the ISR-during-flash race is real (see esphome/core/hal.h). This
# pre-link hook routes that section into each family's executable RAM:
# - LN882H: inject KEEP(*(.sram.text*)) into .flash_copysection.
# - RTL8710B: inject KEEP(*(.sram.text*)) into .ram_image2.text.
# - RTL8720C: no-op (stock linker already consumes *(.sram.text*)).
# BK72xx (all variants) is no-op: the Beken SDK wraps every flash write
# in GLOBAL_INT_DISABLE() so no ISR can fire during a flash stall; the
# race IRAM_ATTR guards against cannot occur.
# IRAM_ATTR routes ISR code into RAM-executable sections (see
# esphome/core/hal.h). Most families need no linker help; LN882H is the
# exception — its stock linker has no glob for ".sram.text", so this
# pre-link hook injects KEEP(*(.sram.text*)) into .flash_copysection.
# The script also prints a post-link summary on all non-BK72xx families.
cg.add_platformio_option("extra_scripts", ["pre:patch_linker.py"])
# dummy version code
cg.add_define("USE_ARDUINO_VERSION_CODE", cg.RawExpression("VERSION_CODE(0, 0, 0)"))
@@ -5,26 +5,19 @@ import os
import re
import subprocess
# ESPHome marks ISR code IRAM_ATTR, which on LibreTiny expands to
# section(".sram.text") (see esphome/core/hal.h). Each family's linker script
# needs that section routed into RAM-resident *executable* memory so the
# function is callable while flash is busy (XIP stall, OTA, logger flash
# write):
# ESPHome marks ISR code IRAM_ATTR, which on LibreTiny maps to a section
# that each family's linker routes into RAM-executable memory so the function
# is callable while flash is busy (see esphome/core/hal.h for the per-family
# section names).
#
# - LN882H: stock linker has ".flash_copysection" which is flash-to-RAM0
# copied at startup; inject "KEEP(*(.sram.text*))" there.
# - RTL8710B (AmebaZ): stock linker has ".ram_image2.text" output section
# (which already consumes *(.image2.ram.text*)) — inject
# "KEEP(*(.sram.text*))" into it as a second input glob.
# - RTL8720C (AmebaZ2): stock linker already consumes "*(.sram.text*)",
# no-op. Loaded directly from the framework package so we cannot inject
# our __esphome_sram_text_start/end markers either; the post-link summary
# falls back to reading known IRAM_ATTR symbol addresses instead.
# Most families need no linker patching:
# - RTL8710B: hal.h uses section(".image2.ram.text"); stock linker consumes it.
# - RTL8720C: hal.h uses section(".sram.text"); stock linker consumes it.
# - BK72xx: IRAM_ATTR is a no-op (SDK masks FIQ+IRQ around flash writes).
#
# BK72xx (all variants) have no .ld patcher: the Beken SDK wraps every flash
# operation in GLOBAL_INT_DISABLE() which masks FIQ + IRQ at the CPU, so no
# ISR can fire during a flash stall and the race IRAM_ATTR guards against
# cannot occur. IRAM_ATTR is a no-op on BK72xx (see esphome/core/hal.h).
# LN882H is the only family that needs patching: its stock linker has no glob
# that catches ".sram.text", so we inject KEEP(*(.sram.text*)) into the
# ".flash_copysection" output (which is flash-to-RAM0 copied at startup).
_MARKER = "/* esphome .sram.text */"
@@ -37,11 +30,6 @@ _KEEP_LINE = (
+ _MARKER + "\n"
)
_LN_COPY = re.compile(r"(\.flash_copysection\s*:\s*\{\s*\n)")
# RTL8710B's output section is ".ram_image2.text"; its stock linker consumes
# "*(.image2.ram.text*)" as an input glob inside that output, but we need to
# add a second input glob "*(.sram.text*)" so the ESPHome-marked functions
# land in the same RAM-resident output.
_RTL8710B_IMAGE2 = re.compile(r"(\.ram_image2\.text\s*:\s*\{\s*\n)")
def _detect(env):
@@ -83,11 +71,12 @@ def _inject_keep(host_section):
# Variants not listed here intentionally have no .ld patcher:
# - RTL8710B: hal.h uses section(".image2.ram.text") which the stock linker
# already routes into .ram_image2.text (> BD_RAM).
# - RTL8720C: stock linker already consumes *(.sram.text*).
# - BK72xx (all): SDK masks FIQ+IRQ around flash writes, IRAM_ATTR is no-op.
_PATCHERS_BY_VARIANT = {
"LN882H": (_inject_keep(_LN_COPY),),
"RTL8710B": (_inject_keep(_RTL8710B_IMAGE2),),
}
+6
View File
@@ -39,7 +39,13 @@
// layer.
#if defined(USE_BK72XX)
#define IRAM_ATTR
#elif defined(USE_LIBRETINY_VARIANT_RTL8710B)
// Stock linker consumes *(.image2.ram.text*) into .ram_image2.text (> BD_RAM).
#define IRAM_ATTR __attribute__((noinline, section(".image2.ram.text")))
#else
// RTL8720C: stock linker consumes *(.sram.text*) into .ram.code_text.
// LN882H: patch_linker.py.script injects *(.sram.text*) into
// .flash_copysection (> RAM0 AT> FLASH).
#define IRAM_ATTR __attribute__((noinline, section(".sram.text")))
#endif
#define PROGMEM