Taming inaccurate real-time clocks
An algorithm compensates for oscillator inaccuracies and adjusts to changes in the environment and aging.
By Rufus Michael Gnana and Nazmul Hoda, Ittiam Systems -- EDN, December 3, 2009
In modern multimedia systems, maintaining an RTC (real-time clock) is an important task. An RTC supports displaying the play time on a media player and the call details in a video phone. One way to provide the RTC feature is to use an RTC chip. An RTC chip uses an internal crystal oscillator as a reference and keeps track of time. Most RTC chips maintain time in seconds, minutes, hours, days, and years, and they also account for leap years. You can read the current time from certain registers in the RTC chip using an SPI (serial-peripheral interface) or a two-wire I²C (inter-integrated-circuit) interface. Some systems use an auxiliary microcontroller to perform user-interface and other housekeeping functions, and it makes good design sense to have the RTC function on this microcontroller. In this case, the microcontroller maintains a count of elapsed seconds using an external crystal as a reference. The conversion of this counter to seconds, minutes, hours, days, and years takes place in software.
A dedicated RTC chip eliminates the onus on software when using an embedded-RTC implementation. Also, the crystals in many chips are temperature-controlled and provide accuracies of 2 to 3 ppm (parts per million). On the other hand, using a microcontroller to implement an embedded RTC along with user interfaces and other housekeeping functions results in a single-chip implementation for multiple functions and results in a lower design cost (Figure 1).
However, the accuracy of the time the microcontroller maintains depends heavily on the accuracy of the crystal it uses as a reference. Typical crystals have accuracies of 20 to 45 ppm. This range translates to an unacceptable error of 1.7 to 3.9 seconds/day. One obvious way to alleviate this problem is to use a highly accurate crystal, but this approach translates to an increased design cost and hence is not viable for cost-sensitive embedded designs. Another approach uses a calibration algorithm that can implement an accurate embedded RTC in the presence of an inaccurate crystal in the system. Some embedded-RTC algorithms use a look-up table to compensate for the crystal inaccuracies. A generic approach is adopted here that adjusts the calibration factor in tune with changes in crystal, system, or temperature and aging.
Calibration
Implementing an RTC with a microcontroller typically uses the signal from a 32.768-kHz crystal oscillator, which increments a counter, such as the 16-bit CNT1 counter (Figure 2). The duration of 32,768 clock cycles corresponds to an interval of 1 second. For each second, when the system is on, CNT1 increments from 00000d to 32767d. Because the crystal is inaccurate, CNT1 overflows from 32767d to 00000d more frequently than once a second if the source clock frequency is greater than 32.768 kHz and vice versa. When CNT1 overflows from 32767d to 00000d, the microcontroller increments a second counter—CNT2, for example. CNT2 provides the count of the number of seconds elapsed since the system turned on.
To calibrate the system, the microcontroller maintaining the time connects to the RTC crystal and to an accurate 1-Hz-interrupt source. This source can be generated using a combination of another microcontroller and an accurate and more costly RTC crystal. You can justify the use of an accurate RTC crystal because you must build this additional setup in small quantities just for calibration.
The first accurate 1-Hz interrupt can occur at any instant with respect to the power-on of the microcontroller you are calibrating. The value in CNT1 on the first 1-Hz interrupt is VAL. If the RTC crystal is accurate, the value in CNT1 at any of the 1-Hz interrupts would be VAL. This situation is true because CNT1 would have overflowed and counted up to the same value each second. However, this scenario will not be the case when the RTC crystal’s frequency is inaccurate (Figure 3). For this analysis, the observation time is T seconds. On the second and (T+1)th accurate 1-Hz interrupt, the microcontroller stores the contents of CNT1. The microcontroller then calculates the calibration factor and stores it in its internal flash; if there is no way to write into the flash at runtime, the microcontroller can store the value in RAM and rely on the RTC’s battery backup. Once this action is complete, the calibration algorithm can transfer the control to the main code that runs on the microcontroller.
In the flow charts of figure 4, figure 5, and figure 6, the microcontroller increments CNT1 every 1/32,786 seconds and increments CNT2 each time CNT1 overflows from 32767d to 00000h. This counter is converted into hours, minutes, and seconds in software. The microcontroller increments CNT3 on each accurate 1-Hz interrupt. At any given point, the value in CNT3 is the number of seconds that elapsed since the first accurate 1-Hz interrupt plus one. E is the error in CNT1 per increment of CNT3. ERR1 through ERRT are the errors in CNT1 after 1 through T seconds from the occurrence of the first accurate 1-Hz interrupt. Each interrupt corresponds to an increment in CNT3. The total error in CNT1 occurring in (T+1) seconds is ETOTAL=ERRT.
|
The purpose of this setup is to determine the average error in CNT1 occurring on every 1-Hz interrupt through the increment count of CNT3. You can also determine this error as follows: Error per second (E)=value of CNT1 (when CNT3=2)–value of CNT1 (when CNT3=T+1)/T. From the value of E, you can calculate the number of seconds after which a 1-second error would occur using the following equation: CF=32,768/E, where CF is the calibration factor. So, by incrementing or decrementing the value of CNT2—that is, the seconds counter that the microcontroller maintains—every CF seconds, you should be able to achieve high accuracies. Alternatively, you can increment or decrement CNT1 by CF counts every T seconds, which can yield higher accuracies because it avoids a division-rounding error. However, the former has been adopted in this algorithm because CNT1 was a nonmodifiable hardware counter in the experimental setup.
Flow chart and procedure
Figure 4, figure 5, and figure 6 describe the flow of the algorithm, which uses the following steps:
-
On each clock cycle of the inaccurate crystal, use a hardware-counter module to increment CNT1.
-
Increment CNT2 every time CNT1 overflows from 32767d to 00000d.
-
On every accurate 1-Hz interrupt, increment CNT3.
-
On the second accurate 1-Hz interrupt, copy the contents of CNT1’s initial value into a RAM location—say, RAM1—and increment CNT3. On subsequent accurate 1-Hz interrupts, increment CNT3.
-
Once CNT3 counts to T+1, where T is the observation interval, store the new value of CNT1 into a RAM location—say, RAM2.
-
Calculate the following equations: If RAM2>RAM1, E=(RAM2–RAM1)/T; if RAM1>RAM2, E=(RAM1–RAM2)/T; and CF=32,768/E.
-
Program the value of CF into the microcontroller flash. If necessary, use a glowing LED to indicate the completion of calibration.
-
The code running on the microcontroller must now increment the contents of CNT2 by one every CF seconds if RAM1>RAM2 or decrement the contents if RAM2>RAM1.
Setup and results
The experimental setup to validate the RTC calibration algorithm comprises a microcontroller, M1, and an inaccurate 32.768-kHz RTC crystal with an accuracy of 40 ppm. Another microcontroller, M2, and a 32.768-kHz RTC crystal with an accuracy of 2 ppm generate the accurate 1-Hz source. The accurate 1-Hz clock from M2 connects to an interruptible GPIO (general-purpose-I/O) pin of M1. Observation times of powers of two ensure accurate division results when calculating the calibration factor. The calibration factor resides in M1’s flash memory. The main code on M1 now compensates for the crystal frequency’s inaccuracy based on this calibration factor, and M1 was observed to achieve an RTC accuracy of approximately 2 ppm.
This approach allows you to manufacture the setup to generate the accurate 1-Hz interrupt in small quantities and use it across multiple boards. By increasing the observation time, you can achieve high accuracies. You can also use this algorithm to ascertain the exact parts-per-million accuracy rating of a crystal. Because most microcontrollers have sector-based flash, you can store the calibration code and the calibration factor in one sector and the user code in the remaining sectors.
This algorithm can achieve accurate timekeeping in a microcontroller-based RTC implementation. You must manually erase the calibration code on the microcontroller once the calibration completes; otherwise, you must permanently program the now-redundant calibration code into the flash. However, if you need to calibrate the microcontroller again due to a substantial change in temperature or aging, the presence of the calibration code is an advantage. You must connect the calibration setup to the device and disconnect it once the LED indicates that the calibration is complete.

















Rufus Michael Gnana obtained a bachelor’s degree in electronics and communication engineering from Rashtriya Vidhyalaya College of Engineering Bangalore (Karnaraka, India) in 2007. He has been working as an engineer at Ittiam Systems Ltd since 2007. You can reach him at
Nazmul Hoda obtained a bachelor’s degree in electronics and telecommunication engineering from the University College of Engineering (Burla, Orissa, India) in 2000 and a master’s degree in electrical engineering from the Indian Institute of Science (Bangalore, India) in 2007. From 2000 to 2007, he was with the Centre for Development of Telematics (Bangalore), where he worked on wireless-communication-system design. He joined Ittiam Systems Ltd in 2007, where he works on multimedia-system design. You can reach him at 
