RV3028: backup switchover and trickle charging written to RAM only, so they revert at the next midnight; 0xB4 also overwrites a calibration bit
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 22/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- c
- Domain
- embedded-iot
Research direction
Read src/helpers/AutoDiscoverRTCClock.cpp around the writes to registers 0x35 and 0x37, then review the proposed procedure in linked issue #3545 and the RV-3028 manual sections cited here. Compare the EEPROM configuration with the RAM values and preserve the factory calibration bits when storing the settings. Done means the settings persist past midnight and time survives a power cut, as described in the hardware evidence.
Written by the indexing model from the issue text.
Description
The RV3028 backup switchover (and trickle charger) that AutoDiscoverRTCClock::begin() turns on is lost at the next midnight, and the same write overwrites a factory frequency-calibration bit. Proposed fix: #3545. Confirmed on hardware, before and after; see Evidence.
References used throughout:
- The manual: RV-3028-C7 Application Manual, Micro Crystal, Rev. 1.4, November 2021, from the Documents section of the product page: https://www.microcrystal.com/en/products/real-time-clock-rtc-modules/rv-3028-c7. Every "§" section number and "p." page number below is that document's.
- The code: upstream
devat3e3150c8(AutoDiscoverRTCClockis unchanged sincefad0ffb7, where the before-fix tests ran). - The RTC library: Melopero RV3028 Arduino library, tag
1.2.0, the version MeshCore builds against.
src/helpers/AutoDiscoverRTCClock.cpp L38-L39:
rtc_rv3028.writeToRegister(0x35, 0x00);
rtc_rv3028.writeToRegister(0x37, 0xB4); // Direct Switching Mode (DSM): when VDD < VBACKUP, switchover occurs from VDD to VBACKUP
Melopero's writeToRegister() is a plain I2C register write, so these change only the RAM mirror of two EEPROM-backed configuration registers.
1. The setting reverts at the next midnight
- §3.7, Control 1 (0Fh), bit EERD, p. 23. With EERD = 0, the default: "All data in the Configuration Registers are refreshed by the data stored in the EEPROM each 24 hours, at date increment (at the beginning of the last second before midnight)." §4.6.2 (p. 54) says the same.
- §4.6.9, p. 57. "To perform certain tests, it is sufficient to use only the RAM mirror. But the new, changed configurations are lost as soon as a refresh occurs (POR refresh, Automatic refresh or Refresh by software)."
- §3.15.6, EEPROM Backup (37h), p. 39. BSM = 00 ("Switchover Disabled") and TCE = 0 are the default values on delivery.
- §7.3, p. 105. The vendor's own rechargeable-backup circuit says: "Power Management settings have to be stored in EEPROM for permanent configuration".
On a part whose EEPROM still holds the factory value, the switchover and trickle charging enabled at boot turn off at the first midnight after boot, and stay off until the next reboot. A power cut after that midnight loses the time, and the supercapacitor stops being charged. That covers any repeater that stays up for more than a day.
The choice of mode is right. DSM with the trickle charger is what §7.3 (p. 105) specifies for a capacitor: "DSM Backup Switchover Mode for capacitors (or LSM for rechargeable battery)". What is missing is the EEPROM store.
2. 0xB4 overwrites the factory frequency calibration
Bit 7 of 37h is EEOffset[0], the LSB of the factory-calibrated frequency offset (§3.15.6, p. 39). §7.3 (p. 105) shows that bit as "0/1", meaning leave it as it is. Writing the whole byte forces it to 1. On a part calibrated with 0 there, that shifts the trim by one step until the next refresh: 0.9537 ppm per step (§3.15.5, p. 38). A fix that stored 0xB4 to EEPROM as-is would make that shift permanent.
The fix (#3545)
#3545 stores the configuration in EEPROM. Its body has the full procedure, with permalinks.
- Sequence. It follows §3.15.6 (p. 39), which says BSM must be 00 or 10 for any EEPROM read or write:
- EERD = 1, then wait for EEbusy (§4.6.7, p. 56).
- Hold BSM = 00 in RAM.
- Compare each config byte against the EEPROM with a single-byte read (§4.6.6, p. 55), and write only the bytes that differ with a single-byte write (§4.6.5, p. 55). Only CLKOE in 35h, and TCE, FEDE, BSM and TCR in 37h, are touched.
- A closing Refresh (§4.6.4, p. 54) restores the stored switchover. Read it back, then clear EERD.
- What it never writes. The factory calibration bits, 37h bit 7 and 36h.
- What this issue first suggested instead. A Refresh plus a whole-block Update (§4.6.3, p. 54) with BSM live, as Zephyr's
drivers/mfd/mfd_rv3028.cand Micro Crystal's Linux driver do. §3.15.6 was chosen instead, after testing on two boards found no spurious switchover either way. Only the §3.15.6 sequence stays valid when the backup sits above VDD, and it never rewrites the 36h trim.
Evidence
All power cuts were done by hand, with USB unplugged and no battery fitted. The hardware is RAK4631 + RAK12002 boards.
MeshCore, on a part whose EEPROM still held factory values. A throwaway diagnostic CLI (test/rv3028-diag) stepped the RTC to 23:59:50, so midnight passed in seconds. Full table, with the commit each test ran on: #3545, Testing.
- Before, on
devfad0ffb7:- After boot, RAM 37h =
B4, against EEPROM10, so bit 7 was forced to 1 against the chip's 0. - After RTC midnight, RAM 37h =
10: BSM = 00, TCE = 0, switchover off. - A ~60 s power cut then lost the time: the RTC came back at 2000-01-01, with PORF = 1.
- After boot, RAM 37h =
- After, with the fix:
- EEPROM 35h/37h =
40/34, written once, with the trim bit kept. - Nothing is written on reboot.
- It holds past midnight.
- A ~60 s power cut after midnight kept the time to the second, with BSF = 1 and PORF = 0.
- This was tested on both the first and the final sequence.
- EEPROM 35h/37h =
ZephCore (ptr727/liquidraver-ZephCore#35, same §3.15.6 sequence, second board):
- With the switchover never enabled, a 30 s cut came back with the power-loss flag set.
- With the EEPROM-stored configuration, a 31 s cut came back with the correct time, PORF clear and BSF set.
No spurious switchovers: status 0Eh was polled every 30 s on both boards (31 min on MeshCore, about 55 min on ZephCore). BSF never set outside a deliberate power cut.
Also resolved by #3545: the old RAM writes were issued without waiting for EEbusy, so a POR refresh (§4.6.1, p. 54) within about 66 ms of the RTC's own power-on could overwrite them. #3545 sets EERD and waits for EEbusy before touching the configuration. That race was never observed; the fix removes it by construction.
- Dominant language
- C
- Stars
- 3.9k
- Forks
- 1.5k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 24
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from meshcore-dev/MeshCore
-
Difficulty 2/5 1-3 hours Newbie friendliness 63/100
meshcore-dev/MeshCore#3622 ·
Maintainers usually reply within 1 day
-
[Feature Request] Set Australia (Mid) Preset to automatically enable 2 byte default path hash sizeOpen
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
meshcore-dev/MeshCore#3571 · 5 reactions ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
meshcore-dev/MeshCore#3567 · 1 comment ·
Maintainers usually reply within 1 day
-
RTC_RX8130CE writes and reads the one-hot WEEK register as a numberPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
meshcore-dev/MeshCore#3549 ·
Maintainers usually reply within 1 day
-
Repeater: CLI reply to 'setperm <key> 0' is lost when the removed ACL entry sits before the requester (stale ClientInfo* after array shift)Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
meshcore-dev/MeshCore#3513 ·
Maintainers usually reply within 1 day
All issues in meshcore-dev/MeshCore
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
colbymchenry/codegraph#2770 ·
Maintainers usually reply within 1 day
-
area/ysql kind/enhancement priority/medium status/awaiting-triage
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
yugabyte/yugabyte-db#35578 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
Maintainers usually reply within 1 day
-
Bug Status: Needs Triage
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
interpreter-core type-feature
Difficulty 1/5 Under an hour Newbie friendliness 78/100
Maintainers usually reply within 1 day