raspberrypi / linux

Kernel source tree for Raspberry Pi-provided kernel builds. Issues unrelated to the linux kernel should be posted on the community forum at https://forums.raspberrypi.com/
Other
10.93k stars 4.92k forks source link

i2c-rtc overlay should also enable `hwclock --hctosys` calls #3860

Open maresmar opened 3 years ago

maresmar commented 3 years ago

Is this the right place for my bug report? I hope so :-) The dtoverlay=i2c-rtc overlay is located in this repository. But I don't have a clue how does it work inside...

Describe the bug The overlay correctly enables RTC support but doesn't use RTC as a system time source.

To reproduce

  1. Add dtoverlay=i2c-rtc,ds3231 to /boot/config.txt
  2. Reboot
  3. Save time to RTC - sudo hwclock -w
  4. Disable NTP - sudo timedatectl set-ntp false
  5. Power off RaspberryPi
  6. Wait a few minutes (optimal)
  7. Power on RaspberryPi

Expected behaviour The system should use the correct time from RTC.

Actual behaviour The system uses the wrong time from the last shutdown (using fake-hwclock).

Some solutions The most of tutorials solve it by commenting a few lines in /lib/udev/hwclock-set (these changes enable hwclock --hctosys call in systemd environment). This is a bad solution as that file is overridden with standard package updates.

There is already an (old) bug report in Debian with a nice analysis of the problem. One of later comment recommend nice solutions using systemd service:

[Unit]
Description=sync system clock with default rtc
After=sysinit.target

[Service]
Type=oneshot
ExecStart=/sbin/hwclock --hctosys

[Install]
WantedBy=basic.target

This works fine for me. Could override include / enable this service for everyone?

System

Raspberry Pi reference 2019-06-20
Generated using pi-gen, https://github.com/RPi-Distro/pi-gen, 150e25c4f8123a4c9c63e8dca1b4737fa6c1135c, stage2
Sep  2 2020 21:16:35 
Copyright (c) 2012 Broadcom
version 4439d2aaa6c376a2d1ef4402f142e1cf4de37c43 (clean) (release) (start_x)
Linux 5.4.51-v7+ #1333 SMP Mon Aug 10 16:45:19 BST 2020 armv7l GNU/Linux

Logs

$ journalctl | grep -C 2 rtc
Feb 14 11:12:02 systemd-udevd[146]: Using default interface naming scheme 'v240'.
Feb 14 11:12:02 systemd[1]: Started File System Check on /dev/disk/by-partuuid/ea0c2131-01.
Feb 14 11:12:03 kernel: rtc-ds1307 1-0068: registered as rtc0
Feb 14 11:12:03 systemd[1]: Listening on Load/Save RF Kill Switch Status /dev/rfkill Watch.
Feb 14 11:12:03 systemd[1]: Condition check resulted in FUSE Control File System being skipped.

Additional context

pelwell commented 3 years ago

Overlays don't have the ability to cause arbitrary commands to be run, but you could use modify the systemd service you refer to make it conditional on something in /proc/device-tree created by the overlay, or that /sys/class/rtc is not empty - something like:

[Unit]
Description=sync system clock with default rtc
After=sysinit.target
ConditionDirectoryNotEmpty=/sys/class/rtc

[Service]
Type=oneshot
ExecStart=/sbin/hwclock --hctosys

[Install]
WantedBy=basic.target

If that works then we could add it to the standard images.

maresmar commented 3 years ago

It works great for me. I modified my service file and it still works as I would expect. Please note I had that service already enabled (using systemctl enable my-hwclock-service). I don't know how it would behave out of the box.

Sorry for the delay. I didn't find a time to try it earlier.

MichaIng commented 3 years ago

I guess it would work correctly if fake-hwclock did not override it. Try to purge it: apt purge fake-hwclock

Usually it is not required to install a custom service as systemd applies the RTC time automatically, at least it actively sets a mask for hwclock.service, even on Debian Bullseye where systemd-timesyncd has become an own package. fake-hwclock likely overrides it, as it does not have any conditionals:

# systemctl cat fake-hwclock
# /lib/systemd/system/fake-hwclock.service
[Unit]
Description=Restore / save the current clock
Documentation=man:fake-hwclock(8)
DefaultDependencies=no
Before=sysinit.target shutdown.target
Conflicts=shutdown.target

[Service]
EnvironmentFile=-/etc/default/fake-hwclock
ExecStart=/sbin/fake-hwclock load $FORCE
ExecStop=/sbin/fake-hwclock save
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=sysinit.target

If you want it as fallback, you'd need to add a conditional, e.g.:

mkdir -p /etc/systemd/system/fake-hwclock.service.d
echo -e '[Unit]\nConditionDirectoryNotEmpty=!/sys/class/rtc'

But probably my assumption is wrong when the RTC is loaded as kernel module and becomes ready a bit later, or if because of this the timing of systemd/udev/whatever does not work out.


Ah lol, what a coincidence: https://github.com/raspberrypi/linux/commit/f877159aeda241935e07833ba9b7234836c99ed7 Probably that was the reason for the missing automatic sync and this issue is therefore solved by that commit?

pelwell commented 3 years ago

Exactly - the sync should now be automatic in both directions.