1 /*
2    This is a small demo of the NetX Duo PTP client on the high-performance NetX Duo TCP/IP stack.
3    This demo relies on ThreadX, NetX Duo and NetX Duo PTP client API to execute the Precision Time
4    Protocol.
5 
6  */
7 
8 #include <stdio.h>
9 #include "nx_api.h"
10 #include "nxd_ptp_client.h"
11 
12 #ifndef SAMPLE_DHCP_DISABLE
13 #include "nxd_dhcp_client.h"
14 #endif /* SAMPLE_DHCP_DISABLE */
15 
16 #define PTP_THREAD_PRIORITY 2
17 
18 /* Define the ThreadX and NetX object control blocks...  */
19 static TX_THREAD        thread_0;
20 static NX_PACKET_POOL   pool_0;
21 static NX_IP            ip_0;
22 #ifndef SAMPLE_DHCP_DISABLE
23 static NX_DHCP          dhcp_client;
24 #endif /* SAMPLE_DHCP_DISABLE */
25 static NX_PTP_CLIENT    ptp_client;
26 
27 /* Define the IP thread's stack area.  */
28 static ULONG            ip_thread_stack[2048 / sizeof(ULONG)];
29 
30 /* Define packet pool for the demonstration.  */
31 static ULONG            packet_pool_area[((1536 + sizeof(NX_PACKET)) * 32) / sizeof(ULONG)];
32 
33 /* Define the ARP cache area.  */
34 static ULONG            arp_space_area[512 / sizeof(ULONG)];
35 
36 /* Define the main thread.  */
37 static ULONG            thread_0_stack[2048 / sizeof(ULONG)];
38 static ULONG            ptp_stack[2048 / sizeof(ULONG)];
39 
40 /* Define an error counter.  */
41 static ULONG            error_counter;
42 
43 /* Define ptp utc offset.  */
44 static SHORT            ptp_utc_offset = 0;
45 
46 #ifndef SAMPLE_DHCP_DISABLE
47 #define IPV4_ADDRESS            IP_ADDRESS(0, 0, 0, 0)
48 #define IPV4_NETWORK_MASK       IP_ADDRESS(0, 0, 0, 0)
49 #else
50 #define IPV4_ADDRESS            IP_ADDRESS(10, 1, 0, 212)
51 #define IPV4_NETWORK_MASK       IP_ADDRESS(255, 255, 0, 0)
52 #define IPV4_GATEWAY_ADDR       IP_ADDRESS(10, 1, 0, 1)
53 #define DNS_SERVER_ADDRESS      IP_ADDRESS(10, 1, 0, 1)
54 #endif /* SAMPLE_DHCP_DISABLE */
55 
56 /* Define the main thread entry point. */
57 static VOID thread_0_entry(ULONG thread_input);
58 
59 /* PTP handler.  */
60 static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data);
61 
62 #ifndef SAMPLE_DHCP_DISABLE
63 static void dhcp_wait();
64 #endif /* SAMPLE_DHCP_DISABLE */
65 
66 /***** Substitute your ethernet driver entry function here *********/
67 #ifndef NETWORK_DRIVER
68 #define NETWORK_DRIVER _nx_ram_network_driver
69 #endif
70 extern VOID NETWORK_DRIVER(NX_IP_DRIVER *driver_req_ptr);
71 
72 #ifndef CLOCK_CALLBACK
73 #define CLOCK_CALLBACK nx_ptp_client_soft_clock_callback
74 #endif
75 extern UINT CLOCK_CALLBACK(NX_PTP_CLIENT *client_ptr, UINT operation,
76                            NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr,
77                            VOID *callback_data);
78 
79 #ifdef HARDWARE_SETUP
80 extern VOID HARDWARE_SETUP();
81 #endif
82 
main()83 int main()
84 {
85 #ifdef HARDWARE_SETUP
86     HARDWARE_SETUP();
87 #endif
88 
89     /* Enter the ThreadX kernel.  */
90     tx_kernel_enter();
91     return 0;
92 }
93 
94 
95 /* Define what the initial system looks like.  */
96 
tx_application_define(void * first_unused_memory)97 void    tx_application_define(void *first_unused_memory)
98 {
99 
100 UINT  status;
101 
102 
103     /* Initialize the NetX system.  */
104     nx_system_initialize();
105 
106     /* Create a packet pool.  */
107     status =  nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536,  (ULONG*)(((int)packet_pool_area + 15) & ~15) , sizeof(packet_pool_area));
108 
109     /* Check for pool creation error.  */
110     if (status)
111         error_counter++;
112 
113     /* Create an IP instance.  */
114     status = nx_ip_create(&ip_0,
115                           "NetX IP Instance 0",
116                           IPV4_ADDRESS,
117                           IPV4_NETWORK_MASK,
118                           &pool_0,
119                           NETWORK_DRIVER,
120                           (UCHAR*)ip_thread_stack,
121                           sizeof(ip_thread_stack),
122                           1);
123 
124     /* Check for IP create errors.  */
125     if (status)
126         error_counter++;
127 
128     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
129     status =  nx_arp_enable(&ip_0, (void *)arp_space_area, sizeof(arp_space_area));
130 
131     /* Check for ARP enable errors.  */
132     if (status)
133         error_counter++;
134 
135     /* Enable TCP traffic.  */
136     status =  nx_tcp_enable(&ip_0);
137 
138     /* Check for TCP enable errors.  */
139     if (status)
140         error_counter++;
141 
142     /* Enable UDP traffic.  */
143     status =  nx_udp_enable(&ip_0);
144 
145     /* Check for UDP enable errors.  */
146     if (status)
147         error_counter++;
148 
149     /* Enable ICMP.  */
150     status =  nx_icmp_enable(&ip_0);
151 
152     /* Check for errors.  */
153     if (status)
154         error_counter++;
155 
156     /* Create the main thread.  */
157     tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0,
158                      thread_0_stack, sizeof(thread_0_stack),
159                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
160 }
161 
162 
163 /* Define the test threads.  */
thread_0_entry(ULONG thread_input)164 void    thread_0_entry(ULONG thread_input)
165 {
166 
167 NX_PTP_TIME tm;
168 NX_PTP_DATE_TIME date;
169 
170 #ifndef SAMPLE_DHCP_DISABLE
171     dhcp_wait();
172 #endif /* SAMPLE_DHCP_DISABLE */
173 
174     /* Create the PTP client instance */
175     nx_ptp_client_create(&ptp_client, &ip_0, 0, &pool_0,
176                          PTP_THREAD_PRIORITY, (UCHAR *)ptp_stack, sizeof(ptp_stack),
177                          CLOCK_CALLBACK, NX_NULL);
178 
179     /* start the PTP client */
180     nx_ptp_client_start(&ptp_client, NX_NULL, 0, 0, 0, ptp_event_callback, NX_NULL);
181 
182     while(1)
183     {
184 
185         /* read the PTP clock */
186         nx_ptp_client_time_get(&ptp_client, &tm);
187 
188         /* convert PTP time to UTC date and time */
189         nx_ptp_client_utility_convert_time_to_date(&tm, -ptp_utc_offset, &date);
190 
191         /* display the current time */
192         printf("%2u/%02u/%u %02u:%02u:%02u.%09lu\r\n", date.day, date.month, date.year, date.hour, date.minute, date.second, date.nanosecond);
193 
194         tx_thread_sleep(NX_IP_PERIODIC_RATE);
195     }
196 }
197 
ptp_event_callback(NX_PTP_CLIENT * ptp_client_ptr,UINT event,VOID * event_data,VOID * callback_data)198 static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data)
199 {
200     NX_PARAMETER_NOT_USED(callback_data);
201 
202     switch (event)
203     {
204         case NX_PTP_CLIENT_EVENT_MASTER:
205         {
206             printf("new MASTER clock!\r\n");
207             break;
208         }
209 
210         case NX_PTP_CLIENT_EVENT_SYNC:
211         {
212             nx_ptp_client_sync_info_get((NX_PTP_CLIENT_SYNC *)event_data, NX_NULL, &ptp_utc_offset);
213             printf("SYNC event: utc offset=%d\r\n", ptp_utc_offset);
214             break;
215         }
216 
217         case NX_PTP_CLIENT_EVENT_TIMEOUT:
218         {
219             printf("Master clock TIMEOUT!\r\n");
220             break;
221         }
222         default:
223         {
224             break;
225         }
226     }
227 
228     return 0;
229 }
230 
231 /* DHCP */
232 #ifndef SAMPLE_DHCP_DISABLE
dhcp_wait(void)233 void dhcp_wait(void)
234 {
235 
236 ULONG   actual_status;
237 ULONG   ip_address;
238 ULONG   network_mask;
239 ULONG   gw_address;
240 
241     printf("DHCP In Progress...\r\n");
242 
243     /* Create the DHCP instance.  */
244     nx_dhcp_create(&dhcp_client, &ip_0, "dhcp_client");
245 
246     /* Start the DHCP Client.  */
247     nx_dhcp_start(&dhcp_client);
248 
249     /* Wait util address is solved. */
250     nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, NX_WAIT_FOREVER);
251 
252     /* Get IP address. */
253     nx_ip_address_get(&ip_0, &ip_address, &network_mask);
254     nx_ip_gateway_address_get(&ip_0, &gw_address);
255 
256     /* Output IP address. */
257     printf("IP address: %d.%d.%d.%d\r\nMask: %d.%d.%d.%d\r\nGateway: %d.%d.%d.%d\r\n",
258            (INT)(ip_address >> 24),
259            (INT)(ip_address >> 16 & 0xFF),
260            (INT)(ip_address >> 8 & 0xFF),
261            (INT)(ip_address & 0xFF),
262            (INT)(network_mask >> 24),
263            (INT)(network_mask >> 16 & 0xFF),
264            (INT)(network_mask >> 8 & 0xFF),
265            (INT)(network_mask & 0xFF),
266            (INT)(gw_address >> 24),
267            (INT)(gw_address >> 16 & 0xFF),
268            (INT)(gw_address >> 8 & 0xFF),
269            (INT)(gw_address & 0xFF));
270 }
271 #endif /* SAMPLE_DHCP_DISABLE  */