第 2 章 - Azure RTOS NetX Duo SNTP 客户端的安装和使用

本章旨在介绍与安装、设置和使用 Azure RTOS NetX Duo SNTP 客户端相关的各种问题。

产品分发

可在 https://github.com/azure-rtos/netxduo 获取 SNTP for NetX Duo。 此软件包包含两个源文件和一个 PDF 文件,该 PDF 文件包含本文档,如下所示:

  • nxd_sntp_client.c SNTP 客户端 C 源文件
  • nxd_sntp_client.h SNTP 客户端头文件
  • demo_netxduo_sntp_client.c 演示 SNTP 客户端应用程序
  • nxd_sntp_client.pdf NetX Duo SNTP 客户端用户指南

NetX Duo SNTP 客户端安装

若要使用 SNTP for NetX Duo,应将之前提到的全部分发文件复制到 NetX Duo 所安装的目录。 例如,如果在目录“\threadx\arm7\green”中安装了 NetX Duo,则应将 NetX Duo SNTP 客户端文件“nxd_sntp_client.c”和“nxd_sntp_client.h”(NetX 中的 nx_sntp_client.c 和 nx_sntp_client.h)复制到此目录。

使用 NetX Duo SNTP 客户端

使用 NetX Duo SNTP 客户端非常简单。 大致说来,必须在应用程序代码中加入 tx_api.h、fx_api.h 和 nx_api.h ,然后加入 nxd_sntp_client.h,才能分别使用 ThreadX 和 NetX Duo。 在包含 nxd_sntp_client.h 之后,应用程序代码即可进行本指南后文所指定的 SNTP 函数调用。 在生成过程中,还必须在应用程序中加入 nxd_sntp_client.c。 这些文件的编译方式必须与其他应用程序文件相同,并且其对象格式必须与应用程序的文件一起链接。 这就是使用 NetX Duo SNTP 客户端所需的全部内容。

注意

由于 NetX Duo SNTP 客户端使用 NetX Duo UDP 服务,因此在使用 SNTP 服务之前,必须通过 nx_udp_enable 启用 UDP。

小型示例系统

下面显示了如何使用 NetX Duo SNTP 的示例。 请注意,此示例不保证在系统上按原样工作。 你可能需要对特定系统和硬件进行调整。 例如,你必须将 NetX ram 驱动程序替换为实际的驱动程序函数。 从严格意义上说,此示例仅作演示之用。

在此示例中,包含了 SNTP 头文件 nxd_sntp_client.h。 SNTP 客户端在“tx_application_define”中创建。 请注意,在创建 SNTP 客户端时,导致必败的操作 (Kiss of Death) 和闰秒处理程序函数是可选的。

此演示可用于 IPv6 或 IPv4。 若要通过 IPv6 运行 SNTP 客户端,请定义 USE_IPV6。 还必须在 NetX Duo 中启用 IPv6。 为 NetX Duo 中的 IPv6 地址验证及 ICMPv6 和 IPv6 服务设置了 SNTP 客户端主机。 有关 NetX Duo 中 IPv6 支持的更多信息,请参阅 NetX Duo 用户指南。

然后,必须为单播或广播模式初始化 SNTP 客户端。

SNTP 客户端最初会将服务器时间更新写入其自己的内部数据结构。 这与设备本地时间不同。 设备本地时间可以设置为 SNTP 客户端中的基线时间,然后启动 SNTP 客户端线程。 如果配置 SNTP 客户端(NX_SNTP_CLIENT_IGNORE_MAX_ADJUST_STARTUP 设置为 NX_FALSE)以将第一次服务器更新与 NX_SNTP_CLIENT_MAX_ADJUSTMENT(默认值 180 毫秒)进行比较,则这会非常有用。 否则,在从服务器获取第一次更新时,SNTP 客户端将直接设置初始本地时间。

使用 nx_sntp_client_set_local_time 服务将基线时间应用于 SNTP 客户端。

SNTP 客户端分别启动单播和广播模式。 对于特定间隔(略低于单播轮询间隔),应用程序使用来自“实时时钟”的“nx_sntp_client_set_local_time”更新 SNTP 客户端本地时间,我们只需通过增加当前时间的秒和毫秒来进行模拟。 在每个间隔后,应用程序会定期检查 SNTP 服务器更新。 nx_sntp_client_receiving _updates 服务验证 SNTP 客户端当前是否正在接收有效更新。 如果是,它将使用 nx_sntp_client_get_local_time_extended 服务检索最新的更新时间。

