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 onwards the system clock is used to track time. During shutdown, the system time is used to set the hardware clock as a way to ‘save’ the time between reboots.

Traditionally, on power off, the system clock will get stored into the hardware clock by a shutdown script. Our images use systemd-timedated and the timedatectl command since V2.1. 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.

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

Using the timedatectl to set the date or time makes sure the new system clock is synchronized with the hardware clock (RTC) immediately:

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

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

Note: Our image currently use the standalone service ntpd to synchronize time with network time servers. Currently, the systemd implementation of the NTP service called systemd-timesyncd is not part of our image. Hence the NTP related commands of timedatectl do not work.

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 .

  1. hwclock -r
    (Show hardware clock time)
  2. hwclock -w
    (Set hardware clock to system time)
  3. 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:

[    9.614096] rtc-ds1307 0-0068: rtc core: registered m41t00 as rtc0
[    9.624583] snvs_rtc snvs_rtc.0: rtc core: registered snvs_rtc as rtc1
....
[   10.750452] rtc-ds1307 0-0068: setting system clock to 2014-03-12 10:51:11 UTC (1394621471)

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.