OK3568 RTC 驱动适配与 Linux 系统时间管理总结
文章目录
- [OK3568 RTC 驱动适配与 Linux 系统时间管理总结](#OK3568 RTC 驱动适配与 Linux 系统时间管理总结)
-
- 一、背景
- 二、适配步骤
-
- [2.1 I2C 总线确认](#2.1 I2C 总线确认)
- [2.2 驱动文件确认](#2.2 驱动文件确认)
- [2.3 修改设备树](#2.3 修改设备树)
- [2.4 内核配置开启 RX8010 驱动](#2.4 内核配置开启 RX8010 驱动)
- [2.5 烧写验证](#2.5 烧写验证)
- [三、RTC 与系统时间的关系(核心知识点)](#三、RTC 与系统时间的关系(核心知识点))
-
- [3.1 两个时钟的区别](#3.1 两个时钟的区别)
- [3.2 上电同步:hctosys](#3.2 上电同步:hctosys)
- [3.3 运行期间的同步命令](#3.3 运行期间的同步命令)
- [3.4 时区注意](#3.4 时区注意)
- 四、调试过程与问题解决
-
- [4.1 问题一:Frequency stop 告警](#4.1 问题一:Frequency stop 告警)
- [五、BMS 场景的时间管理方案](#五、BMS 场景的时间管理方案)
- 六、总结
一、背景
| 硬件平台 | RTC 芯片 |
|---|---|
| FCU2601 核心板 | RX8010SJ(EPSON) |
| OK3568 开发板 | PCF8563(NXP) |
| BCU3.0 产品 | RX8010SJ |
BCU3.0 使用的核心板与 OK3568 开发板一致(都是飞凌的 OK3568-C),但 RTC 芯片从 PCF8563 换成了 RX8010SJ,因此需要将软件从 PCF8563 适配到 RX8010SJ。
二、适配步骤
2.1 I2C 总线确认
查看 BCU3.0 原理图与 OK3568 原理图,两颗 RTC 芯片都挂在 RK3568 的 I2C3 总线上:
| 芯片 | I2C 地址 |
|---|---|
| RX8010 | 0x32 |
| PCF8563 | 0x51 |
I2C 总线驱动不需要修改,只需调整设备树。
2.2 驱动文件确认
OK3568 SDK 内核源码中已包含两套 RTC 驱动:
bash
ls kernel/drivers/rtc/rtc-rx8010.c
ls kernel/drivers/rtc/rtc-pcf8563.c
不需要自己编写驱动,关键是要在内核配置中启用 RX8010 驱动。
2.3 修改设备树
文件位置:
OK3568_Linux_fs/kernel/arch/arm64/boot/dts/rockchip/OK3568-C-common.dtsi
修改前(原代码):
dts
&i2c3 {
status = "okay";
rx8010: rx8010@32 {
compatible = "epson,rx8010";
reg = <0x32>;
};
pcf8563: pcf8563@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
#clock-cells = <0>;
};
};
修改后:
dts
&i2c3 {
status = "okay";
rx8010: rx8010@32 {
compatible = "epson,rx8010";
reg = <0x32>;
status = "okay"; /* 启用 RX8010 */
};
pcf8563: pcf8563@51 {
compatible = "nxp,pcf8563";
reg = <0x51>;
status = "disabled"; /* 禁用 PCF8563 */
};
};
关键变化:RX8010 加 status = "okay",PCF8563 加 status = "disabled"。确保同一 I2C 总线上只有一颗 RTC 芯片被使能。
2.4 内核配置开启 RX8010 驱动
这是整个适配中最容易被忽略的一步。默认的 OK3568 板级 defconfig 中 RX8010 驱动未使能:
bash
zcat /proc/config.gz | grep RX8010
# 输出:# CONFIG_RTC_DRV_RX8010 is not set
需要修改板级 defconfig(注意:直接 make menuconfig 改 .config 无效,因为飞凌的 build.sh kernel 每次会用 defconfig 覆盖 .config):
bash
cd /home/forlinx/3568/OK3568-linux-source/kernel/arch/arm64/configs/
vim OK3568-C-linux_defconfig
在文件末尾添加:
CONFIG_RTC_DRV_RX8010=y
保存后重新编译内核:
bash
cd /home/forlinx/3568/OK3568-linux-source
./build.sh kernel
编译完成后验证:
bash
grep RX8010 kernel/.config
# 预期输出:CONFIG_RTC_DRV_RX8010=y
2.5 烧写验证
将新生成的 boot.img 烧写到开发板 boot 分区,重启后验证:
bash
# 1. 确认驱动已编译进内核
zcat /proc/config.gz | grep RX8010
# → CONFIG_RTC_DRV_RX8010=y
# 2. 确认驱动注册成功
dmesg | grep -i rtc
# → rtc-rx8010 3-0032: rtc core: registered rx8010 as rtc0
# → rtc-rx8010 3-0032: setting system clock to 2026-06-05 02:35:21 UTC
# 3. 确认设备节点存在
ls /dev/rtc*
# → /dev/rtc /dev/rtc0
三、RTC 与系统时间的关系(核心知识点)
3.1 两个时钟的区别
┌─────────────────────────────────────────┐
│ Linux 系统 │
│ │
│ 系统时间 (Software Clock) │
│ · 内核维护的软件计数器 │
│ · date / timedatectl 查看 │
│ · 纳秒级精度 │
│ · 基于 CPU 定时器中断累加 │
│ · ❌ 断电丢失,重启归零 │
│ │
│ ↕ hwclock 命令 │
│ │
│ RTC 硬件时钟 (Hardware Clock) │
│ · I2C 芯片 RX8010 内部计时 │
│ · hwclock -r 查看 │
│ · 秒级精度 │
│ · 32.768kHz 晶振 │
│ · ✅ Vbat 供电 → 断电保持 │
└─────────────────────────────────────────┘
| 系统时间 | RTC 硬件时钟 | |
|---|---|---|
| 存储位置 | 内核内存变量 | I2C RTC 芯片寄存器 |
| 断电后 | 丢失 | 保持 |
| 精度 | 纳秒级 | 秒级 |
| 读取命令 | date |
hwclock -r |
| 写入命令 | date -s |
hwclock -w |
3.2 上电同步:hctosys
Linux 内核启动时,如果开启了 CONFIG_RTC_HCTOSYS=y,会自动从 RTC 读取时间并设置为系统时间:
bash
zcat /proc/config.gz | grep HCTOSYS
# → CONFIG_RTC_HCTOSYS=y
# → CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
dmesg 日志中能看到:
rtc-rx8010 3-0032: setting system clock to 2026-06-05 02:35:21 UTC
这个过程是内核自动完成的,不需要用户编写任何代码。
3.3 运行期间的同步命令
| 场景 | 命令 | 说明 |
|---|---|---|
| 查看系统时间 | date |
本地时区显示 |
| 查看 RTC 时间 | sudo hwclock -r |
读硬件时钟 |
| RTC → 系统 | sudo hwclock -s |
hctosys 手动版 |
| 系统 → RTC | sudo hwclock -w |
systohc |
| 查看完整信息 | timedatectl status |
含时区、NTP 状态 |
| 设置系统时间 | sudo date -s "2026-06-05 15:30:00" |
临时校准 |
3.4 时区注意
RTC 硬件时钟通常存储 UTC 时间 (内核驱动默认行为),系统时间显示为本地时间 (+08:00 北京时区)。
dmesg 里看到的是 UTC:02:35:21 UTC,date 显示是 10:35:21 CST,差了 8 小时是正常的。
应用程序拿时间用 time() / gettimeofday() 取系统时间即可,时区转换由系统处理。
四、调试过程与问题解决
4.1 问题一:Frequency stop 告警
首次上电后 dmesg 出现:
rtc-rx8010 3-0032: Frequency stop was detected
rtc-rx8010 3-0032: hctosys: unable to read the hardware clock
原因:RX8010 上电后检测到内部振荡器曾停振(XST 标志位),驱动拒绝读取时钟。这是新芯片首次上电、或者 Vbat 备份电源掉过电的典型现象。
解决 :先用 hwclock -w 写入一次系统时间,驱动写入操作会清除 XST 标志:
bash
# 先随便设一个系统时间(或从网络获取)
sudo date -s "2026-06-05 15:30:00"
# 写入RTC(同时清除XST标志)
sudo hwclock -w -f /dev/rtc0
# 验证读数正常
sudo hwclock -r -f /dev/rtc0
写入成功后,Frequency stop 告警消失,hctosys 恢复正常。
五、BMS 场景的时间管理方案
BCU3.0 常规运行不联网,没有 NTP 时间源。时间同步闭环如下:
上电启动
└── 内核 hctosys:RTC → 系统时间(自动,零代码)
│
运行期间(104 主站对时)
└── 收到时钟同步指令
├── settimeofday() 校准系统时间
└── hwclock -w 写入 RTC
│
下次断电再上电
└── RTC 保持正确时间 → hctosys → 系统时间恢复
| 环节 | 负责方 | 是否需要自己写代码 |
|---|---|---|
| 上电 RTC→系统 | 内核 CONFIG_RTC_HCTOSYS=y |
不需要 |
| 运行中读取时间 | time() / gettimeofday() |
一行调用 |
| 时间校准 | 104 主站下发对时指令 | 需实现 handler |
| 校准后写回 RTC | hwclock -w |
一行命令 |
| 故障录波时间戳 | 直接从系统时间取 | 不需要 |
六、总结
RTC 驱动的适配本质上是三件事:
- 设备树------让内核知道 I2C3 上挂了什么芯片
- 内核配置 ------把对应驱动编译进去(
CONFIG_RTC_DRV_RX8010=y) - 理解 RTC 与系统时间的关系------启动自动同步(hctosys)、运行中读写(hwclock)、断电保持(备份电池)
整个过程中不需要自己写一行 RTC 驱动代码,内核社区已经做好了全部工作。你的应用程序只需要 time() 取系统时间即可,RTC 对上层透明。
参考资料
- EPSON RX8010SJ Datasheet
- Linux kernel RTC subsystem
- 飞凌 OK3568-C 开发板资料
- 前篇:OK3568 设备树适配 RX8010
最后更新:2026-06-05