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  */