如果 SNTP 客户端检测到 SNTP 客户端不再接收有效更新等情况,则可随时使用 nx_sntp_client_stop 服务停止该 SNTP 客户端。 若要重新启动客户端,应用程序必须调用单播或广播初始化服务,然后调用单播或广播运行服务。 当 SNTP 客户端线程任务停止时,SNTP 客户端可以根据需要切换 SNTP 服务器和模式(单播和广播),如以前的 SNTP 服务器显示为关闭状态。

/* 
   This is a small demo of the NetX SNTP Client on the high-performance NetX
   TCP/IP stack. This demo relies on Thread, NetX and NetX SNTP Client API to
   execute the Simple Network Time Protocol in unicast and broadcast modes.  
 */

#include <stdio.h>
#include "nx_api.h"
#include "nx_ip.h"
#include "nxd_sntp_client.h"
                
/* Define SNTP packet size. */
#define NX_SNTP_CLIENT_PACKET_SIZE      (NX_UDP_PACKET + 100)

/* Define SNTP packet pool size. */
#define NX_SNTP_CLIENT_PACKET_POOL_SIZE      (4 * (NX_SNTP_CLIENT_PACKET_SIZE + 
                                                            sizeof(NX_PACKET)))

/* Define how often the demo checks for SNTP updates. */
#define DEMO_PERIODIC_CHECK_INTERVAL      (1 * NX_IP_PERIODIC_RATE) 

/* Define how often we check on SNTP server status. 
   We expect updates from the SNTP server about every hour using 
   the SNTP Client defaults. For testing
   make this (much) shorter. */
#define CHECK_SNTP_UPDATES_TIMEOUT       (180 * NX_IP_PERIODIC_RATE) 

/* Set up generic network driver for demo program. */
void    _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);

/* Application defined services of the NetX SNTP Client. */

UINT leap_second_handler(NX_SNTP_CLIENT *client_ptr, 
                                UINT leap_indicator);
UINT kiss_of_death_handler(NX_SNTP_CLIENT *client_ptr, 
                                        UINT KOD_code);
VOID time_update_callback(NX_SNTP_TIME_MESSAGE *time_update_ptr, 
                                       NX_SNTP_TIME *local_time);


/* Set up client thread and network resources. */

NX_PACKET_POOL      client_packet_pool;
NX_IP               client_ip;
TX_THREAD           demo_client_thread;
NX_SNTP_CLIENT      demo_sntp_client;
TX_EVENT_FLAGS_GROUP sntp_flags;

#define DEMO_SNTP_UPDATE_EVENT  1

/* Configure the SNTP Client to use IPv6. If not enabled, the 
   Client will use IPv4.  Note: IPv6 must be enabled in NetX Duo
   for the Client to communicate over IPv6.    */
#ifdef FEATURE_NX_IPV6
/* #define USE_IPV6 */
#endif /* FEATURE_NX_IPV6 */


/* Configure the SNTP Client to use unicast SNTP. */
#define USE_UNICAST


#define CLIENT_IP_ADDRESS       IP_ADDRESS(192,2,2,66)
#define SERVER_IP_ADDRESS       IP_ADDRESS(192,2,2,92)
#define SERVER_IP_ADDRESS_2     SERVER_IP_ADDRESS

/* Set up the SNTP network and address index; */
UINT     iface_index =0;
UINT     prefix = 64;   
UINT     address_index;

/* Set up client thread entry point. */
void    demo_client_thread_entry(ULONG info);

/* Define main entry point.  */
int main()
{
    /* Enter the ThreadX kernel.  */
    tx_kernel_enter();
    return 0;
}

