Synchronization Issues Between System Time and RTC in Embedded Linux

Synchronization Issues Between System Time and RTC in Embedded Linux

Hello everyone, I am the Intelligence Guy~

Today, I will mainly share with you the synchronization issues between the Linux system time and the RTC.

In a Linux system, the hardware real-time clock (RTC) acts like a “mechanical watch” that never loses power; it can persistently record time even when the device is turned off. However, the system time (the software clock maintained by the kernel) gradually drifts over long periods due to factors such as crystal oscillator errors and temperature changes, leading to time inaccuracies.

So how can we ensure that the system time always uses the RTC as a reference and even prioritizes the accuracy of the RTC?

1. Default Mechanism: How Does Linux Synchronize Time with RTC?

1. “One-time Synchronization” at Startup and Shutdown

At startup: The system reads the time from the RTC using the <span><span>hwclock --hctosys</span></span> command to initialize the system time.At shutdown: The system writes the current system time back to the RTC using <span><span>hwclock --systohc</span></span>.

This mechanism only ensures the accuracy of the boot time, but long-running servers or embedded devices (such as industrial computers and routers) may gradually deviate from the RTC due to system clock drift.

2. Risk of Time Deviation Without Intervention

Example: A server running continuously for 3 months with a system clock drifting 0.1 seconds per second will accumulate an error of about 43 minutes.Consequences: Confused log timestamps, certificate validation failures, and misfired scheduled tasks, etc.

2. systemd’s <span><span>rtcsync</span></span>: Keeping RTC and System Time Synchronized Long-term

1. <span><span>rtcsync</span></span>‘s Role

<span><span>rtcsync</span></span> is one of the core functions of the <span><span>systemd-timesyncd</span></span> service. Once enabled, the system will periodically write the current time to the RTC (by default, it attempts to synchronize every minute), rather than only synchronizing at shutdown. This addresses the issue of time deviation between the system time and RTC during long-term operation, but it synchronizes the system time to the RTC, not the other way around.

To prevent the RTC time from becoming outdated due to abnormal shutdowns, it can immediately persist the accurate time to the RTC when NTP is functioning normally, avoiding RTC time failure due to abnormal shutdowns.

3. Configuration Method

  1. Enable<span><span>rtcsync</span></span>:
    sudo nano /etc/systemd/timesyncd.conf
    

    Modify to:

    [Time]
    RTCSync=yes
    
  2. Restart the service:
    sudo systemctl restart systemd-timesyncd
    
  3. Verify synchronization:
    timedatectl show-timesync | grep RTCTimeUSec  # Check the most recent RTC synchronization time
    hwclock -r &amp;&amp; date                            # Compare RTC and system time
    

3. Let RTC Update System Time

If the RTC itself has high precision (such as an industrial-grade RTC with temperature-compensated crystal oscillators), the system can be configured to prefer the RTC as the time source, or even completely rely on the RTC for time calibration.

Adjusting RTC Synchronization Frequency

Applicable Scenarios: Need high-frequency synchronization of RTC (e.g., second-level calibration).Achieved through systemd timers:

  1. Create service file<span><span>/etc/systemd/system/rtc-sync.service</span></span>:
    [Unit]
    Description=Sync system time from RTC
    
    [Service]
    Type=oneshot
    ExecStart=/sbin/hwclock --hctosys
    
  2. Create timer<span><span>/etc/systemd/system/rtc-sync.timer</span></span>:
    [Unit]
    Description=Sync RTC every 30 seconds
    
    [Timer]
    OnBootSec=1min
    OnUnitActiveSec=30s
    AccuracySec=1ms
    
    [Install]
    WantedBy=timers.target
    
  3. Enable timer:
    sudo systemctl enable --now rtc-sync.timer
    

4. adjtimex Time Correction

<span><span>adjtimex</span></span> is a Linux command-line tool used to adjust the hardware parameters of the kernel clock, thereby controlling the frequency and offset of the system time. Its core function is to fine-tune the oscillation frequency of the system clock, allowing the system time to gradually approach the reference time source (such as hardware RTC or NTP server), avoiding time jumps caused by directly modifying the time value.

adjtimex originates from the Unix <span><span>ntp_adjtime</span></span> system call and is an important interface for time management in the Linux kernel.

1. Causes of Clock Drift

The system time is driven by a software clock maintained by the kernel, with its reference being the oscillation frequency of the hardware clock source (usually 11 MHz or 25 MHz). Due to factors such as temperature and voltage, the actual frequency may have slight deviations from the nominal value (e.g., ±100 ppm), causing the system time to gradually diverge from the real time.

2. <span><span>adjtimex</span></span>‘s Correction Logic

Frequency Adjustment: By modifying the <span><span>frequency</span></span> parameter of the kernel clock, the oscillation frequency of the system clock is directly changed.• Example: If the system clock is slow by 10 seconds per day, the frequency can be increased by 115.74 ppm (<span><span>10 seconds / 86400 seconds ≈ 115.74 ppm</span></span>).Smooth Synchronization: By fine-tuning the frequency, the system time will approach the reference time at a linear rate rather than jumping directly.

3. Kernel Parameter Analysis

<span><span>adjtimex</span></span> operates on the following key parameters (passed through <span><span>struct timex</span></span><code><span><span>):</span></span>

<span><span>frequency</span></span>: Clock frequency offset, measured in ppm (parts per million). Positive values speed up the clock, while negative values slow it down.

<span><span>tick</span></span>: Clock interrupt period (in microseconds), default is 10,000 (i.e., 100 Hz).• Modifying <span><span>tick</span></span> can indirectly adjust the clock frequency but should be done with caution.

<span><span>offset</span></span>: Directly sets the time offset (in microseconds), usually adjusted automatically by NTP services.

<span><span>status</span></span>: Clock status flags (e.g., <span><span>STA_PLL</span></span> enables phase-locked loop frequency adjustment).

Below is an example of an automatic calibration script that dynamically adjusts the frequency based on RTC time deviation:

#!/bin/bash
# Get the time difference between system time and RTC (in seconds)
RTC_TIME=$(hwclock --debug | awk '/Hw clock time/ {print $5}' | tr -d ',')
SYS_TIME=$(date +%s)
DELTA=$(( $(date --date="$RTC_TIME" +%s) - $SYS_TIME ))

# Calculate frequency correction value (assuming calibration every 6 hours)
FREQ_CORRECTION=$(( DELTA * 1000000 / (6 * 3600) ))

# Apply correction
sudo adjtimex --frequency $FREQ_CORRECTION

Finally

The guy has collected some embedded learning materials, reply with 1024 in the public account to find the download link!

Recommended Articles  Click the blue text to jump
☞ Collection | Comprehensive Programming of Linux Applications
☞ Collection | Learn Some Networking Knowledge
☞ Collection | Handwritten C Language

☞ Collection | Handwritten C++ Language
☞ Collection | Experience Sharing
☞ Collection | From Microcontrollers to Linux
☞ Collection | Power Control Technology
☞ Collection | Essential Mathematics for Embedded Systems
☞ Collection | MCU Advanced Collection

☞ Collection | Embedded C Language Advanced Collection
☞ Collection | Experience Sharing

Leave a Comment