mirror of
https://github.com/esphome/esphome.git
synced 2026-09-01 10:36:01 +00:00
libretiny: scope BK72xx IRAM_ATTR to BK7231N; T/Q/7251 stay no-op
BK7231T / BK7231Q / BK7251 share a LibreTiny linker template that only declares flash + ram, no executable RAM region. Their SDK wraps flash writes in GLOBAL_INT_DISABLE() which masks both FIQ and IRQ, so no ISR fires while flash is stalled and the "code in flash while flash is busy" scenario IRAM_ATTR is guarding against does not occur on those variants. Map IRAM_ATTR to nothing on them rather than orphan-linking .sram.text into flash and drop the T/Q/7251 entries from _PATCHERS_BY_VARIANT so the pre-link hook is not registered for them. BK7231N still gets the full fix (grown .itcm.code) because its SDK takes the defense-in-depth route of also placing flash/ISR/FreeRTOS critical code in ITCM, so our IRAM_ATTR functions need to live there too. Also make _grow_bk72xx_itcm fail loudly if the tcm/itcm declarations in the BK7231N template ever change shape, matching the fail-hard stance of the rest of the script.
This commit is contained in:
@@ -467,15 +467,17 @@ 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") (see
|
||||
# esphome/core/hal.h). This pre-link hook rewrites the processed .ld
|
||||
# files in the build dir so that section lands in an executable RAM
|
||||
# output section on each family:
|
||||
# - BK72xx: inject KEEP(*(.sram.text*)) into .itcm.code (the only
|
||||
# rwx RAM region; main SRAM is rw!x on ARM968E-S).
|
||||
# IRAM_ATTR on LibreTiny expands to section(".sram.text") on families
|
||||
# where executable RAM is available (see esphome/core/hal.h). This pre-
|
||||
# link hook rewrites the processed .ld files in the build dir so that
|
||||
# section lands in each family's executable RAM output section:
|
||||
# - BK7231N: grow .itcm from 4.5 kB to 8.5 kB (steal from .tcm) and
|
||||
# inject KEEP(*(.sram.text*)) into .itcm.code.
|
||||
# - LN882H: inject KEEP(*(.sram.text*)) into .flash_copysection.
|
||||
# - RTL8710B: inject KEEP(*(.sram.text*)) into .image2.ram.text.
|
||||
# - RTL8720C: no-op (stock linker already consumes *(.sram.text*)).
|
||||
# BK7231T/Q/7251 have no executable RAM region; their SDK disables IRQ
|
||||
# + FIQ around flash writes, so IRAM_ATTR is left a no-op on them.
|
||||
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)"))
|
||||
|
||||
@@ -52,9 +52,20 @@ _BK_ITCM_REGION = re.compile(
|
||||
|
||||
def _grow_bk72xx_itcm(content):
|
||||
# Shrink tcm by 4 kB: 60k - 512 -> 56k - 512.
|
||||
new_content = _BK_TCM_LEN.sub(r"\g<1>56k\g<2>", content)
|
||||
new_content, tcm_count = _BK_TCM_LEN.subn(r"\g<1>56k\g<2>", content)
|
||||
# Shift itcm origin back 4 kB and grow length: 4k + 512 -> 8k + 512.
|
||||
new_content = _BK_ITCM_REGION.sub(r"\g<1>0x003FDE00\g<2>8k\g<3>", new_content)
|
||||
new_content, itcm_count = _BK_ITCM_REGION.subn(
|
||||
r"\g<1>0x003FDE00\g<2>8k\g<3>", new_content
|
||||
)
|
||||
if tcm_count != 1 or itcm_count != 1:
|
||||
raise RuntimeError(
|
||||
"ESPHome: BK72xx linker script did not match the expected "
|
||||
"tcm/itcm declarations (tcm matches: {}, itcm matches: {}); "
|
||||
"refusing to link because IRAM_ATTR placement cannot be verified. "
|
||||
"LibreTiny probably changed the bk7231*_bsp.template.ld layout, "
|
||||
"update _BK_TCM_LEN / _BK_ITCM_REGION in patch_linker.py.script "
|
||||
"before shipping firmware.".format(tcm_count, itcm_count)
|
||||
)
|
||||
return new_content
|
||||
|
||||
|
||||
@@ -96,13 +107,13 @@ def _inject_keep(host_section):
|
||||
return patch
|
||||
|
||||
|
||||
# RTL8720C is absent: its stock linker already consumes *(.sram.text*), so
|
||||
# no .ld patch is needed; the summary falls back to reading symbol addresses.
|
||||
# Variants not listed here intentionally have no .ld patcher:
|
||||
# - RTL8720C: stock linker already consumes *(.sram.text*).
|
||||
# - BK7231T / BK7231Q / BK7251: SDK wraps flash ops in GLOBAL_INT_DISABLE()
|
||||
# (FIQ + IRQ masked), so no ISR fires during a flash stall and IRAM_ATTR
|
||||
# is a no-op on those variants (see esphome/core/hal.h).
|
||||
_PATCHERS_BY_VARIANT = {
|
||||
"BK7231N": (_grow_bk72xx_itcm, _inject_keep(_BK_ITCM)),
|
||||
"BK7231T": (_grow_bk72xx_itcm, _inject_keep(_BK_ITCM)),
|
||||
"BK7231Q": (_grow_bk72xx_itcm, _inject_keep(_BK_ITCM)),
|
||||
"BK7251": (_grow_bk72xx_itcm, _inject_keep(_BK_ITCM)),
|
||||
"LN882H": (_inject_keep(_LN_COPY),),
|
||||
"RTL8710B": (_inject_keep(_RTL8710B_IMAGE2),),
|
||||
}
|
||||
|
||||
+15
-6
@@ -24,13 +24,22 @@
|
||||
#elif defined(USE_LIBRETINY)
|
||||
|
||||
// IRAM_ATTR places a function in executable RAM so it is callable from an
|
||||
// ISR even while flash is busy (XIP stall, OTA, logger flash write). All
|
||||
// LibreTiny families use ".sram.text"; patch_linker.py.script routes it
|
||||
// into each family's RAM-executable output section (.itcm.code on BK72xx,
|
||||
// .image2.ram.text on RTL8710B, .flash_copysection on LN882H). RTL8720C's
|
||||
// stock linker already consumes *(.sram.text*) via its .ram.code_text
|
||||
// output.
|
||||
// ISR even while flash is busy (XIP stall, OTA, logger flash write).
|
||||
// patch_linker.py.script routes ".sram.text" into each family's RAM-
|
||||
// executable output section: .itcm.code on BK7231N, .image2.ram.text on
|
||||
// RTL8710B, .flash_copysection on LN882H, stock *(.sram.text*) glob on
|
||||
// RTL8720C.
|
||||
//
|
||||
// BK7231T/Q/7251 are left as a no-op: their SDK wraps flash operations in
|
||||
// GLOBAL_INT_DISABLE() which masks FIQ + IRQ for the duration of the
|
||||
// write, so no ISR fires while flash is stalled and the scenario
|
||||
// IRAM_ATTR guards against does not occur there.
|
||||
#if defined(USE_LIBRETINY_VARIANT_BK7231T) || defined(USE_LIBRETINY_VARIANT_BK7231Q) || \
|
||||
defined(USE_LIBRETINY_VARIANT_BK7251)
|
||||
#define IRAM_ATTR
|
||||
#else
|
||||
#define IRAM_ATTR __attribute__((noinline, section(".sram.text")))
|
||||
#endif
|
||||
#define PROGMEM
|
||||
|
||||
#else
|
||||
|
||||
Reference in New Issue
Block a user