前言
最近捣鼓RT-Thread的RTC时钟时,发现有点小bug(4.1.0版本的bug,之前用4.0.1还没发现),记录一下学习的过程。
平台
芯片:STM32F405RGT6
RT-Thread版本:4.1.0(发行版)
硬件:使用内部时钟
配置ENV
- 开启RTC组件,不要选择软件模拟RTC
- 使能RTC片上外设
- 选择时钟源。我这里硬件上没有外接晶振,所以只能用内部时钟。
- scons生成工程
配置CubeMX
- 使能RTC
- 配置时钟
- 将CubeMX生成的工程文件中的时钟配置函数替换到rtthread的工程中
添加代码
- 设置时间的函数
void rtc_set_time(int argc, char *argv[])
{
if(argc < 2)
{
return;
}
else
{
time_t timestamp = atoi(argv[1]);//字符串转整型
rt_device_t dev = RT_NULL;
dev = rt_device_find("rtc");
if(dev == RT_NULL)
{
return;
}
rt_err_t ret = rt_device_control(dev, RT_DEVICE_CTRL_RTC_SET_TIME, ×tamp);
if(ret != RT_EOK)
{
rt_kprintf("set rtc time fail\n");
}
}
}
MSH_CMD_EXPORT(rtc_set_time, set time);
- 获取时间的函数
void rtc_get_time(void)
{
rt_device_t dev = RT_NULL;
dev = rt_device_find("rtc");
if(dev == RT_NULL)
{
return;
}
time_t timestamp;
rt_err_t ret = rt_device_control(dev, RT_DEVICE_CTRL_RTC_GET_TIME, ×tamp);
if(ret != RT_EOK)
{
rt_kprintf("get time fail\n");
}
else
{
struct tm *tm_local = localtime(×tamp); // 转换为本地时间
// 打印日期和时间
rt_kprintf("current date and time: %d-%02d-%02d %02d:%02d:%02d\n",
tm_local->tm_year + 1900, tm_local->tm_mon + 1, tm_local->tm_mday,
tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec);
}
}
MSH_CMD_EXPORT(rtc_get_time, get time);
Bug
编译下载代码后,进行测试,发现在使用命令rtc_set_time设置rtc时间时,总是设置失败。像这样
当我发现用date命令时,会有这样的打印
看了一下代码,发现这个打印只有在初始化rtc的函数stm32_rtc_init中才有的。因此前面用rtc_set_time设置rtc时间失败的原因是rtc硬件还没有初始化。
仔细研究了一下drv_rtc.c文件中的代码后,发现rtthread自动初始化机制所调用的函数为rt_hw_rtc_init,这个函数只是对rtc设备进行注册,并没有对rtc硬件进行初始化。而当使用date这个命令是,rtc设备没有初始化的情况下,会调用到硬件初始化函数stm32_rtc_init。(具体这个调用关系需要自己去理清)
也就是说,在当前代码的基础上,如果我要设置rtc时间,就要先调用rtc的初始化函数,那么只需要将rtc的初始化函数stm32_rtc_init加到rt_hw_rtc_init中即可。
之后就能正常使用rtc时钟了。
顺带一提,获取rtc时间也可以用time函数
time_t now = time(NULL);//获取当前时间戳
struct tm *tm_local = localtime(&now); // 转换为本地时间
// 打印日期和时间
rt_kprintf("date:%04d-%02d-%02d\ntime:%02d:%02d:%02d\n",
tm_local->tm_year + 1900, tm_local->tm_mon + 1, tm_local->tm_mday,
tm_local->tm_hour, tm_local->tm_min, tm_local->tm_sec);
rtthread中的time函数,实际上调用的也是获取rtc的时间