mirror of
https://github.com/liquidraver/ZephCore.git
synced 2026-10-15 22:49:59 +00:00
The RAK4631 overlay declared no zephcore,rtc-i2c candidate, so a fitted RAK12002 (an RV3028 at 0x52) was never probed or written, and every power cut started the node at 1970. Declaring it is not enough: the RV3028 ships with backup switchover disabled (EEPROM 37h BSM = 00), so a power cut still loses the time. The overlay now declares the RV3028 with the zero-mask rtc-i2c.dtsi uses for it, and a new optional rv3028-eeprom-config descriptor property holds (register, mask, value) triplets for its EEPROM configuration registers 35h-37h. The RAK4631 sets direct switchover with the trickle charger on (TCE, BSM = 01, TCR 3 kOhm), as the RV-3028-C7 Application Manual (Rev. 1.4) 7.3 prescribes for a capacitor backup, FEDE set as 3.15.6 says it always should be, and CLKOUT off. The configuration has to live in EEPROM: the chip reloads its configuration RAM from EEPROM at power-on and every midnight (4.6.2). The store runs only when a read identified the chip (RTC_FOUND, not an adoption on a failed second read) and a BSF-checked time read just before it showed no switchover. It follows 3.15.6 (BSM 00 or 10 for any EEPROM access): EERD held, switchover off in RAM, each configured byte compared against the EEPROM with a single-byte read and written only if it differs, and a closing Refresh that restores the stored switchover mode, read back on every boot. 36h, the factory trim, is never written. Switchover is turned back on only once EEbusy reads 0; otherwise it stays off until a retry or the daily refresh. A failed store sets the config in RAM (also only once EEbusy reads 0). A failed or skipped store is retried every 10 minutes, at most 3 times per boot, each retry identifying the chip again first. A switchover disables the chip's I2C mid-transfer (4.2), so at a node with rv3028-eeprom-config the time is read at boot and written on each sync with BSF cleared before and checked after. A read that saw a switchover gives no time. A write sets year 00h first and the real year last, so a power loss cutting it between its first and last byte leaves year 2000 and the next boot takes no time from it, and a write not confirmed is repeated every 5 s, up to 12 times, with the time run on. All of the RV3028 code is compiled only when some node carries rv3028-eeprom-config, so other boards, thinknode_m1 among them, build the same RTC object as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
3.8 KiB
C
80 lines
3.8 KiB
C
/*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
* Boot-time hardware-RTC auto-discovery (compact raw-I2C reader).
|
|
*
|
|
* Probes every I2C RTC chip declared with the "zephcore,rtc-i2c" binding
|
|
* (boards/common/rtc-i2c.dtsi, or a board's own overlay). Chips that aren't
|
|
* physically present fail the probe and are skipped — like the environment
|
|
* sensors.
|
|
*
|
|
* If a present chip holds a valid time, zephcore_rtc_restore() returns it so
|
|
* the soft clock can be seeded at boot (shown tagged "L" — local). Every
|
|
* ZephyrRTCClock::setCurrentTime() writes it back via zephcore_rtc_save(), so
|
|
* time survives the next power-off.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/*
|
|
* Probe the declared RTC chips in order, stopping at the first that holds a
|
|
* sane time (year >= 2025 and its power-loss flag clear): store its Unix
|
|
* epoch in *epoch_out and return true. The first chip found (valid time or
|
|
* not) is remembered as the write-back target. A failed first read means
|
|
* nothing is there, and a first read of all 0xFF (an erased EEPROM) is
|
|
* skipped. Otherwise a device is passed over only if two reads each show it
|
|
* is not that RTC: a bit set that the data sheet shows as 0 (the
|
|
* descriptor's zero-mask), seconds, minutes, date or month out of range
|
|
* while the power-loss flag does not read as set (an unreadable flag counts
|
|
* as not set), or, on the second read, all 0xFF. A failed second read never
|
|
* rules a device out. A time is taken only from a clean read whose fields,
|
|
* hours and year are each in range (12-hour mode is not decoded). Returns
|
|
* false if none present or no trustworthy time is held.
|
|
*
|
|
* At a descriptor with rv3028-eeprom-config, the time is read once more
|
|
* with the chip's backup switch flag (BSF) cleared before and checked
|
|
* after, and is not taken if the read failed or BSF was set. A chip adopted
|
|
* on a read that identified it (not on a failed second read), with BSF
|
|
* clear, has that config stored at once: after the power-on refresh (up to
|
|
* ~66 ms), backup switchover is turned off while the EEPROM is read, each
|
|
* byte that differs is written, and a refresh from EEPROM restores it.
|
|
* Measured on a RAK4631: about 14 ms when nothing is written, 52 ms for two
|
|
* bytes, then up to 2 ms for DSM to react (4.2.2). If the store fails, the
|
|
* config is set in RAM, which lasts until the chip's next refresh from
|
|
* EEPROM (daily while EERD is clear), and only once EEbusy reads 0;
|
|
* otherwise switchover stays as the store left it, off once the store has
|
|
* disabled it, until a retry or that refresh. A failed store, or one
|
|
* skipped at boot, is retried on the system work queue every 10 minutes, at
|
|
* most 3 times, each retry identifying the chip again first.
|
|
*/
|
|
bool zephcore_rtc_restore(uint32_t *epoch_out);
|
|
|
|
/*
|
|
* Persist an authoritative epoch to the discovered RTC chip and clear its
|
|
* power-loss flag. No-op if no RTC was discovered. Safe to call often, but
|
|
* intended only for real syncs (GPS/app/CLI), not per-packet clock nudges.
|
|
* If restore adopted nothing but skipped a candidate whose first read was all
|
|
* 0xFF, the first save probes again, once per boot, in the caller's context.
|
|
* A device ruled out on its second read is not probed again for that reason.
|
|
*
|
|
* At a descriptor with rv3028-eeprom-config the time is written with BSF
|
|
* cleared before and checked after, year 00h first and the real year last,
|
|
* so a write cut by a power loss reads at boot as "time not yet set". A
|
|
* write not confirmed is repeated every 5 s on the system work queue, with
|
|
* the time run on, until one is confirmed, a newer save replaces it, or 12
|
|
* repeats (13 attempts in all) have failed. Call only from the system work
|
|
* queue: the repeat shares state with this call.
|
|
*/
|
|
void zephcore_rtc_save(uint32_t epoch);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|