如何快速调试RTC?

时间:2023-01-16 12:00:56

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框图 如何快速调试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时间同步提供支持。

本文作者:软通动力HOS

想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com/#bkwz​