項目場景:
需要增加外置RTC,保證時間的精準。
問題描述:
基本情況,外置i2c接口的RTC,注冊、讀寫都正常,但是偶發性重啟后,系統時間是2022,rtc時間是1970,都像是恢復了默認時間一樣。
原因分析:
幾個名詞含義:
- 系統時鐘(
date
):存儲在內存中,由操作系統維護,斷電后會丟失,依賴硬件時鐘初始化。- 硬件時鐘(
hwclock
):由主板電池供電的獨立時鐘,斷電后仍能運行,用于系統啟動時初始化系統時鐘。- UTC時間:全球統一時間。
- CST時間:我國采用時間,東八區時間,UTC+8。
- 例如:硬件時鐘顯示
10:00 UTC
,系統時鐘若為北京時間(UTC+8),則顯示18:00
。
設置時間腳本:
#/bin/bash
echo close ntp
timedatectl set-ntp false
echo time set rtc1
date -s "2025-07-16 8:00:00" && hwclock -w -f /dev/rtc1
echo print rtc1
hwclock -f /dev/rtc1
echo system to rtc1
hwclock --systohc -u
echo show rtc1
hwclock -u
echo sync to sys
hwclock --hctosys -u
這樣設置后,date返回的系統時間,以及hwclock返回的rtc時間都是正確的,但是奇怪的事情發生了,若干次重啟后,date顯示2022,hwclock顯示1970。
于是查看內核打印信息,是怎么說的:
內核顯示上電時,就是把rtc讀給了系統啊,但是確實是讀了1970,那原因在于,nxp有自己集成的一個rtc0是默認的,實際上通過hwclock查的是rtc0,并不是我的外置rtc,通過指令可以看到,外置的rtc1實際上是一直正常工作的。
解決方案:
那解決的問題就是變成了:干掉rtc0,使能rtc1,有很多的解決辦法,我的解決辦法是簡單粗暴,改設備樹。
其中在NXP的設備樹中,我找到了他對自己rtc的定義
snvs: snvs@30370000 {compatible = "fsl,sec-v4.0-mon","syscon", "simple-mfd";reg = <0x30370000 0x10000>;snvs_rtc: snvs-rtc-lp {compatible = "fsl,sec-v4.0-mon-rtc-lp";regmap =<&snvs>;offset = <0x34>;interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,<GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clk IMX8MP_CLK_SNVS_ROOT>;clock-names = "snvs-rtc";};snvs_pwrkey: snvs-powerkey {compatible = "fsl,sec-v4.0-pwrkey";regmap = <&snvs>;interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clk IMX8MP_CLK_SNVS_ROOT>;clock-names = "snvs-pwrkey";linux,keycode = <KEY_POWER>;wakeup-source;status = "disabled";};};
snvs_rtc就是我們的目標rtc,把它干掉就可以了。
在自己的設備樹xxx.dts里加上這一句,因為我是引用了NXP的imx8mp.dtsi的。
&snvs_rtc{status = "disabled";
};
至此,大功告成,時間正常,內核打印只顯示這個i2crtc了,只是映射從從rtc1變為了rtc0。
最后:記得更改本地時區。
timedatectl set-timezone Asia/Shanghai