嵌入式技术论坛
直播中

王刚

8年用户 1352经验值
私信 关注
[经验]

RT-Thread系统使用ntp_sync进行网络时钟同步

硬件

RT-THREAD ART-PI开发板,使用4G模块EC200进行时钟同步。

现象

msh />ntp_sync
[I/ntp] Get local time from NTP server: Fri May 28 23:02:58 2021
[I/ntp] 1622214178
[I/ntp] year:2000, month:3, day:4
[I/ntp] hour:23, min:2, sec:58
[I/ntp] Get local time from NTP server: Fri May 28 23:02:58 2021

使用ntp_sync进行网络时钟同步。年月日时间没有同步,时分秒时间同步了。

解决

修改packages\netutils\ntp\ntp.c文件中代码。

struct tm *cur_tm;
cur_tm = localtime(&cur_time);
set_time(cur_tm->tm_hour, cur_tm->tm_min, cur_tm->tm_sec);
set_date(cur_tm->tm_year + 1900, cur_tm->tm_mon + 1, cur_tm->tm_mday);

更改为

struct tm *cur_tm;
struct tm cur_tm_t;
cur_tm = &cur_tm_t;
localtime_r(&cur_time, cur_tm);
set_time(cur_tm->tm_hour, cur_tm->tm_min, cur_tm->tm_sec);
set_date(cur_tm->tm_year + 1900, cur_tm->tm_mon + 1, cur_tm->tm_mday);

或者使用设备操作替换

rt_device_control(rt_device_find("rtc"), RT_DEVICE_CTRL_RTC_SET_TIME, &cur_time);

问题分析

函数localtime调用流程。

graph LR
A[localtime] --> B[localtime_r]
B --> C[gmtime_r]

其中它返回的地址是localtime函数中声明的静态变量static struct tm tmp。

其中cur_tm指针指向struct tm tmp的地址。而后面的函数set_time(cur_tm->tm_hour, cur_tm->tm_min, cur_tm->tm_sec);会调用localtime函数,同时更改静态变量的值,同步更新cur_tm->tm_year等值。造成set_date函数中参数变化,影响年月日的设置。

使用localtime_r函数,将值保存在声明的局部变量,可修复bug。

set_time中包含localtime(),影响cur_tm指针指向的变量。

rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)
{
time_t now;
struct tm p_tm;
struct tm tm_new;
rt_device_t device;
rt_err_t ret = -RT_ERROR;
/
get current time /
now = time(RT_NULL);
/
lock scheduler. /
rt_enter_critical();
/
converts calendar time into local time. /
p_tm = localtime(&now);
/
copy the statically located variable /
rt_memcpy(&tm_new, p_tm, sizeof(struct tm));
/
unlock scheduler. /
rt_exit_critical();
/
update time. /
tm_new.tm_hour = hour;
tm_new.tm_min = minute;
tm_new.tm_sec = second;
/
converts the local time into the calendar time. /
now = mktime(&tm_new);
device = rt_device_find("rtc");
if (device == RT_NULL)
{
return -RT_ERROR;
}
/
update to RTC device. */
ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &now);
return ret;
}

原作者:HVOK_6419

更多回帖

发帖
×
20
完善资料,
赚取积分