想了解更多关于开源的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com
1、RTC介绍
RTC是Real Time Clock的简称,它在硬件电路上单独供电,当系统关机时,CPU和其他外部硬件设备全部掉电,但是RTC仍然继续工作。这样就可以继续给设备提供精准的时钟,并提供报警功能和计时器功能。
2、如何查询系统时间和硬件时间
(1)查询系统时间.
# dateSat Aug 5 09:15:26 UTC 2017
(2)查看RTC硬件时间:hwclock -r 显示RTC时间(读取RTC时间显示)。
# hwclockSat Aug 5 09:13:36 2017 0.000000 seconds
(3) 设置系统时间,硬件时间hwclock -r 显示RTC时间(读取RTC时间显示)hwclock -w 设置RTC时间(将系统时间传递给RTC驱动,设置RTC的驱动时间)hwclock -s 设置系统时间(将RTC时间读取出来设置给系统时间).
3、如何查看RTC设备节点及文件
(1)RTC设备节点。
# pwd
/dev# ls rtc*
rtc rtc0 rtc1
2)sys/class/rtc
# pwd
/sys/class/rtc# ls
rtc0 rtc1# pwd
/sys/class/rtc/rtc0# ls
alarmtimer.3.auto device name subsystem wakealarm
date hctosys power time
dev max_user_freq since_epoch uevent
(2)proc/driver/rtc:获取RTC的相关信息。
# cat proc/driver/rtc
rtc_time : 09:12:46
rtc_date : 2017-08-05
alrm_time : 00:00:00
alrm_date : 1999-12-16
alarm_IRQ : no
alrm_pending : no
update IRQ enabled : no
periodic IRQ enabled : no
periodic IRQ frequency : 1
max user IRQ frequency : 64
24hr : yes
4、内核中如何开启RTC,并设置时间同步
在linux系统上,从用户空间正确管理RTC需要关注两个内核选项:CONFIG_RTC_HCTOSYSCONFIG_RTC_HCTOSYS_DEVICE要使用CONFIG_RTC_HCTOSYS应在内核构建过程中包含代码文件drivers/rtc/hctosys.c,它在启动和恢复时从RTC设置系统时间。一旦启用此选项,就将使用从指定RTC设备读取的值设置系统时间。RTC设备应该在CONFIG_RTC_HCTOSYS_DEVICE中指定:
CONFIG_RTC_HCTOSYS=yCONFIG_RTC_HCTOSYS_DEVICE="rtc0"
5、RTC关键结构体说明
rtc_time 结构体说明:
struct rtc_time {
inttm_sec; /* 秒,0~60(60是闰秒的需要)*/
inttm_min; /* 分钟,0~59*/
inttm_hour; /* 小时,0~23 */
inttm_mday; /* 本月中的第几天,1~31 */
inttm_mon; /* 自一月以来的第几个月,0~11*/
inttm_year; /* 自1900年以来的年数*/
inttm_wday; /* 本周的第几天,0~6,星期天是0 */
inttm_yday; /* 一年当中的第几天,0~365*/
inttm_isdst; /* 夏令时标志*/
};
rtc_wkalrm 结构体说明:
struct rtc_wkalrm {
unsignedchar enabled; /* 0 = 禁止alarm,1 = 使能alarm */
unsignedchar pending; /* 0 = alarm未挂起,1 = alarm挂起(已发生)*/
structrtc_time time; /* 设置的alarm中断发生的时刻 */
};
6、RTC框图
7、RTC适配问题总结
问题1:/dev/rtc未生成,无法获取硬件时间。
# hwclock
hwclock: /dev/misc/rtc: No such file or directory
问题分析:启动日志报错no valid clock/calendar values available
[ 1.179936] rk808-rtc rk808-rtc: registered as rtc0[ 1.186459] rtc-hym8563 5-0051: no valid clock/calendar values available[ 1.186675] rtc-hym8563 5-0051: registered as rtc1[ 1.187698] rtc-hym8563 5-0051: no valid clock/calendar values available[ 1.187723] rtc-hym8563 5-0051: hctosys: unable to read the hardware clock
从log分析,rtc1时钟值无效,可能为人为写入了无效值,或者初始化时写入了无效值;解决方案:
(1)在dts中添加init_date项,当hym8563_probe的时候,检测到系统如果未设置时间,则给时钟芯片一个默认值(init_date 设置的值);
&i2c_AO {
status = "okay";
pinctrl-names="default";
pinctrl-0=;
clock-frequency = ; /* default 100k */
/* for rtc hym8563 */ hym8563: hym8563@51 {
compatible = "haoyu,hym8563";
reg = ;
init_date = "2021/07/28";
#clock-cells = ;
};
};
(2)通过命令设置硬件时钟;
hwclock -w。
验证结果:通过日志查看显示.
[ 1.413453] rk808-rtc rk808-rtc: registered as rtc0
[ 1.423286] rtc-hym8563 5-0051: registered as rtc1
[ 1.424348] rtc-hym8563 5-0051: setting system clock to 2021-11-13T21:10:55 UTC (1636837855)
问题2:将rtc1设置为硬件时钟后,连接网络进行NTP时间同步,查看rtc1时钟未同步,实际同步的是rtc0硬件时钟
# dateFri Nov 18 15:53:21 UTC 2022# hwclockSun Nov 14 20:18:58 2021 0.000000 seconds
问题分析:怀疑连接网络后,网络时间同步模块在将同步后的系统时间写入硬件时钟时,写入到了/dev/rtc0,而非实际使用的/dev/rtc1;经排查网络时间同步后设置硬件时钟代码所在位置为:/base/miscservices/time/services/time_manager/src/time_service.cpp加入LOG打印信息如下,证实问题所在就是写入到了/dev/rtc0,而非实际使用的/dev/rtc1;
# hilog | grep RTC
11-18 15:46:28.906 464 464 E 01c02/TimeService: [time_service.cpp] set_rtc_time# RTC rtc_id : 0:
11-18 15:46:28.906 464 464 E 01c02/TimeService: [time_service.cpp] set_rtc_time# RTC rtc_dev : /dev/rtc0:
解决方案:修改代码set_rtc_time函数中,设备节点由/dev/rtc0修改为/dev/rtc,此时/dev/rtc软连接的是实际使用的硬件时钟/dev/rtc1,而非固定为/dev/rtc0。
vi base/miscservices/time/services/time_manager/src/time_service.cpp +351
@@ -348,13 +356,15 @@ int TimeService::set_rtc_time(time_t sec)
return -1;
}
std::stringstream strs;
- strs << "/dev/rtc" << rtc_id;
+ strs << "/dev/rtc";
修改后发现NTP时钟同步仍然失败,加log打印后发现,set_rtc_time中open设备节点失败。
11-18 17:10:41.495 533 533 E 01c02/TimeService: [time_service.cpp] set_rtc_time# RTC rtc_dev : /dev/rtc:11-18 17:10:41.495 533 533 E 01c02/TimeService: [time_service.cpp] set_rtc_time# RTC open failed /dev/rtc: Permission denied
查看设备节点发现,新增的rtc1用户组为root,因此用户程序无权限打开,需将用户组修改为system。
# ls -al rtc*
lrwxrwxrwx 1 root system 4 2021-11-14 21:15 rtc -> rtc1
crw-r----- 1 system system 250, 0 2021-11-14 21:15 rtc0
crw-r----- 1 root root 250, 1 2021-11-14 21:15 rtc1
在设备初始化代码中增加修改rtc1用户组:
index 766f404..0530a20 100755
--- a/rk3568/build/rootfs/init.rk3568.cfg
+++ b/rk3568/build/rootfs/init.rk3568.cfg
@@ -5,7 +5,8 @@
"jobs" : [{
"name" : "pre-init",
"cmds" : [
- "write /proc/sys/vm/min_free_kbytes 10240"
+ "write /proc/sys/vm/min_free_kbytes 10240",
+ "chown system system /dev/rtc1"
]
}, {
"name" : "init",
修改后查看rtc1用户组:
# cd dev/# ls -al rtc*
lrwxrwxrwx 1 root system 4 2022-11-18 18:24 rtc -> rtc1
crw-r----- 1 system system 250, 0 2022-11-18 18:24 rtc0
crw-rw---- 1 system system 250, 1 2022-11-18 18:24 rtc1
用户程序可正常打开:
11-18 18:00:36.159 533 533 E 01c02/TimeService: [time_service.cpp] set_rtc_time# RTC rtc_dev : /dev/rtc:11-18 18:00:36.161 533 533 E 01c02/TimeService: [time_service.cpp] set_rtc_time# RTC set_rtc_time success!!!!!!
验证结果:结果符合预期,连接网络后系统时间,硬件时钟均自动同步为网络时间。
//设置系统和硬件时间为非当前时间。
# dateFri Jan 1 00:02:40 UTC 2021
# hwclockFri Jan 1 00:02:46 2021 0.000000 seconds//
连接网络后,同步网络时间,系统时间和硬件时钟均自动同步。
# dateMon Nov 21 15:19:28 UTC 2022
# hwclockMon Nov 21 15:19:32 2022 0.000000 seconds
总结:
本文介绍了OpenHarmony中外置RTC调试和使用方法,以及RTC在操作系统中的作用,为后续NTP时间同步提供支持。
想了解更多关于开源的内容,请访问:
51CTO 开源基础软件社区
https://ost.51cto.com