2

folks!

I have a single board computer (HardKernel Odroid C2) that has no builtin RTC and need an external time source on each system boot. While I have a local NTP server, I also need RTC just in case of rare power fail, that will force NTP server to reboot and loose its time as well. As time is vital for the system functioning, I built RTC using PCF8563 I2C RTC. The problem is that it needs special kernel modules to make a system usable RTC and I have to load this modules during boot process. So the system starts with incorrect time, loads modules needed and then sets the system time from RTC with a help of /etc/rc.local:

#Set system datetime from RTC
logger "Starting system clock synchronization with RTC"
if [ -e /dev/rtc ]; then
    /sbin/hwclock --hctosys
fi
logger "System clock synchronized to RTC"

The problem is that systemd seems to treat the period in between early boot process and clock setup as kind of "incorrect" writing no logs. I see no logs at all after system goes down and system clock setup:

Jan  5 23:20:39 tank systemd-journald[206]: Journal stopped
Jan  5 23:20:55 tank root[394]: System clock synchronized to RTC <- this is the second logger message
Jan  5 23:20:55 tank systemd[1]: Started /etc/rc.local Compatibility.
...
Jan  5 23:21:07 tank chronyd[384]: Forward time jump detected!

Synchronizing system clock from RTC by running hwhlock --hctosys from /etc/rc.local is the suggested method by the HardKernel. But that seems totally wrong as system clearly work for some period with predefined time before it runs rc.local. So, is there are any ways to set system clock from RTC early?

4
  • Why ask here? No mention of OS & release is provided thus I see no connection with this site.
    – guiverc
    Jan 5 at 22:37
  • Because it is Ubuntu. No mention of OS just because askubuntu is about... Ubuntu and it is supposed to be Ubuntu in that case, right?
    – e-pirate
    Jan 5 at 22:49
  • You might try installing fake-hwclock and then adding your rtc read to the end of that startup mechanism.
    – meuh
    Jan 6 at 16:32
  • The release details provide software stack details.. Given some supported releases have 10 years of support (eg. Ubuntu Core products), software stacks can vary quite considerably.
    – guiverc
    Jan 6 at 21:07
2

I spent 2 days and finally found the exact solution. The problem is the rc.local is executed way to late after system boots up. This leads to several problems: 1) part (including valuable kernel and early system start up) or all logs dropped dew to time jump, that makes journal discard all logs prior new date 2) if dew to some reason system clock will be updated after system logger (syslogd or syslog-ng in my case) is started, there will be no logs after last shut down at all. While system is still functional, this is a major failure as there is no way to investigate anything on a running system. After some exhausting experimenting with no logs, I found the combination (pretty obvious, actually) to set system clock at the most yearly time possible:

/lib/systemd/system/hwrtc.service

[Unit]
Description=Synchronise System clock to hardware RTC
DefaultDependencies=no
After=systemd-modules-load.service
Before=systemd-journald.service time-sync.target sysinit.target shutdown.target
Conflicts=shutdown.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/hwclock --hctosys --utc --noadjfile
RestrictRealtime=yes

[Install]
WantedBy=sysinit.target

And enable this service. This will make system start hwclock right after mandatory modules are loaded and before journal is started, so all logs will be marked with actual time restored from RTC saving all messages including the very first kernel ones.

5
  • (1) You added After=systemd-modules.load.service. Does this approach expect a file in /etc/modules-load.d to list the relevant kernel modules? (2) man systemd.unit suggests that locally-installed stuff should be in /etc/systemd/system rather than under /lib. (3) Pis come with a /lib/systemd/system/fake-hwclock.service which this races with; I'd list that in After= (or disable it). (4) I'd run before systemd-fsck-root.service to avoid the initial fsck complaining about the last mount time.
    – Scott Lamb
    Jul 13 at 17:43
  • (5) How are you telling the kernel about /dev/rtc0? Are you doing something like dt_overlay in /boot/config.txt or running a echo .... > /sys/class/i2c-adapter/i2c-1/new_device somewhere?
    – Scott Lamb
    Jul 13 at 17:44
  • @ScottLamb did you manage to run this before fsck? as far as I can tell modules in /etc/modules (i2c-dev and rtc-ds1307 to make my rtc work) are loaded after that so just calling hwclock before that won't be enough... any idea to make those modules available early? a ramdisk would be ideal but that seems cumbersome to setup on a rpi
    – filippo
    Jul 25 at 4:21
  • @filippo I'm just explicitly running modprobe myself. github.com/scottlamb/moonfire-nvr/wiki/…
    – Scott Lamb
    Jul 29 at 3:44
  • @ScottLamb thanks, will give this a try. Nice write-up, especially the part about why other tutorials are wrong... unfortunately there's plenty of subpar guides in the raspberry world and one often have to figure out how to do things the proper way on his own
    – filippo
    Jul 29 at 7:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.