From 3d3e26d141af2bce145948d966921993b5aedacc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 11 Apr 2026 23:10:19 -1000 Subject: [PATCH] [esp8266] Merge millis_accumulator into millis(), use struct for statics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge the separate millis_accumulator() function directly into millis() to eliminate the extra function call overhead and prologue/epilogue. Pack the three statics into a struct so the compiler loads one base address instead of three literal pool entries. Saves ~12 bytes of IRAM (87+6 → 81 bytes). --- esphome/components/esp8266/core.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index 6df0db7a1c..02aea6f2e8 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -35,24 +35,27 @@ void HOT yield() { ::yield(); } // ::millis() directly also get the fast version. Interrupts are briefly disabled // (~10 instructions, ~125 ns at 80 MHz) to protect the static state from // concurrent ISR access. -static uint32_t IRAM_ATTR HOT millis_accumulator() { - static uint32_t s_cache = 0; - static uint32_t s_remainder = 0; - static uint32_t s_last_us = 0; +uint32_t IRAM_ATTR HOT millis() { + // Struct packs the three statics so the compiler loads one base address + // instead of three separate literal pool entries (saves ~8 bytes IRAM). + static struct { + uint32_t cache; + uint32_t remainder; + uint32_t last_us; + } state = {0, 0, 0}; uint32_t ps = xt_rsil(15); uint32_t now_us = system_get_time(); - uint32_t delta = now_us - s_last_us; - s_last_us = now_us; - s_remainder += delta; - while (s_remainder >= 1000) { - s_cache++; - s_remainder -= 1000; + uint32_t delta = now_us - state.last_us; + state.last_us = now_us; + state.remainder += delta; + while (state.remainder >= 1000) { + state.cache++; + state.remainder -= 1000; } - uint32_t result = s_cache; + uint32_t result = state.cache; xt_wsr_ps(ps); return result; } -uint32_t IRAM_ATTR HOT millis() { return millis_accumulator(); } uint64_t millis_64() { return Millis64Impl::compute(millis()); } // Avoid calling ::delay() which pulls in __delay from core_esp8266_wiring.cpp. // __delay has an intra-object call to the original millis() that --wrap=millis