/* Define what the initial system looks like.  */
void    tx_application_define(void *first_unused_memory)
{

UINT     status;
UCHAR    *free_memory_pointer;


    free_memory_pointer = (UCHAR *)first_unused_memory;

    /* Create client packet pool. */
    status =  nx_packet_pool_create(&client_packet_pool, 
                                "SNTP Client Packet Pool",
                                NX_SNTP_CLIENT_PACKET_SIZE, 
                                free_memory_pointer, 
                                NX_SNTP_CLIENT_PACKET_POOL_SIZE);

    /* Check for errors. */
    if (status != NX_SUCCESS)
    {

        return;
    }

    /* Initialize the NetX system. */
    nx_system_initialize();

    /* Update pointer to unallocated (free) memory. */
    free_memory_pointer =  free_memory_pointer + NX_SNTP_CLIENT_PACKET_POOL_SIZE;

    /* Create Client IP instances */
    status = nx_ip_create(&client_ip, "SNTP IP Instance", 
                                        CLIENT_IP_ADDRESS, 
                                        0xFFFFFF00UL, 
                                        &client_packet_pool, 
                                       _nx_ram_network_driver, 
                                       free_memory_pointer, 2048, 1);
    
    /* Check for error. */
    if (status != NX_SUCCESS)
    {

        return;
    }

    free_memory_pointer =  free_memory_pointer + 2048;

#ifndef NX_DISABLE_IPV4
    /* Enable ARP and supply ARP cache memory. */
    status =  nx_arp_enable(&client_ip, (void **) free_memory_pointer, 2048);

    /* Check for error. */
    if (status != NX_SUCCESS)
    {

        return;
    }
#endif /* NX_DISABLE_IPV4  */

    /* Update pointer to unallocated (free) memory. */
    free_memory_pointer = free_memory_pointer + 2048;
    
    /* Enable UDP for client. */
    status =  nx_udp_enable(&client_ip);
    
    /* Check for error. */
    if (status != NX_SUCCESS)
    {

        return;
    }

#ifndef NX_DISABLE_IPV4
    status = nx_icmp_enable(&client_ip);

    /* Check for error. */
    if (status != NX_SUCCESS)
    {

        return;
    }
#endif /* NX_DISABLE_IPV4  */

    /* Create the client thread */
    status = tx_thread_create(&demo_client_thread, "SNTP Client Thread", 
                                                demo_client_thread_entry, 
                                              (ULONG)(&demo_sntp_client), 
                                                free_memory_pointer, 2048, 
                                                  4, 4, TX_NO_TIME_SLICE, 
                                                        TX_DONT_START);

    /* Check for errors */
    if (status != TX_SUCCESS)
    {

        return;
    }

    /* Create the event flags. */
    status = tx_event_flags_create(&sntp_flags, "SNTP event flags");

    /* Check for errors */
    if (status != TX_SUCCESS)
    {

        return;
    }

    /* Update pointer to unallocated (free) memory. */
    free_memory_pointer = free_memory_pointer + 2048;

    /* set the SNTP network interface to the primary interface. */
    iface_index = 0;

    /* Create the SNTP Client to run in broadcast mode.. */
status =  nx_sntp_client_create(&demo_sntp_client, &client_ip,
                           iface_index, &client_packet_pool,  
                               leap_second_handler, 
                               kiss_of_death_handler, 
                               NULL /* no random_number_generator callback */);

    /* Check for error. */
    if (status != NX_SUCCESS)
    {

        /* Bail out!*/
        return;
    }

    tx_thread_resume(&demo_client_thread);

    return;
}

/* Define size of buffer to display client's local time. */
#define BUFSIZE 50

/* Define the client thread.  */
void    demo_client_thread_entry(ULONG info)
{

UINT   status;
UINT   spin;
UINT   server_status;
ULONG  base_seconds;
ULONG  base_fraction;
ULONG  seconds, milliseconds, microseconds, fraction;
UINT   wait = 0;
UINT   error_counter = 0;
ULONG  events = 0;
#ifdef USE_IPV6
NXD_ADDRESS sntp_server_address;
NXD_ADDRESS client_ip_address;
#endif

    NX_PARAMETER_NOT_USED(info);

    /* Give other threads (IP instance) initialize first. */
    tx_thread_sleep(NX_IP_PERIODIC_RATE); 

#ifdef USE_IPV6
    /* Set up IPv6 services. */
    status = nxd_ipv6_enable(&client_ip);

    status += nxd_icmp_enable(&client_ip);

    if (status  != NX_SUCCESS)
        return;

    client_ip_address.nxd_ip_address.v6[0] = 0x20010db8;
    client_ip_address.nxd_ip_address.v6[1] = 0x0000f101;
    client_ip_address.nxd_ip_address.v6[2] = 0x0;
    client_ip_address.nxd_ip_address.v6[3] = 0x101;
    client_ip_address.nxd_ip_version = NX_IP_VERSION_V6;

    /* Set the IPv6 server address. */
    sntp_server_address.nxd_ip_address.v6[0] = 0x20010db8;  
    sntp_server_address.nxd_ip_address.v6[1] = 0x0000f101;
    sntp_server_address.nxd_ip_address.v6[2] = 0x0;
    sntp_server_address.nxd_ip_address.v6[3] = 0x00000106;
    sntp_server_address.nxd_ip_version = NX_IP_VERSION_V6;

    /* Establish the link local address for the host. The RAM driver creates
       a virtual MAC address. */
    status = nxd_ipv6_address_set(&client_ip, iface_index, NX_NULL, 10, NULL);

    /* Check for link local address set error.  */
    if (status != NX_SUCCESS) 
    {
        return;
    }

     /* Set the host global IP address. We are assuming a 64 
       bit prefix here but this can be any value (< 128). */
    status = nxd_ipv6_address_set(&client_ip, iface_index, 
                                        &client_ip_address, 
                                    prefix, &address_index);

    /* Check for global address set error.  */
    if (status != NX_SUCCESS) 
    {
        return;
    }

    /* Wait while NetX Duo validates the global and link local addresses. */
    tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);

