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
- Enable
<span><span>rtcsync</span></span>
:sudo nano /etc/systemd/timesyncd.conf
Modify to:
[Time] RTCSync=yes
- Restart the service:
sudo systemctl restart systemd-timesyncd
- Verify synchronization:
timedatectl show-timesync | grep RTCTimeUSec # Check the most recent RTC synchronization time hwclock -r && 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:
- 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
- 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
- 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