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