#endif

    /* Setup time update callback function. */
    nx_sntp_client_set_time_update_notify(&demo_sntp_client, 
                                        time_update_callback);

    /* Set up client time updates depending on mode. */
#ifdef USE_UNICAST

    /* Initialize the Client for unicast mode to 
       poll the SNTP server once an hour. */
#ifdef USE_IPV6
/* Use the duo service to set up the Client and set the IPv6 SNTP server.
   Note: this can take either an IPv4 or IPv6 address. */
    status = nxd_sntp_client_initialize_unicast(&demo_sntp_client, 
                                            &sntp_server_address);
#else
    /* Use the IPv4 service to set up the Client and set the IPv4 SNTP server. */
    status = nx_sntp_client_initialize_unicast(&demo_sntp_client, 
                                                SERVER_IP_ADDRESS);
#endif  /* USE_IPV6 */


#else   /* Broadcast mode */

/* Initialize the Client for broadcast mode, no roundtrip calculation
   required and a broadcast SNTP service. */
#ifdef USE_IPV6
    /* Use the duo service to initialize the Client 
       and set IPv6 SNTP all hosts multicast address. 
       (Note: This can take either an IPv4 or IPv6 address.)*/
    status = nxd_sntp_client_initialize_broadcast(&demo_sntp_client, 
                                                &sntp_server_address, 
                                                            NX_NULL);
#else

    /* Use the IPv4 service to initialize the Client and set 
       IPv4 SNTP broadcast address. */
    status = nx_sntp_client_initialize_broadcast(&demo_sntp_client,  
                                                NX_NULL, 
                                                SERVER_IP_ADDRESS);
#endif  /* USE_IPV6 */
#endif  /* USE_UNICAST */

    /* Check for error. */
    if (status != NX_SUCCESS)
    {
        return;
    }

    /* Set the base time which is approximately the number of seconds since
       the turn of the last century. If this is not available in SNTP format,
       the nx_sntp_client_utility_add_msecs_to_ntp_time service can convert
       milliseconds to fraction.  For how to compute NTP seconds from real
   time, read the NetX SNTP User Guide. Otherwise set the base time to 
   zero and set NX_SNTP_CLIENT_IGNORE_MAX_ADJUST_STARTUP to NX_TRUE for
       the SNTP CLient to accept the first time update without applying a
       minimum or maximum adjustment parameters
      (NX_SNTP_CLIENT_MIN_TIME_ADJUSTMENT and
       NX_SNTP_CLIENT_MAX_TIME_ADJUSTMENT). */

    base_seconds =  0xd2c96b90;  /* Jan 24, 2012 UTC */
    base_fraction = 0xa132db1e;

    /* Apply to the SNTP Client local time.  */
status = nx_sntp_client_set_local_time(&demo_sntp_client, base_seconds,
                                base_fraction);

    /* Check for error. */
    if (status != NX_SUCCESS)
    {
        return;
    }

    /* Run whichever service the client is configured for. */
#ifdef USE_UNICAST
    status = nx_sntp_client_run_unicast(&demo_sntp_client);
#else
    status = nx_sntp_client_run_broadcast(&demo_sntp_client);
