RTC

Real Time Clock (RTC), it’s a battery-powered clock on your computer’s motherboard. This clock keeps time even when the system is powered off. Linux, like other operating systems, reads this clock during boot and uses it to set the system clock.

The system clock is part of the Linux kernel and the system time is incremented by a timer interrupt. The system time is basically the number of seconds elapsed since the 1st Sepuary 1970. The system clock does not have its own power source, in other words, if the system is powered off it will stop counting and reset. This means that the system time is reverted back to 1970 once the device is powered on again.

The RTC, or hardware clock, is a hardware device running with a dedicated power supply as a battery or a capacitor. It runs even when the Linux system is unplugged or powered off.  Usually, this device is connected to the SoC through the I2C or SPI bus

RTC time can be stored either in UTC or in local time. It is recommended to store the RTC time in UT to make NTP synchronization easier. The NTP synchronization with RTC in non-UTC is not effective.

Kernel Configuration

To make Linux sets the system clock from the hardware clock when booting, we need to configure the Linux kernel

config RTC_HCTOSYS_DEVICE
        string "RTC used to set the system time"
        depends on RTC_HCTOSYS
        default "rtc0"
        help
          The RTC device that will be used to (re)initialize the system
          clock, usually rtc0. Initialization is done when the system
          starts up, and when it resumes from a low power state. This
          device should record time in UTC, since the kernel won't do
          timezone correction.

          This clock should be battery-backed, so that it reads the correct
          time when the system boots from a power-off state. Otherwise, your
          system will need an external clock source (like an NTP server).

          If the clock you specify here is not battery backed, it may still
          be useful to reinitialize system time when resuming from system
          sleep states. Do not specify an RTC here unless it stays powered
          during all this system's supported sleep states.
config RTC_SYSTOHC_DEVICE
        string "RTC used to synchronize NTP adjustment"
        depends on RTC_SYSTOHC
        default RTC_HCTOSYS_DEVICE if RTC_HCTOSYS
        default "rtc0"
        help
          The RTC device used for NTP synchronization. The main difference
between RTC_HCTOSYS_DEVICE and RTC_SYSTOHC_DEVICE is that this
          one can sleep when setting time, because it runs in the workqueue
          context.

Once Linux boots, we can check the log message 

dmesg | grep rtc

#result:
[    2.255643] rtc-pcf2731 1-0068: setting system clock to 2024-09-06T13:17:11- UTC

To get current hardware clock time

hwclock --show

#result:
2024-09-06 15:03:18.123456+02:00

To set the system time

hwclock --set --date="YYYY-MM-DD HH:MM:SS"

To set hardware clock from system time in utc

hwclock –systohc --utc

History of hardware clock changes

Each time the hardware clock is changed by hwclock command, the /etc/adjtime is updated to keep history change.

The adjtime file format is

<The systematic drift rate in seconds per day> <Number of seconds since 1969 UTC> <Zero (for compatibility reasons)>
<Last calibration time in seconds since 1969 UTC>
<"UTC" or "LOCAL">

# example:
0.000000 1720036215 0.000000
1720036215
UTC

The systemd-timedated service

The systemd-timedated service is a system service that may be used as a mechanism to change the system clock and timezone, as well as to enable/disable network time synchronization. systemd-timedated is automatically activated on request and terminates itself when it is unused.

The timedatectl is a command line client to this service.

The systemd-timedated service set the following parameters:

  • The system time
  • The system timezone
  • A boolean controlling whether the system RTC is in local or UTC timezone
  • Whether the time synchronization service is enabled/started or disabled/stopped, see next section.

The systemd-timesyncd service

This systemd-timesyncd is a service to synchronize the system clock across the network. It implements an SNTP client. This service queries time from one remote NTP server and synchronize the local system clock to it. 

This service stores the current clock to file system every time a new NTP sync has been acquired (and every 60 seconds), and uses this to possibly correct the system clock early at bootup, in order to accommodate for systems that lack an RTC, and make sure that time monotonically progresses on these systems, even if it is not always correct.

The systemd-timesyncd does not provide a NTP server service at the opposite of Chrony.

Note:

* The service writes to a local file /var/lib/systemd/timesync/clock with every synchronization and every 60 seconds. This location is hard-coded and cannot be changed.
* This writing may be problematic for running off read-only root partition or trying to minimize writes to an SD card.
* The number of writes can be minimized with a configuration like PollIntervalMinSec=1d and SaveIntervalSec=infinity.

