VxWorks系统中如何在usrAppInit.c中设置跨重启持久化的系统时间
VxWorks系统中如何在usrAppInit.c中设置跨重启持久化的系统时间
看起来你已经找对了方向,但可能在硬件RTC的写入环节没做足——要让时间跨重启保存,核心是把时间真正写入硬件实时时钟(RTC)芯片,而不只是修改系统的软件时钟。我来帮你梳理问题并给出修正方案:
你的现有代码存在的几个关键点问题
- 没有检查
vxbRtcSet的返回值:如果这个调用失败,说明根本没把时间写入硬件RTC,重启后自然会丢失 - 直接使用
gmtime返回的静态缓冲区:gmtime返回的是全局静态内存,后续其他时间操作可能会覆盖这个数据,导致写入RTC的时间出错 - 没有验证RTC写入是否成功:写完后最好读回来确认硬件已经保存了正确时间
修正后的完整实现方案
把下面的代码整合到你的usrAppInit.c中,它会确保时间被写入硬件RTC,且重启后依然有效:
#include <time.h> #include <vxWorks.h> #include <vxbRtcLib.h> #include <ipcom_printf.h> void setPersistentSystemTime(void) { struct timespec targetTime; struct tm rtcTm; // 用本地变量存储时间结构,避免静态缓冲区覆盖问题 struct tm *tmpTmPtr; // 1. 打印当前系统时间(用于对比) if (clock_gettime(CLOCK_REALTIME, &targetTime) != OK) { ipcom_printf("%s[%d] ERROR: 读取当前系统时间失败\n", __FUNCTION__, __LINE__); return; } ipcom_printf("%s[%d] 初始系统时间: %lx.%lx, %s\n", __FUNCTION__, __LINE__, (unsigned long)targetTime.tv_sec, (unsigned long)targetTime.tv_nsec, ipcom_ctime(&targetTime.tv_sec)); // 2. 设置你需要的目标时间(这里用你指定的1674065500,对应2023-01-19 12:11:40 GMT) targetTime.tv_sec = 1674065500UL; targetTime.tv_nsec = 0; // 3. 转换为GMT格式的tm结构,并复制到本地变量 tmpTmPtr = gmtime(&targetTime.tv_sec); if (tmpTmPtr == NULL) { ipcom_printf("%s[%d] ERROR: 时间格式转换失败\n", __FUNCTION__, __LINE__); return; } rtcTm = *tmpTmPtr; // 复制静态缓冲区内容到本地变量,避免后续被覆盖 // 4. 将时间写入硬件RTC(这是持久化的核心步骤) if (vxbRtcSet(&rtcTm) != OK) { ipcom_printf("%s[%d] ERROR: 写入硬件RTC失败\n", __FUNCTION__, __LINE__); return; } // 5. 验证RTC写入是否成功 if (vxbRtcGet(&rtcTm) != OK) { ipcom_printf("%s[%d] ERROR: 读取硬件RTC失败\n", __FUNCTION__, __LINE__); return; } // 把RTC读取到的时间转换回时间戳,同步系统软件时钟 targetTime.tv_sec = mktime_gmt(&rtcTm); // 使用GMT版本的mktime,避免时区偏移问题 targetTime.tv_nsec = 0; if (clock_settime(CLOCK_REALTIME, &targetTime) != OK) { ipcom_printf("%s[%d] ERROR: 更新系统软件时钟失败\n", __FUNCTION__, __LINE__); return; } // 6. 再次打印系统时间确认结果 if (clock_gettime(CLOCK_REALTIME, &targetTime) == OK) { ipcom_printf("%s[%d] 设置后系统时间: %lx.%lx, %s\n", __FUNCTION__, __LINE__, (unsigned long)targetTime.tv_sec, (unsigned long)targetTime.tv_nsec, ipcom_ctime(&targetTime.tv_sec)); } else { ipcom_printf("%s[%d] ERROR: 读取设置后系统时间失败\n", __FUNCTION__, __LINE__); } }
然后在usrAppInit函数的末尾添加调用:
void usrAppInit(void) { // ... 你原有的初始化代码 ... // 设置持久化系统时间 setPersistentSystemTime(); }
关键注意事项
- 硬件RTC的后备电池:如果你的硬件RTC没有后备电池,就算写入成功,断电重启后时间依然会丢失——这是硬件层面的问题,需要确认硬件配置
- RTC驱动初始化时机:确保
usrAppInit执行时,RTC驱动已经完成初始化。如果不确定,可以在代码开头添加vxbDevFind("rtc")检查设备是否存在 - 时区问题:一定要使用
gmtime和mktime_gmt来处理时间,避免时区转换导致的时间偏差 - 避免重复设置:如果不需要每次启动都强制设置时间,可以添加判断逻辑,比如只有当RTC时间远早于目标时间时才执行写入操作
备注:内容来源于stack exchange,提问作者PeterVE
相关产品推荐
相关产品推荐