#endif  /* USE_UNICAST */

    if (status != NX_SUCCESS)
    {
        return;
    }

    spin = NX_TRUE;

    /* Now check periodically for time changes. */
    while(spin)
    {
        /* Wait for a server update event. */
        tx_event_flags_get(&sntp_flags, DEMO_SNTP_UPDATE_EVENT, 
                                          TX_OR_CLEAR, &events, 
                                 DEMO_PERIODIC_CHECK_INTERVAL);

        if (events == DEMO_SNTP_UPDATE_EVENT)
        {

            /* Check for valid SNTP server status. */
            status = nx_sntp_client_receiving_updates(&demo_sntp_client,
                                               &server_status);

            if ((status != NX_SUCCESS) || (server_status == NX_FALSE))
            {

                /* We do not have a valid update. Skip processing any time
                   data. If this happens repeatedly, consider stopping the
                   SNTP Client thread, picking another SNTP server and
                   resuming the SNTP Client thread task (more details about
                   that in the comments at the end of this function).
                 
                   If SNTP Client configurable parameters are too restrictive,
                   such as Max Adjustment, that may also cause valid server
                   updates to be rejected. Configurable parameters, however,
                   cannot be changed at run time.
                 */
                 
                continue;
            }

            /* We have a valid update.  Get the SNTP Client time.  */
            status = nx_sntp_client_get_local_time_extended(&demo_sntp_client, 
                                                    &seconds, &fraction,  
                                                    NX_NULL, 0); 

            /* Convert fraction to microseconds. */
            nx_sntp_client_utility_fraction_to_usecs(fraction, &microseconds);

            milliseconds = ((microseconds + 500) / 1000);

            if (status != NX_SUCCESS)
            {
                printf("Internal error with getting local time 0x%x\n", 
                       status);
                error_counter++;
            }
            else
            {
                printf("\nSNTP updated\n");
                printf("Time: %lu.%03lu sec.\r\n", seconds, milliseconds);
            }

            /* Clear all events in our event flag. */
            events = 0;
        }
        else
        {

            /* No SNTP update event.             
               In the meantime, if we have an RTC we might want to check
               its notion of time. In this demo, we simulate the passage of 
               time on our 'RTC' really just the CPU counter, assuming that 
               seconds and milliseconds have previously been set to a base 
              (starting) time (as was the SNTP Client before running it) 
             */

            seconds += 1;
            milliseconds += 1;

            /* Update our timer. */
            wait += DEMO_PERIODIC_CHECK_INTERVAL;

            /* Check if it is time to display the local 'RTC' time. */
            if (wait >= CHECK_SNTP_UPDATES_TIMEOUT)
            {
                /* It is. Reset the timeout and print local time. */
                wait = 0;

                printf("Time: %lu.%03lu sec.\r\n", seconds, milliseconds);
            }           
        }
    }

/* We can stop the SNTP service if for example we think the SNTP server 
   has stopped sending updates.
     
       To restart the SNTP Client, simply call the
       nx_sntp_client_initialize_unicast or
       nx_sntp_client_initialize_broadcast using another SNTP server IP
       address as input, and resume the SNTP Client by calling
       nx_sntp_client_run_unicast or
       nx_sntp_client_run_braodcast. */
    status = nx_sntp_client_stop(&demo_sntp_client);

    if (status != NX_SUCCESS)
    {
        error_counter++;
    }

    /* When done with the SNTP Client, we delete it */
    status = nx_sntp_client_delete(&demo_sntp_client);

    return;
}


/* This application defined handler for handling an 
   impending leap second is not required by 
   the SNTP Client. The default handler below only logs the
   event for every time stamp received with the 
   leap indicator set.  */

UINT leap_second_handler(NX_SNTP_CLIENT *client_ptr, 
                                UINT leap_indicator)
{
    NX_PARAMETER_NOT_USED(client_ptr);
    NX_PARAMETER_NOT_USED(leap_indicator);

    /* Handle the leap second handler... */

    return NX_SUCCESS;
}

/* This application defined handler for handling 
   a Kiss of Death packet is not required by the SNTP Client. 
   A KOD handler should determine if the Client task should continue vs. 
   abort sending/receiving time data from its current time server, 
   and if aborting if it should remove
   the server from its active server list. 

   Note that the KOD list of codes is subject to change. The list
   below is current at the time of this software release. */

