Commit Graph
27813 Commits
Author SHA1 Message Date
J. Nick Koston 8dba87014a libretiny: use strong linker assignments for SRAM text markers
PROVIDE symbols without references get garbage-collected by the linker, so
the post-link summary was falling back to the symbol-scrape path on every
family. Use direct assignment so the markers always land in the ELF symbol
table, giving an exact byte count for the ESPHome IRAM_ATTR contribution.
2026-04-15 14:07:31 -10:00
J. Nick Koston ab382c1e52 libretiny: print IRAM_ATTR placement summary after link
After linking, walk the ELF symbol table and print one of:

  ESPHome: IRAM_ATTR placement summary (BK7231N):
    .sram.text:  312 bytes at 0x004001d0 - 0x00400308

  ESPHome: IRAM_ATTR placement summary (RTL8720C):
    IRAM symbols at 0x10002f6c - 0x10002fa8 (approx 60 bytes)

On the three families whose linker scripts we already patch (BK72xx, LN882H,
RTL8710B) the PROVIDE(__esphome_sram_text_start/end = .) markers injected
alongside KEEP(*(.sram.text*)) give an exact byte count for the ESPHome
IRAM_ATTR contribution. On RTL8720C we cannot patch the linker script (it
is loaded directly from the framework package) so the summary falls back to
reading the addresses of the three core IRAM_ATTR symbols. Either way the
address range is visible proof that the functions ended up in SRAM rather
than flash.
2026-04-15 14:05:48 -10:00
J. Nick Koston 33118e0e57 libretiny: patch_linker.py.script — fail hard if IRAM_ATTR cannot land in SRAM
Two issues from the cb3s smoke test:

- The previous CPPDEFINES-only variant detection missed the
  USE_LIBRETINY_VARIANT_* define on BK72xx in the pre-script environment,
  so no patcher registered and the .sram.text section silently landed in
  flash. Check BUILD_FLAGS as a fallback so the define is picked up
  regardless of when PlatformIO finishes populating CPPDEFINES.

- When the variant could not be detected, or no .ld file was modified, the
  script exited quietly and the firmware linked with IRAM_ATTR functions
  in flash — the exact bug this PR is trying to fix. Raise a RuntimeError
  in all three failure cases (variant missing, variant unknown, no .ld
  patched) so the build fails loudly instead of producing broken firmware.
2026-04-15 13:59:42 -10:00
J. Nick Koston 55845b3e85 Address copilot review: update extra_scripts comment to match current implementation 2026-04-15 13:56:39 -10:00
J. Nick Koston 90b311258a libretiny: move Beken extern "C" declaration out of function body 2026-04-15 13:54:23 -10:00
J. Nick Koston e5b46540ee libretiny: fix BK72xx Thumb asm; unify IRAM_ATTR on .sram.text
Two fixes on top of the initial landing:

- BK72xx builds Thumb-mode TUs alongside its ARM FreeRTOS port, and the
  MRS CPSR instruction is ARM-only, so in_isr_context() failed to
  assemble on cb3s. Delegate to the port's own platform_is_in_interrupt_context()
  helper (declared extern "C" in portmacro.h and built in ARM mode) instead
  of embedding inline CPSR reads in Thumb code.

- Section name unified to ".sram.text" for every LibreTiny family to avoid
  the "setting incorrect section attributes for .data.*" GAS warning. The
  pre-link patcher now knows how to route that section into each family's
  RAM-resident output:
    * BK72xx: flip SRAM region (rw!x) -> (rwx) and inject
      KEEP(*(.sram.text*)) into .data : { ... }
    * LN882H: inject KEEP(*(.sram.text*)) into .flash_copysection : { ... }
    * RTL8710B: inject KEEP(*(.sram.text*)) into .image2.ram.text : { ... }
    * RTL8720C: no-op (linker already consumes *(.sram.text*))
  The injection uses a "/* esphome .sram.text */" marker so repeated runs
  are idempotent.
