【简介】
RTC (Real-Time Clock)实时时钟可以提供精确的实时时间,它可以用于产生年、月、日、时、分、秒等信息。在RT-thread 中将RTC 设备驱动定义了特定的驱动框架,我们只要实现底层的OPS 函数即完成了RTC 驱动的适配。对应的OPS 如下,如果不使用alarm功能我么只要实现init/get_secs/set_secs/get_timeval/set_timeval函数接口即可。
/* used for alarm function */ struct rt_rtc_wkalarm { rt_bool_t enable; /* 0 = alarm disabled, 1 = alarm enabled */ rt_int32_t tm_sec; /* alarm at tm_sec */ rt_int32_t tm_min; /* alarm at tm_min */ rt_int32_t tm_hour; /* alarm at tm_hour */ rt_int32_t tm_mday; /* alarm at tm_mday */ rt_int32_t tm_mon; /* alarm at tm_mon */ rt_int32_t tm_year; /* alarm at tm_year */ }; struct rt_rtc_ops { rt_err_t (*init)(void); rt_err_t (*get_secs)(time_t *sec); rt_err_t (*set_secs)(time_t *sec); rt_err_t (*get_alarm)(struct rt_rtc_wkalarm *alarm); rt_err_t (*set_alarm)(struct rt_rtc_wkalarm *alarm); rt_err_t (*get_timeval)(struct timeval *tv); rt_err_t (*set_timeval)(struct timeval *tv); }; typedef struct rt_rtc_device { struct rt_device parent; const struct rt_rtc_ops *ops; } rt_rtc_dev_t;
【驱动配置】
1.Kconfig 配置
menuconfig BSP_USING_ONCHIP_RTC bool "Enable RTC" select RT_USING_RTC select RT_USING_LIBC default n
在menuconfig 中使能刚才配置的RTC 开关
2.SConscript 配置
添加rtc 驱动适配文件
# add rtc driver if GetDepend('BSP_USING_ONCHIP_RTC'): src += ['drv_rtc.c']
添加S32K146 SDK RTC驱动代码
# add rtc drivers config. if GetDepend('BSP_USING_ONCHIP_RTC'): src += ['peripherals_rtc_1.c']
# add rtc drivers config. if GetDepend('BSP_USING_ONCHIP_RTC'): src += ['platform/drivers/src/rtc/rtc_driver.c'] src += ['platform/drivers/src/rtc/rtc_hw_access.c'] src += ['platform/drivers/src/rtc/rtc_irq.c']
3.RTC 驱动OPS配置
init 函数
static rt_err_t s32k14x_rtc_init(void) { status_t ret; /* Call the init function */ ret = RTC_DRV_Init(RTC_1, &rtc_1InitCfg0); if(ret != STATUS_SUCCESS) { LOG_E("RTC init failed %x.",ret); goto __exit; } else { LOG_I("RTC init OK."); } /* Set the time and date */ ret = RTC_DRV_SetTimeDate(RTC_1, &rtc_1InitCfg0_StartTime); if(ret != STATUS_SUCCESS) { LOG_E("RTC set time failed %x.",ret); goto __exit; } else { LOG_I("RTC set time OK."); } /* Start RTC counter */ ret = RTC_DRV_StartCounter(RTC_1); if(ret != STATUS_SUCCESS) { LOG_E("RTC start failed %x.",ret); goto __exit; } else { LOG_I("RTC start OK."); } __exit: return ret == STATUS_SUCCESS ? RT_EOK : -RT_ERROR; }
get_timeval 函数
static rt_err_t s32k14x_rtc_get_timeval(struct timeval *tv) { status_t ret; rtc_timedate_t currentTime; struct tm tm_new = {0}; ret = RTC_DRV_GetCurrentTimeDate ( RTC_1, ¤tTime ); if(ret != STATUS_SUCCESS) { LOG_E("RTC read failed %x.",ret); goto __exit; } tm_new.tm_sec = currentTime.seconds; tm_new.tm_min = currentTime.minutes; tm_new.tm_hour = currentTime.hour; tm_new.tm_mday = currentTime.day; tm_new.tm_mon = currentTime.month-1; tm_new.tm_year = currentTime.year-1900; tv->tv_sec = timegm(&tm_new); __exit: return ret == STATUS_SUCCESS ? RT_EOK : -RT_ERROR; }
get_secs 函数
static rt_err_t s32k14x_rtc_get_secs(time_t *sec) { struct timeval tv; s32k14x_rtc_get_timeval(&tv); *(time_t *) sec = tv.tv_sec; LOG_D("RTC: get rtc_time %d", *sec); return RT_EOK; }
set_secs 函数
static rt_err_t set_rtc_time_stamp(time_t time_stamp) { status_t ret; rtc_timedate_t currentTime; struct tm tm = {0}; gmtime_r(&time_stamp, &tm); if (tm.tm_year < 100) { return -RT_ERROR; } ret = RTC_DRV_StopCounter(RTC_1); if(ret != STATUS_SUCCESS) { LOG_E("RTC stop failed %x.",ret); return -RT_ERROR; } currentTime.seconds = tm.tm_sec ; currentTime.minutes = tm.tm_min ; currentTime.hour = tm.tm_hour; currentTime.day = tm.tm_mday; currentTime.month = tm.tm_mon + 1 ; currentTime.year = tm.tm_year + 1900; ret = RTC_DRV_SetTimeDate(RTC_1, ¤tTime); if(ret != STATUS_SUCCESS) { LOG_E("RTC set time failed %x.",ret); return -RT_ERROR; } ret = RTC_DRV_StartCounter(RTC_1); if(ret != STATUS_SUCCESS) { LOG_E("RTC start failed %x.",ret); return -RT_ERROR; } return RT_EOK; } static rt_err_t s32k14x_rtc_set_secs(time_t *sec) { rt_err_t result = RT_EOK; if (set_rtc_time_stamp(*sec)) { result = -RT_ERROR; } LOG_D("RTC: set rtc_time %d", *sec); return result; }
注册rtc_ops 至系统
/******************************************************************************************************** * Private Variable Definitions * *******************************************************************************************************/ static const struct rt_rtc_ops s32k14x_rtc_ops = { .init = s32k14x_rtc_init, .get_secs = s32k14x_rtc_get_secs, .get_timeval = s32k14x_rtc_get_timeval, .set_secs = s32k14x_rtc_set_secs, .get_alarm = NULL, .set_alarm = NULL, .set_timeval = NULL }; static struct rt_rtc_device rtc_device; /******************************************************************************************************** * Global Function Declarations * *******************************************************************************************************/ static int rt_hw_rtc_init(void) { rt_err_t result; rtc_device.ops = &s32k14x_rtc_ops; result = rt_hw_rtc_register(&rtc_device, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL); if (result != RT_EOK) { LOG_E("rtc register err code: %d", result); return result; } LOG_D("rtc init success"); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_rtc_init);
【功能验证】
list device 发现RTC驱动设备已经注册到系统
输入date 读取当前时间
date 设置时间为2025/6/27 20:35:30,设置时间后再次读取时间和设置的保持一致