Search by Tags

How to use the Real Time Clock in Linux

 
Applicable for

Compare with Revision




Subscribe for this article updates

Purpose

This article describes how to use a Real Time Clock (RTC) on Embedded Linux.

Real Time Clock in Linux

Two clocks are important in Linux: a ‘hardware clock’, also known as RTC, CMOS or BIOS clock. This is the battery backed clock that keeps time even when the system is shut down. The second clock is called the ‘system clock’ or 'kernel clock' and is maintained by the operating system. At boot time, the hardware clock is read and used to set the system clock. From that point onward the system clock is used to track time.

Our images use systemd-timedated and the timedatectl command since V2.1 and sytemd-timesyncd since V2.4 to synchronize time with a remote Network Time Protocol (NTP) server. When using the timedatectl utility, the time will get stored into the hardware clock immediately when setting a new date or time. The system clock will not get stored into the hardware clock on shutdown.

Alternatively, there is the tool hwclock for accessing one of the hardware clocks directly. You can display the current time, set a hardware clock to a specified time, set a hardware clock to the system time, and set the system time from the hardware clock. Traditionally, on power off, the system clock will get stored into the hardware clock by a shutdown script.

Note: To let one of the RTCs retain the time even when no power is applied to the system, put a backup battery in the respective holder on the carrier board.

Using the timedatectl Command

The timedatectl allows to display the current time, both, the system clock and the hardware clock. Furthermore, it also displays the currently configured time zone of the system (which is UTC by default in our images).

# timedatectl 
      Local time: Mon 2014-05-26 11:29:40 UTC
  Universal time: Mon 2014-05-26 11:29:40 UTC
        RTC time: Mon 2014-05-26 11:29:39
        Timezone: Universal (UTC, +0000)
     NTP enabled: n/a
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a

If the RTC reports an invalid time, timedatectl reports an error:

# timedatectl status
Failed to query server: Invalid argument

In this case the RTC needs to be rewritten.

If internet connection is provided, the systemd-timesyncd service will automatically synchronize the local system clock with a remote Network Time Protocol server. systemd-timedated will make sure the new system clock is synchronized with the hardware clock (RTC) immediately.

If no internet connection is provided, timedatectl can be used to set the date or time. systemd-timedated will make sure the new system clock is synchronized with the hardware clock (RTC) immediately:

timedatectl set-ntp false
timedatectl set-time "2015-01-31 11:13:54"

For more information refer to the timedatectl manual page at freedesktop.org.

Using the date and hwclock Command

Use these two commands to manipulate the system clock and hardware clock directly.

From http://busybox.net/downloads/BusyBox.html#hwclock .

  • hwclock -r

    (Show hardware clock time)

  • hwclock -w

    (Set hardware clock to system time)

  • hwclock -s

    (Set system time from hardware clock)

-f FILE can be used to specify a particular RTC device (e.g. /dev/rtc2).

To set system time, use the date command:

date -s "2013-11-19 15:11:40"

Setting the system time using the date command does not automatically synchronize the RTCs. Use the hwclock command after entering the date command to synchronize an RTC with the updated system time:

hwclock -w

Using the alarm feature to wake up

When in sleep mode, a RTC can be used to wake the system up later. Not all RTC support this wake up mode, check the availability of the wakealarm file.

To enable wake in 20 seconds from now, one can use this statement:

echo +20 > /sys/class/rtc/rtc2/wakealarm

Available RTCs on Tegra

As can be seen from the kernel boot log there are actually 3 RTC drivers active on Tegra based modules:

[    4.483598] using rtc device, m41t00, for alarms
[    4.488204] rtc-ds1307 0-0068: rtc core: registered m41t00 as rtc0
[    4.500130] tegra_rtc tegra_rtc: rtc core: registered tegra_rtc as rtc1
[    4.509545] tegra_rtc tegra_rtc: Tegra internal Real Time Clock
[    4.519127] tps6586x-rtc tps6586x-rtc.0: rtc core: registered tps6586x-rtc as rtc2
...
[    5.440682] rtc-ds1307 0-0068: setting system clock to 2012-09-28 00:38:03 UTC (1348792683)

The first one is the ultra low-power RTC available on the carrier board. The second one is Tegra SoC internal and won't keep the time across power-cycles in our design. The third one is PMIC integrated usually drawing much more current that the first dedicated one.

Available RTCs on Vybrid

As can be seen from the kernel boot log there are actually 2 RTC drivers active on Vybrid based modules:

[    1.339243] rtc-ds1307 0-0068: rtc core: registered m41t0 as rtc0
[    1.353708] snvs_rtc 400a7000.snvs:snvs-rtc-lp: rtc core: registered 400a7000.snvs:snvs- as rtc1
.... 
[    2.562813] rtc-ds1307 0-0068: setting system clock to 2015-01-31 11:20:53 UTC (1422703253)

The first one is the ultra low-power RTC available on the carrier board. The second one is Vybrid SoC internal.

Available RTCs on i.MX6

As can be seen from the kernel boot log there are 2 RTC drivers active on i.MX6 based modules:

[    1.798495] rtc-ds1307 2-0068: rtc core: registered m41t00 as rtc0
[    1.818131] snvs_rtc 20cc034.snvs-rtc-lp: rtc core: registered 20cc034.snvs-rtc-lp as rtc1

The first one is the ultra low-power RTC available on the carrier board. The second one is iMX6 SoC internal.