2026-04-15 13:53:35 -10:00
J. Nick Koston f404768fd1 libretiny: fix BK72xx build — guard portYIELD_FROM_ISR; use .data.iram_text
Two issues surfaced building cb3s-test.yaml:

1. BK72xx's ARM9 FreeRTOS port does not define portYIELD_FROM_ISR; context
   switches happen naturally at IRQ exit. Wrap the call in #ifdef so the
   wake path compiles on ports that lack it.

2. Placing functions directly in section(".data") provoked assembler
   "ignoring changed section attributes" warnings and a hard DWARF error
   ("leb128 operand is an undefined symbol: .LVU31") because the compiler
   emits code-style attributes ("ax") that collide with .data's
   data-style attributes ("aw"). Use section(".data.iram_text") instead;
   the linker still folds it into the .data output via "*(.data.*)", so
   the bytes land in SRAM via the SDK's .data copy, but the assembler no
   longer sees conflicting attributes.
2026-04-15 13:48:11 -10:00
J. Nick Koston c1ef3cab37 libretiny: wire copy_files() through each target_platform module
target_platform for LibreTiny devices is one of bk72xx, rtl87xx, ln882x
(not "libretiny" itself), so writer.py's platform-dispatched copy_files()
call was not reaching libretiny.copy_files(). That left the pre-link
patch_linker.py script absent from the build dir, so PlatformIO failed
with "missing SConscript file 'patch_linker.py'".

Add a delegating copy_files() to each generated sub-component and to
generate_components.py so regeneration keeps them in sync.
2026-04-15 13:46:37 -10:00
J. Nick Koston 3e5c4fd603 Make IRAM_ATTR functional on LibreTiny
Previously, IRAM_ATTR was an empty no-op on every LibreTiny family, so any
ISR handler (gpio binary sensor, cc1101, sx126x/sx127x, mcp23xxx, pcf8574,
pca9554, pca6416a, pi4ioe5v6408, tca9555, ...) lived in flash. When the
ISR fired while flash was busy (XIP stall, OTA, logger flash write), the
device could deadlock or crash.

- hal.h: IRAM_ATTR now routes each family into a RAM-resident section
  (RTL8710B .image2.ram.text, RTL8720C .sram.text, BK72xx / LN882H .data,
  which the SDK startup code copies from flash into SRAM before main).
  Also adds esphome::in_isr_context() as a portable always_inline ISR
  detection helper: xPortInIsrContext on ESP32, PS.INTLEVEL on ESP8266,
  IPSR on Cortex-M cores, CPSR mode on BK72xx ARM9.

- main_task.h: both notify helpers marked always_inline so IRAM callers
  keep the wake path in IRAM; removes the ESP32-only notify_any_context
  which moves into wake.h.

- wake.h / wake.cpp: LibreTiny now shares the ESP32 wake path via a new
  wake_main_task_any_context() helper that picks between xTaskNotifyGive
  and vTaskNotifyGiveFromISR using in_isr_context(). wake_loop_any_context
  and wake_loop_isrsafe are now IRAM_ATTR entry points on LibreTiny too.

- libretiny/patch_linker.py.script: pre-link hook modelled on the ESP8266
  testing_mode patcher. BK72xx linker templates declare the SRAM region
  as (rw!x), blocking code placement in .data. The hook flips that to
  (rwx) so IRAM_ATTR functions can be emitted there; the MMU already
  permits RAM execution (the Wi-Fi driver runs from SRAM). No-op on the
  other families.
