SNTP,Simple Network Time Protocol(简单网络时间协议),用来同步时钟。
百度百科:SNTP
SNTP协议采用客户端/服务器的工作方式,可以采用单播(点对点)或者广播(一点对多点)模式操作。
SNTP服务器通过接收GPS信号或自带的原子钟作为系统的时间基准。
单播模式下,SNTP客户端能够通过定期访问SNTP服务器获得准确的时间信息,用于调整客户端自身所在系统的时间,达到同步时间的目的。
广播模式下,SNTP服务器周期性地发送消息给指定的IP广播地址或者IP多播地址;SNTP客户端通过监听这些地址来获得时间信息。
sntp_setoperatingmode()
,SNTP_OPMODE_POLL
表示单播模式,SNTP_OPMODE_LISTENONLY
表示广播模式。// sntp.h 47
/* SNTP operating modes: default is to poll using unicast.
The mode has to be set before calling sntp_init(). */
#define SNTP_OPMODE_POLL 0
#define SNTP_OPMODE_LISTENONLY 1
// sntp.c 713
/**
* @ingroup sntp
* Sets the operating mode.
* @param operating_mode one of the available operating modes
*/
void
sntp_setoperatingmode(u8_t operating_mode)
{
LWIP_ASSERT_CORE_LOCKED();
LWIP_ASSERT("Invalid operating mode", operating_mode <= SNTP_OPMODE_LISTENONLY);
LWIP_ASSERT("Operating mode must not be set while SNTP client is running", sntp_pcb == NULL);
sntp_opmode = operating_mode;
}
sntp_setservername()
。这里的SNTP_MAX_SERVERS
控制了服务器数量,后面有说明在哪里修改。// sntp.c 865
/**
* Initialize one of the NTP servers by name
*
* @param idx the index of the NTP server to set must be < SNTP_MAX_SERVERS
* @param server DNS name of the NTP server to set, to be resolved at contact time
*/
void
sntp_setservername(u8_t idx, const char *server)
{
LWIP_ASSERT_CORE_LOCKED();
if (idx < SNTP_MAX_SERVERS) {
sntp_servers[idx].name = server;
}
}
sntp_set_time_sync_notification_cb()
,后面有说明回调函数怎么处理。// sntp.c 69
// set a callback function for time synchronization notification
void sntp_set_time_sync_notification_cb(sntp_sync_time_cb_t callback)
{
time_sync_notification_cb = callback;
}
sntp_init()
来初始化SNTP模块。const char *g_apcNtpServer[] = {
"0.pool.ntp.org",
"1.pool.ntp.org",
"2.pool.ntp.org",
"3.pool.ntp.org",
};
static void utc_sntp_init(void)
{
sntp_setoperatingmode(SNTP_OPMODE_POLL);
uint8_t ucServNum = sizeof(g_apcNtpServer) / sizeof(g_apcNtpServer[0]);
for (uint8_t cnt = 0; cnt < ucServNum; cnt++)
{
sntp_setservername(cnt, g_apcNtpServer[cnt]);
}
sntp_set_time_sync_notification_cb(&sntp_set_time_sync_callback);
sntp_init();
}
sntp_sync_time()
里被调用,形参是结构体指针类型struct timeval *
,可以直接得到长整型的UTC时间(秒和毫秒)。void sntp_set_time_sync_callback(struct timeval *tv)
{
struct tm timeinfo = {0};
ESP_LOGI(UTC_TAG, "tv_sec: %lld", (uint64_t)tv->tv_sec);
localtime_r((const time_t *)&(tv->tv_sec), &timeinfo);
ESP_LOGI(UTC_TAG, "%d %d %d %d:%d:%d", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday,
timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
// sntp_stop();
// utc_set_time((uint64_t)tv->tv_sec);
}
SNTP_MAX_SERVERS
,也就是CONFIG_LWIP_DHCP_MAX_NTP_SERVERS
,在make menuconfig
中修改。// sntp_opts.h 59
/** The maximum number of SNTP servers that can be set */
#if !defined SNTP_MAX_SERVERS || defined __DOXYGEN__
#define SNTP_MAX_SERVERS LWIP_DHCP_MAX_NTP_SERVERS
#endif
// opt.h 952
/**
* The maximum of NTP servers requested
*/
#if !defined LWIP_DHCP_MAX_NTP_SERVERS || defined __DOXYGEN__
#define LWIP_DHCP_MAX_NTP_SERVERS 1
#endif
// lwipopts.h 812
#define LWIP_DHCP_MAX_NTP_SERVERS CONFIG_LWIP_DHCP_MAX_NTP_SERVERS
// sdkconfig.h
#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 4
SNTP_UPDATE_DELAY
,到下一次发起更新时间请求的间隔时间,单位是ms,最小不能小于15s,也是通过make menuconfig
修改CONFIG_LWIP_SNTP_UPDATE_DELAY
。// sntp.c 74
#ifndef SNTP_SUPPRESS_DELAY_CHECK
#if SNTP_UPDATE_DELAY < 15000
#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds (define SNTP_SUPPRESS_DELAY_CHECK to disable this error)!"
#endif
#endif
// sntp_opts.h 167
/** SNTP update delay - in milliseconds
* Default is 1 hour. Must not be beolw 60 seconds by specification (i.e. 60000)
*/
#if !defined SNTP_UPDATE_DELAY || defined __DOXYGEN__
#define SNTP_UPDATE_DELAY 3600000
#endif
// lwipopts.h 829
#define SNTP_UPDATE_DELAY CONFIG_LWIP_SNTP_UPDATE_DELAY
// sdkconfig.h
#define CONFIG_LWIP_SNTP_UPDATE_DELAY 600000