[rp2040] Bound the while loop in millis() accumulator

Same approach as ESP8266: split into common path (while loop, ≤10
iterations) and rare path (constant-time /1000 multiply for gaps
>10 ms). RP2040 has no ISR callers so no interrupt guard needed,
but the bounded loop avoids worst-case latency if millis() is
called from a context that was blocked for a long time.
This commit is contained in:
J. Nick Koston
2026-04-11 23:22:12 -10:00
parent 85c51967f5
commit 12d227dee8
+14 -4
View File
@@ -26,7 +26,8 @@ void HOT yield() { ::yield(); }
// s_last_us and ::micros() start at 0, so no special initialization needed.
//
// Also installed as __wrap_millis (via -Wl,--wrap=millis) so Arduino library
// code calling ::millis() directly gets the fast version.
// code calling ::millis() directly gets the fast version. No interrupt guard
// needed — no ESPHome ISR calls millis() on RP2040.
uint32_t HOT millis() {
static struct {
uint32_t cache;
@@ -37,9 +38,18 @@ uint32_t HOT millis() {
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;
if (state.remainder >= 10000) {
// Rare path: large gap (>10 ms — boot, long block). Constant-time
// multiply-by-reciprocal via /1000.
uint32_t ms = state.remainder / 1000;
state.cache += ms;
state.remainder -= ms * 1000;
} else {
// Common path: small gap. Loop runs at most 10 times.
while (state.remainder >= 1000) {
state.cache++;
state.remainder -= 1000;
}
}
return state.cache;
}