1 /* PTP two steps off test.  This test case validates two steps off procedure of PTP client synchronize. */
2 
3 #include   "netx_ptp_utility.h"
4 
5 #define     DEMO_STACK_SIZE    2048
6 
7 /* Define the ThreadX and NetX object control blocks...  */
8 
9 static TX_THREAD               ntest_0;
10 static TX_THREAD               ntest_1;
11 
12 static NX_PACKET_POOL          pool_0;
13 static NX_IP                   ip_0;
14 static NX_IP                   ip_1;
15 static NX_UDP_SOCKET           generic_socket;
16 static NX_UDP_SOCKET           event_socket;
17 static NX_PTP_CLIENT           ptp_client;
18 
19 static NX_PTP_TIME             sync_ts = {0x0, 0x5F97CD71, 0x240d93b2};
20 static NX_PTP_TIME             follow_up_ts = {0x0, 0x5F97CD71, 0x240e29e0};
21 static NX_PTP_TIME             delay_response_ts = {0x0, 0x5F97CD71, 0x2494b730};
22 static NX_PTP_TIME             synced_time;
23 static NX_PTP_TIME             expected_time;
24 static USHORT                  synced_utc_offset;
25 static USHORT                  expected_utc_offset;
26 static UCHAR                   ptp_stack[2048];
27 
28 
29 #define NUM_PACKETS            24
30 #define PACKET_SIZE            1536
31 #define PACKET_POOL_SIZE       (NUM_PACKETS * (PACKET_SIZE + sizeof(NX_PACKET)))
32 
33 /* Define thread prototypes.  */
34 
35 static void    ntest_0_entry(ULONG thread_input);
36 static void    ntest_1_entry(ULONG thread_input);
37 extern void    _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req);
38 
39 
40 /* Define what the initial system looks like.  */
41 #ifdef CTEST
test_application_define(void * first_unused_memory)42 VOID test_application_define(void *first_unused_memory)
43 #else
44 void netx_ptp_client_two_steps_off_application_define(void *first_unused_memory)
45 #endif
46 {
47 CHAR       *pointer;
48 UINT       status;
49 
50     /* Print out test information banner.  */
51     printf("NetX Test:   PTP Two Steps Off Test ...................................");
52 
53 #if defined(NX_ENABLE_GPTP) || (NX_PTP_CLIENT_TRANSPORT_UDP==0)
54     printf("N/A\n");
55     test_control_return(3);
56 #else
57     /* Setup the working pointer.  */
58     pointer = (CHAR *) first_unused_memory;
59 
60     /* Create the main thread.  */
61     tx_thread_create(&ntest_0, "thread 0", ntest_0_entry, 0,
62                      pointer, DEMO_STACK_SIZE,
63                      4, 4, TX_NO_TIME_SLICE, TX_AUTO_START);
64 
65     pointer = pointer + DEMO_STACK_SIZE;
66 
67     /* Create the main thread.  */
68     tx_thread_create(&ntest_1, "thread 1", ntest_1_entry, 0,
69                      pointer, DEMO_STACK_SIZE,
70                      3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);
71 
72     pointer = pointer + DEMO_STACK_SIZE;
73 
74     /* Initialize the NetX system.  */
75     nx_system_initialize();
76 
77     /* Create a packet pool.  */
78     status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", PACKET_SIZE, pointer, PACKET_POOL_SIZE);
79     pointer = pointer + PACKET_POOL_SIZE;
80 
81     if(status)
82         ASSERT_SUCCESS(status);
83 
84     /* Create an IP instance.  */
85     status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(1, 2, 3, 4), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
86                           pointer, 2048, 1);
87     pointer = pointer + 2048;
88 
89     /* Create another IP instance.  */
90     status += nx_ip_create(&ip_1, "NetX IP Instance 1", IP_ADDRESS(1, 2, 3, 5), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver,
91                            pointer, 2048, 1);
92     pointer = pointer + 2048;
93 
94     if(status)
95         ASSERT_SUCCESS(status);
96 
97     /* Enable ARP and supply ARP cache memory for IP Instance 0.  */
98     status = nx_arp_enable(&ip_0, (void *) pointer, 1024);
99     pointer = pointer + 1024;
100 
101     /* Enable ARP and supply ARP cache memory for IP Instance 1.  */
102     status += nx_arp_enable(&ip_1, (void *) pointer, 1024);
103     pointer = pointer + 1024;
104 
105     /* Check ARP enable status.  */
106     if(status)
107         ASSERT_SUCCESS(status);
108 
109     /* Enable UDP processing for both IP instances.  */
110     status = nx_udp_enable(&ip_0);
111     status += nx_udp_enable(&ip_1);
112 
113     /* Check UDP enable status.  */
114     if(status)
115         ASSERT_SUCCESS(status);
116 #endif
117 }
118 
119 
120 /* PTP handler.  */
ptp_event_callback(NX_PTP_CLIENT * ptp_client_ptr,UINT event,VOID * event_data,VOID * callback_data)121 static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data)
122 {
123 NX_PTP_DATE_TIME date;
124 
125     NX_PARAMETER_NOT_USED(callback_data);
126 
127     switch (event)
128     {
129         case NX_PTP_CLIENT_EVENT_MASTER:
130         {
131             DBGPRINTF("new MASTER clock!\r\n");
132             break;
133         }
134 
135         case NX_PTP_CLIENT_EVENT_SYNC:
136         {
137             nx_ptp_client_sync_info_get((NX_PTP_CLIENT_SYNC *)event_data, NX_NULL, &synced_utc_offset);
138             DBGPRINTF("SYNC event: utc offset=%d\r\n", synced_utc_offset);
139 
140             /* read the PTP clock */
141             nx_ptp_client_time_get(ptp_client_ptr, &synced_time);
142 
143             /* convert PTP time to UTC date and time */
144             nx_ptp_client_utility_convert_time_to_date(&synced_time, -synced_utc_offset, &date);
145 
146             /* display the current time */
147             DBGPRINTF("ts: %d%d.%d\r\n", synced_time.second_high,
148                                          synced_time.second_low,
149                                          synced_time.nanosecond);
150             DBGPRINTF("%2u/%02u/%u %02u:%02u:%02u.%09lu\r\n", date.day, date.month, date.year,
151                                                               date.hour, date.minute, date.second,
152                                                               date.nanosecond);
153 
154             break;
155         }
156 
157         case NX_PTP_CLIENT_EVENT_TIMEOUT:
158         {
159             DBGPRINTF("Master clock TIMEOUT!\r\n");
160             break;
161         }
162         default:
163         {
164             break;
165         }
166     }
167 
168     return(0);
169 }
170 
171 /* Define the test threads.  */
ntest_0_entry(ULONG thread_input)172 static void    ntest_0_entry(ULONG thread_input)
173 {
174 UINT status;
175 NX_PTP_TIME ts_diff = {1, 1, 1};
176 
177     /* Reset synced time. */
178     memset(&synced_time, 0, sizeof(synced_time));
179     synced_utc_offset = 0xFFFF;
180 
181     /* Set expected value. */
182     expected_utc_offset = 0x1234;
183     expected_time.second_high = (delay_response_ts.second_high + sync_ts.second_high) / 2;
184     expected_time.second_low = (delay_response_ts.second_low + sync_ts.second_low) / 2;
185     expected_time.nanosecond = (delay_response_ts.nanosecond + sync_ts.nanosecond) / 2;
186 
187     /* Create the PTP client instance */
188     status = nx_ptp_client_create(&ptp_client, &ip_0, 0, &pool_0,
189                                   2, ptp_stack, sizeof(ptp_stack),
190                                   nx_ptp_client_soft_clock_callback, NX_NULL);
191     ASSERT_SUCCESS(status);
192 
193     /* start the PTP client */
194     status = nx_ptp_client_start(&ptp_client, NX_NULL, 0, 0, 0, ptp_event_callback, NX_NULL);
195     ASSERT_SUCCESS(status);
196 
197     /* Sleep 5 seconds for sync up. */
198     tx_thread_sleep(5 * NX_IP_PERIODIC_RATE);
199 
200     /* Compare synced time. */
201     ASSERT_TRUE(synced_utc_offset == expected_utc_offset);
202     status = nx_ptp_client_utility_time_diff(&synced_time, &expected_time, &ts_diff);
203     ASSERT_SUCCESS(status);
204     ASSERT_TRUE(ts_diff.second_high == 0);
205     ASSERT_TRUE(ts_diff.second_low == 0);
206     ASSERT_TRUE(ts_diff.nanosecond / 1000000 <= 1000 / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND);
207 
208     printf("SUCCESS!\n");
209     test_control_return(0);
210 }
211 
212 /* This thread acts as PTP server, accepting the connection. */
ntest_1_entry(ULONG thread_input)213 static void    ntest_1_entry(ULONG thread_input)
214 {
215 DELAY_REQUEST_CONTEXT context;
216 UINT status;
217 
218     create_socket(&ip_1, &generic_socket, PTP_GENERAL_UDP_PORT);
219     create_socket(&ip_1, &event_socket, PTP_EVENT_UDP_PORT);
220 
221     /* Sleep 1 second to wait for PTP thread running. */
222     tx_thread_sleep(1 * NX_IP_PERIODIC_RATE);
223 
224     /* Set two steps off.  */
225     set_two_steps(NX_FALSE);
226 
227     /* Send announce.  */
228     send_announce(&generic_socket, &pool_0, expected_utc_offset);
229 
230     /* Send sync.  */
231     send_sync(&event_socket, &pool_0, &sync_ts);
232 
233     /* Wait for delay request.  */
234     status = receive_delay_request(&event_socket, &context, NX_WAIT_FOREVER);
235     ASSERT_SUCCESS(status);
236 
237     /* Send delay response.  */
238     send_delay_response(&generic_socket, &pool_0, &context, &delay_response_ts);
239 }