UINT kiss_of_death_handler(NX_SNTP_CLIENT *client_ptr, UINT KOD_code)
{

UINT    remove_server_from_list = NX_FALSE;
UINT    status = NX_SUCCESS;

    NX_PARAMETER_NOT_USED(client_ptr);

    /* Handle kiss of death by code group. */
    switch (KOD_code)
    {

        case NX_SNTP_KOD_RATE:
        case NX_SNTP_KOD_NOT_INIT:
        case NX_SNTP_KOD_STEP:

            /* Find another server while this one 
               is temporarily out of service.  */
            status =  NX_SNTP_KOD_SERVER_NOT_AVAILABLE;

        break;

        case NX_SNTP_KOD_AUTH_FAIL:
        case NX_SNTP_KOD_NO_KEY:
        case NX_SNTP_KOD_CRYP_FAIL:

            /* These indicate the server will not 
               service client with time updates
               without successful authentication. */


            remove_server_from_list =  NX_TRUE;

        break;


        default:

            /* All other codes. Remove server 
               before resuming time updates. */

            remove_server_from_list =  NX_TRUE;
        break;
    }

    /* Removing the server from the active server list? */
    if (remove_server_from_list)
    {

        /* Let the caller know it has to bail on 
           this server before resuming service. */
        status = NX_SNTP_KOD_REMOVE_SERVER;
    }

    return status;
}


/* This application defined handler for notifying SNTP time update event.  */

VOID time_update_callback(NX_SNTP_TIME_MESSAGE *time_update_ptr, 
                                       NX_SNTP_TIME *local_time)
{
    tx_event_flags_set(&sntp_flags, DEMO_SNTP_UPDATE_EVENT, TX_OR);
}

图 1 将 SNTP 客户端与 NetX Duo 一起使用的示例

配置选项

有几个配置选项用于定义 NetX Duo SNTP 客户端。 以下列表详细介绍了每个配置选项:

NX_SNTP_CLIENT_THREAD_STACK_SIZE
此选项设置客户端线程堆栈的大小。 NetX Duo SNTP 客户端大小默认为 2048。

NX_SNTP_CLIENT_THREAD_TIME_SLICE
此选项设置计划程序允许客户端线程执行的时间片。 NetX Duo SNTP 客户端大小默认为 TX_NO_TIME_SLICE。

NX_SNTP_CLIENT_ THREAD_PRIORITY
此选项设置客户端线程优先级。 NetX Duo SNTP 客户端默认值为 2。

NX_SNTP_CLIENT_PREEMPTION_THRESHOLD
此选项设置客户端线程允许抢占的优先级级别。 NetX Duo SNTP 客户端值默认设置为 NX_SNTP_CLIENT_ THREAD_PRIORITY

NX_SNTP_CLIENT_UDP_SOCKET_NAME
此选项设置 UDP 套接字名称。 NetX Duo SNTP 客户端 UDP 套接字名称默认为“SNTP 客户端套接字”。

NX_SNTP_CLIENT_UDP_PORT
这将设置客户端套接字绑定到的端口。 NetX Duo SNTP 客户端端口默认为 123。

NX_SNTP_SERVER_UDP_PORT
这是客户端向其上的 SNTP 服务器发送 SNTP 消息的端口。 NetX SNTP 服务器端口默认为 123。

NX_SNTP_CLIENT_TIME_TO_LIVE
指定客户端数据包在被丢弃之前可以传递的路由器数。 NetX Duo SNTP 客户端默认设置为 0x80**。

NX_SNTP_CLIENT_MAX_QUEUE_DEPTH
可在 NetX Duo SNTP 客户端套接字中排队的最大 UDP 数据包(数据报)数量。 接收的其他数据包意味着释放最早的数据包。 NetX Duo SNTP 客户端默认设置为 5。

NX_SNTP_CLIENT_PACKET_TIMEOUT
NetX Duo 数据包分配超时。 NetX Duo SNTP 客户端数据包默认超时 1 秒。

NX_SNTP_CLIENT_NTP_VERSION
客户端 NetX Duo SNTP 客户端 API 使用的 SNTP 版本基于版本 4。 默认值为 3。

NX_SNTP_CLIENT_MIN_NTP_VERSION
客户端将能够使用的最早的 SNTP 版本。 NetX Duo SNTP 客户端默认为版本 3。

