Repository navigation
Conversation
…hour mode ZephCore assumed 24-hour mode. If other firmware had left a chip in 12-hour mode, the boot read masked hours with 0x3F and took any BCD 00-23: 12 AM (12h) was restored as 12:xx, twelve hours ahead, PM 1-3 (21h-23h) as 21:00-23:00, eight hours ahead, and PM 4-12 gave no time. On the RV3028, whose mode bit is in Control 2, a save's 24-hour hours byte also meant a different hour to the chip; on the DS3231/DS1307 the hours byte holds the mode bit, so a save already selected 24-hour mode. A new optional twelve-hour-bit descriptor property, [register mask zero], names the bit that reads set in 12-hour mode and that register's bits that always read 0: [10 02 01] on the RV3028 (Control 2 12_24; RESET, bit 0, always reads 0; Application Manual Rev 1.4, p. 24) and [02 40 00] on the DS3231 node, hours bit 6 (DS3231 19-5170 Rev 10, p. 12; DS1307 p. 8). The PCF8563, RX8130CE and RX8900 count 24 hours only. Build checks reject a malformed property: 3 bytes, a nonzero mode bit, zero bits that don't overlap it, an in-block register that is the hours register, and an out-of-block zero byte that includes bit 0, since I2C sends the MSB first and a read cut short always shows bit 0. While the bit reads set, or cannot be read cleanly, the boot takes no time and leaves the mode bit alone. Each time write selects 24-hour mode first: on the RV3028 a read-modify-write clears 12_24, refuses an unclean read, and is read back and written once more if it differs, inside the BSF bracket at an rv3028-eeprom-config descriptor; the chip converts Hours itself (p. 15). On the DS3231/DS1307 the write's own 24-hour hours byte clears bit 6. The boot log promises a later sync only for the adopted write-back target. Zephyr and MeshCore each ensure 24-hour mode before taking or writing a time, each by its own mechanism; the three are kept consistent. Link: zephyrproject-rtos/zephyr#121389 Link: meshcore-dev/MeshCore#3421 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Enforce one-hot validation for the configured mode-bit mask before approval.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
Adds RTC 12-hour-mode detection and ensures time writes select 24-hour mode.
Changes:
- Adds and validates the
twelve-hour-bitdevicetree property. - Configures RV3028 and DS3231-family RTC metadata.
- Rejects 12-hour restores and verifies 24-hour selection before writes.
| File | Summary |
|---|---|
zephcore/dts/bindings/rtc/zephcore,rtc-i2c.yaml |
Documents the new RTC property. |
zephcore/boards/nrf52840/rak4631/board.overlay |
Configures RV3028 mode metadata. |
zephcore/boards/common/rtc-i2c.dtsi |
Adds RTC mode descriptors. |
zephcore/adapters/clock/ZephyrRTCDiscover.h |
Updates RTC API contracts. |
zephcore/adapters/clock/ZephyrRTCDiscover.c |
Implements mode detection and selection; the mode mask requires one-hot validation. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+69
to
+70
| BUILD_ASSERT(DT_PROP_BY_IDX(node, twelve_hour_bit, 1) != 0, \ | ||
| "twelve-hour-bit needs a mode bit"); \ |
This was referenced Oct 7, 2026
This was referenced Oct 7, 2026
Contributor
Author
|
Replaced by #106, reworked as asked in #103 (comment): a one-time 12_24 clear at boot, as MeshCore does. Closing. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Separate from #103 (the RV3028 A0h year mark), and based on
devwithout it; the two touch different functions inZephyrRTCDiscover.c. The Zephyr and MeshCore counterparts are zephyrproject-rtos/zephyr#121389 and meshcore-dev/MeshCore#3421.Code links are permalinks:
devata2e8d5f, this PR's commit7286e50.12-hour mode. Each project ensures the chip is in 24-hour mode before it takes or writes a time. How each project does it: Zephyr's driver owns the chip and writes Control 2 = 00h at every boot, which also disables interrupts it does not handle, then takes the converted time. MeshCore clears 12_24 inside its read bracket, keeping the other bits, and takes the time only from a BSF- and mode-checked re-read. ZephCore selects 24-hour mode at each time write, keeping the other bits, with a read-back, and refuses a time read in 12-hour mode until the next sync, because a boot-time write would sit outside its BSF bracket. MeshCore and ZephCore trust a Control 2 read for a write only if its always-zero RESET bit reads 0; Zephyr's interrupt-enable read-modify-writes do not yet check it (open follow-up). A single-byte write is stored whole when acknowledged; a switchover in the middle of a byte is not covered (5.10).
The defect
ZephCore assumed 24-hour mode. If other firmware had left a chip in 12-hour mode, the boot read masked hours with
0x3Fand took any BCD 00-23. So 12 AM (12h) was restored as 12:xx, twelve hours ahead, PM 1-3 (21h-23h) as 21:00-23:00, eight hours ahead, and PM 4-12 gave no time. On the RV3028, whose mode bit is in Control 2, a save's 24-hour hours byte also meant a different hour to the chip. On the DS3231/DS1307 the hours byte holds the mode bit, so a save already selected 24-hour mode.The fix
twelve-hour-bit= [register mask zero]names the bit that reads set in 12-hour mode, and that register's bits that always read 0:[10 02 01], Control 212_24, with RESET (bit 0) always reading 0 (Application Manual Rev 1.4, p. 24). Set inrtc-i2c.dtsiand the RAK4631 overlay.[02 40 00], hours bit 6 (DS3231 19-5170 Rev 10, p. 12). This node also covers the DS1307 (p. 8) and the DS3232.RTC_H12_CHECKrejects a malformed property: 3 bytes, a nonzero mode bit, zero bits that don't overlap it, an in-block register that is the hours register, and an out-of-block zero byte that includes bit 0. I2C sends the MSB first, so a read cut short ends in 1s and always shows bit 0 set.rtc_12h(): while the bit reads set, or cannot be read cleanly, the boot takes no time and leaves the mode bit alone (12-hour mode — clock will be set on the next GPS/app/CLI sync). The boot log now promises a later sync only for the adopted write-back target.rtc_select_24h()runs before each time write. On the RV3028 it clears12_24by read-modify-write, refuses an unclean read, then reads the result back and writes it once more if it differs; at anrv3028-eeprom-configdescriptor this sits inside the BSF bracket. The chip converts its Hours register itself (02h, p. 15). On the DS3231/DS1307 the write's own 24-hour hours byte clears bit 6 and re-enters the hours, as the DS1307 sheet requires.Testing
RAK4631 + RAK12002, repeater debug builds. This PR's code is byte-identical to the fork iteration head (
c18e1f0, ondev81d98ab), where it was tested; rebased ontoa2e8d5fsince, with a clean build.12_24(Hours 21h -> 29h). The exactc18e1f0build then booted with12-hour modeand took no time. A CLItimesync wrote the time with 24-hour mode selected, and the next boot loggedRTC rtc-rv3028@52: restored 2026-10-07 00:24:37 UTC.10h=00) and stored 24-hour hours.[10 02 00],[10 02 03],[10 02 80],[10 00 01]and[04 10 00]fails the build.thinknode_m1companion (DS3231 node, generic path) builds.Known point: the binding's
rv3028-eeprom-configtext says a write cut by a power loss reads as "time not yet set". Here, a cut after the 24-hour clear and before the year-00h byte leaves the chip's previous time, which it converted to 24-hour itself, so the next boot takes it. That time is correct, so the behaviour is benign. #103 rewrites that sentence.Fork issue: ptr727#51. Iteration history and review: ptr727#52.
🤖 Generated with Claude Code