2026-04-15 13:42:17 -10:00
dependabot[bot] 403a9f7b7e Bump github/codeql-action from 4.35.1 to 4.35.2 (#15759)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 10:12:30 -10:00
dependabot[bot] 10f52f2056 Bump aioesphomeapi from 44.15.0 to 44.16.0 (#15757)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-15 09:07:49 -10:00
Jonathan Swoboda 274c01ca74 [sx126x][sx127x] Fix frequency precision loss from float32 codegen (#15753) 2026-04-15 14:32:33 -04:00
Jonathan Swoboda 3b82c6e38b [st7789v] Fix swapped offset_width/offset_height in model presets (#15755) 2026-04-15 14:32:11 -04:00
Jesse Hills f59a1011df Merge branch 'release' into dev 2026-04-15 22:45:16 +12:00
Jesse Hills 82c0cb8929 Merge pull request #15745 from esphome/bump-2026.4.0
2026.4.0
2026.4.0
2026-04-15 22:44:27 +12:00
Jesse Hills 2bdd9f6217 Bump version to 2026.4.0 2026-04-15 20:44:30 +12:00
J. Nick Koston d516911d86 Merge remote-tracking branch 'origin/fast-millis-esp32' into integration 2026-04-14 22:05:36 -10:00
J. Nick Koston 6a6d9bb808 cleanup 2026-04-14 21:58:22 -10:00
J. Nick Koston 4dcaea15a3 missed some sites 2026-04-14 21:54:48 -10:00
J. Nick Koston d11e9dc7a2 Merge branch 'dev' into fast-millis-esp32 2026-04-14 21:48:31 -10:00
J. Nick Koston e669008e50 Merge remote-tracking branch 'upstream/fast-millis-esp32' into integration 2026-04-14 21:26:32 -10:00
J. Nick Koston 84a98e6ece internal 2026-04-14 21:22:02 -10:00
J. Nick Koston cf994c3b9f back to inlock divide .. was overkill and 20% regression 2026-04-14 20:48:50 -10:00
J. Nick Koston 8f3bebd0f6 Merge branch 'fast-millis-esp8266' of https://github.com/esphome/esphome into fast-millis-esp8266 2026-04-14 20:42:42 -10:00
J. Nick Koston 3912ede2cf safer 2026-04-14 20:42:25 -10:00
J. Nick Koston a0d617904e Merge branch 'dev' into fast-millis-esp8266 2026-04-14 20:33:56 -10:00
J. Nick Koston 0545365af3 Merge remote-tracking branch 'upstream/runtime-stats-loop-overhead' into integration 2026-04-14 17:10:10 -10:00
J. Nick Koston a20680311c [runtime_stats] Rename global_recorded_us per clang-tidy, use double for ms conversions
- Drop trailing underscore on ComponentRuntimeStats::global_recorded_us
  (public static, clang-tidy readability-identifier-naming).
- Use double instead of float for uint64_t microsecond → millisecond
  conversions on the main_loop and main_loop_overhead_section lines.
  Float's ~7-digit mantissa loses resolution on multi-day totals that
  reach into the 10^8-10^9 microsecond range.
2026-04-14 17:09:20 -10:00
J. Nick Koston ba82a0f288 Merge remote-tracking branch 'upstream/runtime-stats-loop-overhead' into integration 2026-04-14 17:02:28 -10:00
J. Nick Koston a3a531f672 [runtime_stats] Subtract scheduled-callback time from before bucket
The scheduler also constructs WarnIfComponentBlockingGuard around
scheduled item execution (scheduler.cpp:740), so set_interval /
set_timeout / defer callbacks record into the affected component's
runtime_stats_. Since scheduler.call() runs inside before_loop_tasks_,
that time was double-counted: once in component period/total, once
in the "before" overhead bucket. Observed in the field as
before > overhead_total with inter_component clamped to 0.

Fix: add a global cumulative counter on ComponentRuntimeStats that
record_time() bumps on every guard finish, snapshot it around
before_loop_tasks_, and subtract the delta from the before bucket
before passing it to record_loop_active.
2026-04-14 16:58:03 -10:00
J. Nick Koston 5d2e7a014c [runtime_stats] Split main loop overhead into before/tail/inter_component
Adds a second log line per section that breaks overhead down into:
  before          — time in before_loop_tasks_ (scheduler + ISR enable_loop)
  tail            — time in after_loop_tasks_ + trailing record prefix
  inter_component — residual: per-iteration bookkeeping between components
                    (set_current_component, WarnIfComponentBlockingGuard
                    construction/destruction, feed_wdt_with_time, the for
                    loop itself)

Useful for isolating whether per-loop overhead changes come from
scheduler work, loop teardown, or inter-component bookkeeping.
2026-04-14 16:50:27 -10:00
J. Nick Koston 21e6498ee2 Merge remote-tracking branch 'upstream/runtime-stats-loop-overhead' into integration 2026-04-14 16:34:42 -10:00
J. Nick Koston 2f14912196 [runtime_stats] Widen iteration counters, fix overhead total, test main_loop line
- Widen period/total iteration counters to uint64_t to avoid wrapping on
  long-running high-frequency loops.
- Compute total component-time sum over all components (not just the
  period-active subset) so total overhead is not inflated by components
  that ran earlier but are idle now.
- Extend integration test to parse the main_loop line and validate the
  iters/active_avg/active_total/overhead_total fields.
2026-04-14 16:33:39 -10:00
J. Nick Koston 65f0d4a000 merge 2026-04-14 16:28:50 -10:00
J. Nick Koston 2c1f01c76c Merge remote-tracking branch 'upstream/runtime-stats-loop-overhead' into integration 2026-04-14 16:25:06 -10:00
J. Nick Koston e93f49978b [runtime_stats] Track main loop active time and report overhead
Records per-iteration active wall time (excluding yield/sleep) and
reports it alongside the component table. Overhead is computed at log
time as active_total minus the sum of per-component time, exposing time
spent in scheduler dispatch, before/after-loop tasks, and other loop
machinery not attributed to any component.
2026-04-14 16:19:12 -10:00
J. Nick Koston 39eb8dbcf5 Revert "[debug] Add iram sensor for ESP32"
This reverts commit 07b129a58a.
2026-04-14 16:05:33 -10:00
J. Nick Koston 5364ea04ef Revert "[debug] Use MALLOC_CAP_EXEC for iram sensor"
This reverts commit 8a00d302b8.
2026-04-14 16:05:32 -10:00
J. Nick Koston 8a41d5503e Revert "[debug] Fix iram sensor to report IRAM-only free"
This reverts commit 3fa50a27a8.
2026-04-14 16:05:31 -10:00
J. Nick Koston 4d13bd96a6 Merge remote-tracking branch 'origin/debug-iram-sensor' into integration 2026-04-14 15:58:12 -10:00
J. Nick Koston 3fa50a27a8 [debug] Fix iram sensor to report IRAM-only free 2026-04-14 15:57:51 -10:00
J. Nick Koston 363f10c837 Merge remote-tracking branch 'origin/debug-iram-sensor' into integration 2026-04-14 15:53:47 -10:00
J. Nick Koston 8a00d302b8 [debug] Use MALLOC_CAP_EXEC for iram sensor 2026-04-14 15:53:02 -10:00
J. Nick Koston 07cf968226 Merge remote-tracking branch 'upstream-ssh/debug-iram-sensor' into integration 2026-04-14 15:49:52 -10:00
J. Nick Koston 07b129a58a [debug] Add iram sensor for ESP32 2026-04-14 15:47:48 -10:00
Jesse Hills 193e7d476d Pin GitHub Actions to commit SHAs
Replace mutable tag references with immutable commit SHAs
to prevent supply-chain attacks via compromised tags.
Version comments are preserved for readability.
2026-04-15 13:12:20 +12:00
Jesse Hills 1b3e7d5ec4 Merge branch 'beta' into dev 2026-04-15 13:10:45 +12:00
Jesse Hills 767a8c49b0 Merge pull request #15739 from esphome/bump-2026.4.0b3
2026.4.0b3
2026.4.0b3
2026-04-15 13:10:09 +12:00
J. Nick Koston 222626eb8c Merge remote-tracking branch 'upstream/fast-millis-esp32' into integration
# Conflicts:
#	esphome/core/application.cpp
#	esphome/core/time_64.cpp
2026-04-14 15:04:47 -10:00
J. Nick Koston 80e29bc7b2 Merge remote-tracking branch 'upstream/optimize-value-accuracy' into integration 2026-04-14 15:01:45 -10:00