NX_SNTP_CLIENT_MIN_SERVER_STRATUM
客户端将接受的级别最低的(最高数值层次级别)SNTP 服务器层次。 NetX Duo SNTP 客户端默认为 2。

NX_SNTP_CLIENT_MIN_TIME_ADJUSTMENT
客户端将对其本地时钟时间进行的最小时间调整(以毫秒为单位)。 低于此量的时间调整将被忽略。 NetX Duo SNTP 客户端默认为 10。

NX_SNTP_CLIENT_MAX_TIME_ADJUSTMENT
客户端将对其本地时钟时间进行的最大时间调整(以毫秒为单位)。 对于超过此量的时间调整,本地时钟调整受限于最大时间调整。 NetX Duo SNTP 客户端默认为 180000(3 分钟)。

NX_SNTP_CLIENT_IGNORE_MAX_ADJUST_STARTUP
这样,当客户端从其时间服务器接收第一次更新时,将放弃最大时间调整。 此后,将强制执行最大时间调整。 目的是尽快使客户端与服务器时钟同步。 NetX Duo SNTP 客户端默认为 NX_TRUE。

NX_SNTP_CLIENT_MAX_TIME_LAPSE
在 SNTP 客户端未接收有效时间更新的情况下,已过去的最大可允许时间量(以秒为单位)。 SNTP 客户端将继续运行,但 SNTP 服务器状态设置为 NX_FALSE。 默认值为 7200。

NX_SNTP_UPDATE_TIMEOUT_INTERVAL
SNTP 客户端计时器更新自上次收到有效更新以来剩余的 SNTP 客户端时间的间隔(以秒为单位),单播客户端会在发送下一个 SNTP 更新请求之前更新剩余的轮询间隔时间。 默认值为 1。

NX_SNTP_CLIENT_UNICAST_POLL_INTERVAL
客户端向其 SNTP 服务器发送单播请求的起始轮询间隔(以秒为单位)。 NetX Duo SNTP 客户端默认为 3600。

NX_SNTP_CLIENT_EXP_BACKOFF_RATE
当前客户端单播轮询间隔增加的因子。 当客户端无法接收服务器时间更新或从服务器接收到其暂时不可进行时间更新服务的指示(例如尚未同步)后,它将按此速率增加当前轮询间隔,最高可达 NX_SNTP_CLIENT_MAX_TIME_LAPSE(但不超过)。 默认值为 2。

NX_SNTP_CLIENT_RTT_REQUIRED
如果启用此选项,则需要 SNTP 客户端在将服务器更新应用于本地时钟时计算 SNTP 消息的往返时间。 默认值为 NX_FALSE(已禁用)。

NX_SNTP_CLIENT_MAX_ROOT_DISPERSION
客户端将接受的最大服务器时钟离散(以微秒为单位),它是服务器时钟精度的度量值。 若要禁用此要求,请将最大根散射设置为 0x0。 NetX Duo SNTP 客户端默认为 50000。

NX_SNTP_CLIENT_INVALID_UPDATE_LIMIT
在广播或单播模式下,从客户端服务器收到的连续无效更新次数的限制。 达到此限制时,客户端会将当前的 SNTP 服务器状态设置为无效 (NX_FALSE),尽管它将继续尝试从服务器接收更新。 NetX Duo SNTP 客户端默认为 3。

NX_SNTP_CLIENT_RANDOMIZE_ON_STARTUP
这会确定单播模式下的 SNTP 客户端是否应在随机等待间隔后向当前 SNTP 服务器发送其第一个 SNTP 请求。 它用于大量 SNTP 客户端同时启动的情况,以限制 SNTP 服务器上的流量拥堵。 默认值是 NX_FALSE。

NX_SNTP_CLIENT_SLEEP_INTERVAL
SNTP 客户端任务休眠的时间间隔。 这样,应用程序 API 调用就会由 SNTP 客户端执行。 默认值为 1(计时器时钟周期)。

NX_SNTP_CURRENT_YEAR
若要按年/月/日格式显示日期,请将此值设置为等于或小于当前年份(不必与被评估的 NTP 时间的年份相同)。 默认值为 2015。

NTP_SECONDS_AT_01011999
这是主 NTP 时钟上第一个 NTP Epoch 中的秒数。 它定义为 0xBA368E80。 若要禁止在日期和时间中显示 NTP 秒数,请设置为零。