Service configuration

The systemd-timesyncd service can be configurated using the file 

/etc/systemd/timesyncd.conf or /etc/systemd/timesyncd.conf.d/*.conf. The file is format as following

[Time]
NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
FallbackNTP=0.pool.ntp.org 1.pool.ntp.org 0.fr.pool.ntp.org

Verification of service configuration

timedatectl show-timesync --all


# result:


LinkNTPServers=
SystemNTPServers=
FallbackNTPServers=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org
ServerName=0.arch.pool.ntp.org
ServerAddress=103.47.76.177
RootDistanceMaxUSec=5s
PollIntervalMinUSec=32s
PollIntervalMaxUSec=34min 8s
PollIntervalUSec=1min 4s
NTPMessage={ Leap=0, Version=4, Mode=4, Stratum=2, Precision=-21, RootDelay=177.398ms, RootDispersion=142.196ms, Reference=C342F10A, OriginateTimestamp=Mon 2018-07-16 13:53:43 +08, ReceiveTimestamp=Mon 2018-07-16 13:53:43 +08, TransmitTimestamp=Mon 2018-07-16 13:53:43 +08, DestinationTimestamp=Mon 2018-07-16 13:53:43 +08, Ignored=no PacketCount=1, Jitter=0 }
Frequency=22520548

The timedatectl command

To set RTC in UTC format

timedatectl set-local-rtc 1

To set system date time

timedatectl set-time YYYY-MM-DD HH:MM:SS

 Deactivate NTP Synchronization

# to activate the ntp synchronization 
timedatectl set-ntp true

# to deactivate the ntp synchronization 

timedatectl set-ntp false

To get the available system timezones

timedatectl list-timezones | column

To set the system timezone

timedatectl set-timezone <TIMEZONE>

where <TIMEZONE> is one of the timezone list

To get current configuration

timedatectl 
	       Local time: Fri 2024-09-06 15:05:01 CEST
	Universal time: Fri 2024-09-06 15:05:01 UTC
	        RTC time: Fri 2024-09-06 15:05:26
	      Time zone: Europe/Paris (CEST, +0200)
System clock synchronized: no
	      NTP service: inactive
	RTC in local TZ: no
timedatectl 


       Server: 103.47.76.177 (0.arch.pool.ntp.org)
Poll interval: 2min 8s (min: 32s; max 34min 8s)
         Leap: normal
      Version: 4
      Stratum: 2
    Reference: C342F10A
    Precision: 1us (-21)
Root distance: 231.856ms (max: 5s)
       Offset: -19.428ms
        Delay: 36.717ms
       Jitter: 7.343ms
 Packet count: 2
    Frequency: +267.747ppm

The timedatectl command cannot be used to set the hardware clock from the system clock. it can only set the system time and date. The RTC date time can be set from the as system date time by using the hwclock command like hwclock –systohc –utc.

To check systemd-syncd status

timedatectl timesync-status

       Server: 103.47.76.177 (0.arch.pool.ntp.org)
Poll interval: 2min 8s (min: 32s; max 34min 8s)
         Leap: normal
      Version: 4
      Stratum: 2
    Reference: C342F10A
    Precision: 1us (-21)
Root distance: 231.856ms (max: 5s)
       Offset: -19.428ms
        Delay: 36.717ms
       Jitter: 7.343ms
 Packet count: 2
    Frequency: +267.747ppm

View service logs

journalctl -u systemd-timesyncd --no-hostname --since "1 day ago"


Sep 16 15:14:20 systemd[1]: Stopping Network Time Synchronization...
Sep 16 15:14:20 systemd[1]: systemd-timesyncd.service: Deactivated successfully.
Sep 16 15:14:20 systemd[1]: Stopped Network Time Synchronization.
Sep 16 15:14:20 systemd[1]: Starting Network Time Synchronization...
Sep 16 15:14:20 systemd[1]: Started Network Time Synchronization.
Sep 16 15:14:20 systemd-timesyncd[1023]: Contacted time server 178.215.228.24:123 (0.arch.pool.ntp.org).
Sep 16 15:14:20 systemd-timesyncd[1023]: Initial clock synchronization to Fri 2024-01-19 15:14:20.393865 CET.