Linux, there are several tools are related to time, recently work encountered them, so I intend to write a few articles related to Linux time.

Today, I’d like to talk about hwclock, a tool that is probably used by those who play with the Internet of Things, because it is often used to keep the time of hardware devices, but most of the former devices are often networked, that is, they use NTP.

Also, Ubuntu 15.04 onwards uses systemd to manage time, and it comes with the timedatectl tool instead of hwclock, but it’s essentially the same thing, so I won’t go into it here.

Introduction

When a device is not networked, RTC becomes very important and the system time will rely on the energy of the coin cell battery to maintain. If the device needs to switch on and off frequently, then it will rely more on RTC to keep the device time synchronized.

Its principle is very simple, is to use the coin cell battery to drive the RTC (Real-Time Clock) chip to maintain the time when the device is powered off, so that when the device restarts, it can directly restore the time from the RTC.

First let’s take a look at the help information of hwclock.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Usage:
 hwclock [function] [option...]

Time clocks utility.

Functions:
 -r, --show           display the RTC time
     --get            display drift corrected RTC time
     --set            set the RTC according to --date
 -s, --hctosys        set the system time from the RTC
 -w, --systohc        set the RTC from the system time
     --systz          send timescale configurations to the kernel
 -a, --adjust         adjust the RTC to account for systematic drift
     --predict        predict the drifted RTC time according to --date

Options:
 -u, --utc            the RTC timescale is UTC
 -l, --localtime      the RTC timescale is Local
 -f, --rtc <file>     use an alternate file to /dev/rtc0
     --directisa      use the ISA bus instead of /dev/rtc0 access
     --date <time>    date/time input for --set and --predict
     --delay <sec>    delay used when set new RTC time
     --update-drift   update the RTC drift factor
     --noadjfile      do not use /etc/adjtime
     --adjfile <file> use an alternate file to /etc/adjtime
     --test           dry run; implies --verbose
 -v, --verbose        display more details

 -h, --help           display this help
 -V, --version        display version

Here’s how to use this command to solve two of our common problems.

Time synchronization

First of all, it is necessary to distinguish two times, one is the hardware time, that is, the time in the hardware chip such as RTC, and the other is the system time, that is, the time in the system kernel.

In order to synchronize the time, it is enough to use two of its parameters.

  1. before shutdown, write the time from the system to the RTC: hwclock --systohc.
  2. write the time from the RTC back to the system at boot time: hwclock --hctosys.

Actually, this step is done to complete the time synchronization in the offline state. The device is able to reach the point where the device time stays synchronized with the real time in most cases.

But, if the time accuracy of the device is important, then you will need to use its correction function.

Error correction

The RTC actually relies on a 32.768kHz crystal, which is a quartz crystal, however, quartz crystals are unstable and become error prone especially when the temperature changes, and this error can reach one second or more per day.

ppm of error

The above graph is from https://www.ti.com/lit/ml/slap107/slap107.pdf, you can see from the graph that the temperature is too low or too high will cause the deviation to increase, and our equipment generally cannot be placed in a constant temperature environment, so it is bound to cause errors every day.

How to correct this error? There are hardware solutions and there are software solutions.

Hardware solutions, Texas Instruments gave a program, you can directly use the temperature sensor to compensate for the accuracy of the RTC, as unfamiliar with this piece of hardware, can not say a lot, just obviously, the hardware cost will increase some.

The software solution would be much plainer, because we can assume that the environment in which this device is located is constant and the deviation of the hardware time from the system time is systematic, to put it simply, it is fixed every other period, and the deviation of the time between them is actually the same. So, we use a software engineering perspective to calibrate at low cost, that is, the calibration function of hwclock.

It will use a file adjfile to record the status of the calibration, but first it is necessary to explain the format of adjfile, which defaults to /etc/adjtime, and its content contains 3 lines of text.

  • The first line, containing three values.
    • System time offset per day (in seconds)
    • Last adjustment time (Unix timestamp)
    • Calibration status
  • Second line: last calibration time (Unix timestamp)
  • Third line: “UTC” or “LOCAL” (usually only use UTC, don’t use LOCAL to give yourself a hard time)

The usage of the calibration is also very simple.

But before you start, first you need to make sure that the Linux kernel does not have automatic synchronization of system time to hardware time activated, otherwise it will be automatically synchronized by NTP’s 11-minute mode. To do this, run adjtimex --print or adjtimex, look at its status value and see if there is UNSYNC, if there is, it is not synchronized, or you need to calculate status & 0x40 yourself, if 1 means not synchronized.

  1. disable the ntp background process (if auto-sync is active) and disable it from starting with the system.
  2. manually synchronize the system time once.
  3. synchronize the system time to the RTC: hwclock --systohc, when the timestamp in /etc/adjtime will be updated, but at an offset of 0;
  4. shut down and wait for at least one day.
  5. turn on the computer, then immediately synchronize the system time manually once, then let hwclock synchronize to the RTC while automatically calculating the offset hwclock --systohc --update-drift.
  6. check and confirm the offset in /etc/adjtime.
  7. start and enable the ntp background process (if auto-sync is active)

Ref

  1. Implementing a Temperature Compensated RTC, PDF
  2. hwclock - time clocks utility
  3. adjtime - information about hardware clock setting and drift factor
  4. torvalds/linux:include/uapi/linux/timex.h