Recently I was wondering if a Raspberry Pi would be able to run an accurate clock and provide a stable NTP service.
A virtual machine can’t do it, because its system clock has a changing drift factor. The clock compensation technique built into NTP was never designed to handle anything but a static drift factor. This is unfortunate because NTP is a light-wight protocol, so using physical hardware for it may sound wasteful. The Raspberry Pi is physical hardware with a very small footprint. So, how accurately can the Raspberry Pi keep time?
Let’s start with some background before we answer the question.
Clocks in Linux
Two clocks are important in Linux: a ‘hardware clock’, also known as RTC (Real Time Clock), CMOS or BIOS clock. This is the battery backed clock on the motherboard that keeps time even when the machine is shut down. The second clock is called the ‘system clock’, maintained by the operating system, Linux in our case. At boot time, the hardware clock is used to set the system clock and from that point onwards the system clock is used to track time. At shutdown, the system time is used to set the hardware clock as a way to ‘save’ the time between reboots. Linux uses a clocksource to maintain time, several of which exist, mostly depending on the available hardware.
Just like virtual hardware, the Raspberry Pi has no hardware clock. But it is fairly simple to add a hardware clock using the GPIO ports. In a previous blog post, I explained how to set this up.
Clock accuracy is defined in terms of ppm (parts per million) and it gives a way of comparing accuracies. The hardware clock I use, a RasClock, is said to lose 3 ppm (parts per million). So, 3 of each 1 million seconds may be wrong. This means:
3/10e6 x 24 x 60 x 60 = 0.2592 sec/day may be wrong.
One year after setting the hardware clock, it will be 95 seconds off at max.
Note: an atomic clock’s accuracy is something in the order of 0.0000001 ppm😉
How Linux keeps time
Because the hardware clock is used only at system start, it doesn’t help in keeping time while the system runs. The OS needs a decent clocksource to be able to keep time. Think of the clocksource as a counter maintained by the kernel. The purpose of the clocksource is to provide a timeline for the system that tells you where you are in time. For example issuing the command ‘date’ on a Linux system will eventually read the clocksource to determine exactly what time it is.
On x86 and/or amd64 hardware, common clocksources are TSC (Time Stamp Counter), acpi_pm and since about 2005 HPET (High Precision Event Timer).
cat /sys/devices/system/clocksource/clocksource0/current_clocksource cat /sys/devices/system/clocksource/clocksource0/available_clocksource
The first command shows the current clocksource, the second all available ones.
Rasberry Pi’s clocksource
The Raspberry Pi does not ship with a TSC nor HPET counter to use as clocksource. Instead it relies on the STC that Raspbian presents as a clocksource. Based on the source code, “STC: a free running counter that increments at the rate of 1MHz”. This means it increments every microsecond.
How accurate is this STC?
Now that I have a hardware clock hooked to the Raspberry Pi, I can compare the STC clocksource (ie the system clock) to the hardware clock. First I made sure nothing is adjusting the clocksource already, or else you will not get accurate results. To double check:
Make sure these vars have their default values:
And restart afterwards:
These values are used to adjust the system clock. A value of FREQ=65536 speeds up the system clock by about 1 ppm, or .0864 sec/day. FREQ=6553600 and TICK=1 are equal and both speed up the system clock by about 100ppm, or 8.64 sec/day. Since we want to find out the precision of the Raspberry Pi’s system clock, we should not adjust anything. The system should not be doing other tasks during the test, other than normal OS operations.
First I synced the hardware clock with the system clock and logged the point in time that I did this:
hwclock --hctosys --utc; date -u
Read both the hardware clock and the system clock to verify:
hwclock -r; date -u
The two were equal in my test. To compare the hardware clock with the system clock in a more detail, a tool called ‘adjtimex’ exists. I used it with the –compare flag to run the test, like this:
adjtimex --compare=1 --utc
Warning: when you install ‘adjtimex’, it generates adjustment values in ‘/etc/default/adjtimex’. Make sure to reset them, like I did above or else you will get incorrect results.
Example output of the above command:
--- current --- -- suggested -- cmos time system-cmos error_ppm tick freq tick freq 1367834856 -0.002202
Since both clocks just synced, there shouldn’t be much of a difference. I used the following command to log these values during a few days:
while :; do \ date -u +'# Generated at: %Y-%m-%d %H:%M:%S UTC %s %N'\ --date '+1 second'| tee -a time.log 2>&1 \ && adjtimex --compare=1 --utc \ | grep -v current | grep -v cmos |\ tee -a time.log 2>&1 \ && sleep 1;\ done
This command enters an infinite loop and writes results to a logfile. Each loop takes about 2 seconds, so effectively this measures every 2 seconds the difference between the hardware clock and the system clock.
Afterwards, using some vim magic, I combined both logfiles, created a CSV from it and did most of the test analysis in Libre Office. Depending on the period you compare, you may want to filter out some records. Say you want a 1 minute interval in the rest results, instead of 2 seconds. I’ve found awk to be very useful at this:
awk 'NR == 1 || NR % 30 == 0' file.csv > file-1min-interval.csv
I’ve run the test command on two equally equipped and setup Raspberry Pi’s.
You can see the drift is fairly static and predictable. I’ve measured every 2 seconds during roughly 59 hours.
The above chart shows the first hour in more detail.
There is a small difference between the two Raspberry Pi’s I tested, probably due to the fact the STC clocksource is entirely done in software (it does not use a hardware crystal of some kind). After 59 hours the difference is 0.242016 seconds in my test. More testing is needed to find out if this difference is consistent. It might even be caused by something else. Although I’m not sure, I wouldn’t worry too much about it
Total deviation: 8.763317 sec
Accuracy: 8.763317 / ( 59 x 60 x 60 ) x 10e6 = 41.259ppm
Total deviation: 8.521301 sec
Accuracy: 8.521301 / ( 59 x 60 x 60 ) x 10e6 = 40.119ppm
Average accuracy: ( 41.259 + 40.119 ) /2 = 40.689ppm
Deviation in 24h: ( 40.689 / 10e6 ) x 24 x 60 x 60 = ~3.52 sec. So, without adjustments or syncs with other sources, it will drift this many seconds in 24 hours.
While the STC clocksource in Raspbian is not as accurate as a hardware clock, it does a great job in keeping time. The timedrift is linear and it has an accuracy of ~40ppm. It means the Raspberry Pi is able to keep time pretty well just on its own. This a requirement to build a solid NTP service and it is exactly what a VM cannot do. Therefore the Raspberry Pi is an interesting device to consider when planning your NTP service.
We now know what the Raspberry Pi does when it is not synced with other sources. Of course we’ll setup a system where it does sync to make sure it will drift away as little as possible. In a follow-up post we’ll continue from here in building a NTP service on the Raspberry Pi.