Category
Other
Hardware
Raspberry Pi Pico (W)
Is this bug report about any UI component firmware like InkHUD or Meshtatic UI (MUI)?
Firmware Version
2.7.20
Description
Since PR #9493 (200e79e80 — "You get an RTC, and you get an RTC!"), platforms without a hardware RTC (e.g., RP2040) lose their network-derived time immediately after it is set.
Root Cause
PR #9493 removed the #if HAS_RTC guard around readFromRTC() in perhapsSetRTC() (RTC.cpp, line ~283):
// Before #9493:
#if HAS_RTC
readFromRTC();
#endif
// After #9493:
readFromRTC();
On platforms without a hardware RTC, readFromRTC() falls into the #else branch which calls gettimeofday(). On RP2040, gettimeofday() returns uptime (seconds since boot), not wall-clock time, because there is no settimeofday() call for RP2040 in perhapsSetRTC() (only ESP32 has one).
This causes the following sequence:
perhapsSetRTC() correctly sets zeroOffsetSecs to the network time (e.g., 1772717422)
perhapsSetRTC() calls readFromRTC()
readFromRTC() calls gettimeofday() which returns uptime (e.g., 21)
readFromRTC() unconditionally overwrites zeroOffsetSecs = 21
getTime() now returns uptime instead of wall-clock time for the rest of the session
Impact
getTime() returns uptime seconds (~21) instead of epoch time (~1.7 billion)
getValidTime(RTCQualityFromNet) returns tiny values, causing rx_time on all received packets to be uptime-based
NodeDB::updateFrom() sets last_heard to uptime values for newly heard nodes
- Nodes loaded from flash have real timestamps, so newly heard nodes appear "oldest" and get immediately evicted from the nodeDB when it is full
- Rapid nodeDB churn: 222 evictions observed in a single ~3 hour session on a node with
MAX_NUM_NODES=100
Affected Platforms
Any platform without a hardware RTC where gettimeofday() does not reflect time set via the internal zeroOffsetSecs mechanism. Confirmed on RP2040.
Fix
Add the same currentQuality == RTCQualityNone guard that all hardware RTC branches already use in readFromRTC():
// In readFromRTC(), the #else branch (platforms without hardware RTC):
if (!gettimeofday(&tv, NULL)) {
uint32_t now = millis();
uint32_t printableEpoch = tv.tv_sec;
LOG_DEBUG("Read RTC time as %ld", printableEpoch);
if (currentQuality == RTCQualityNone) { // <-- add this guard
timeStartMsec = now;
zeroOffsetSecs = tv.tv_sec;
}
return RTCSetResultSuccess;
}
This matches the existing pattern in the RV3028, PCF8563/PCF85063, and RX8130CE branches which all check if (currentQuality == RTCQualityNone) before overwriting the time.
Introduced In
Relevant log output
Category
Other
Hardware
Raspberry Pi Pico (W)
Is this bug report about any UI component firmware like InkHUD or Meshtatic UI (MUI)?
Firmware Version
2.7.20
Description
Since PR #9493 (
200e79e80— "You get an RTC, and you get an RTC!"), platforms without a hardware RTC (e.g., RP2040) lose their network-derived time immediately after it is set.Root Cause
PR #9493 removed the
#if HAS_RTCguard aroundreadFromRTC()inperhapsSetRTC()(RTC.cpp, line ~283):On platforms without a hardware RTC,
readFromRTC()falls into the#elsebranch which callsgettimeofday(). On RP2040,gettimeofday()returns uptime (seconds since boot), not wall-clock time, because there is nosettimeofday()call for RP2040 inperhapsSetRTC()(only ESP32 has one).This causes the following sequence:
perhapsSetRTC()correctly setszeroOffsetSecsto the network time (e.g.,1772717422)perhapsSetRTC()callsreadFromRTC()readFromRTC()callsgettimeofday()which returns uptime (e.g.,21)readFromRTC()unconditionally overwriteszeroOffsetSecs = 21getTime()now returns uptime instead of wall-clock time for the rest of the sessionImpact
getTime()returns uptime seconds (~21) instead of epoch time (~1.7 billion)getValidTime(RTCQualityFromNet)returns tiny values, causingrx_timeon all received packets to be uptime-basedNodeDB::updateFrom()setslast_heardto uptime values for newly heard nodesMAX_NUM_NODES=100Affected Platforms
Any platform without a hardware RTC where
gettimeofday()does not reflect time set via the internalzeroOffsetSecsmechanism. Confirmed on RP2040.Fix
Add the same
currentQuality == RTCQualityNoneguard that all hardware RTC branches already use inreadFromRTC():This matches the existing pattern in the RV3028, PCF8563/PCF85063, and RX8130CE branches which all check
if (currentQuality == RTCQualityNone)before overwriting the time.Introduced In
200e79e80, merged 2026-01-30Relevant log output