1 /*-----------------------------------------------------------------------------
3 * Purpose: Ethernet test cases
4 *----------------------------------------------------------------------------
5 * Copyright(c) KEIL - An ARM Company
6 *----------------------------------------------------------------------------*/
9 #include "DV_Framework.h"
10 #include "Driver_ETH_MAC.h"
11 #include "Driver_ETH_PHY.h"
16 // Ethernet PTP time definitions
17 #define PTP_S_NS 1000000000U
18 #define PTP_TIME_REF ETH_PTP_TIME_REF
19 #define PTP_TIME_REF_NS ETH_PTP_TIME_REF*1000000U
21 // Ethernet buffer pointers
22 static uint8_t *buffer_out;
23 static uint8_t *buffer_in;
25 // Register Driver_ETH_MAC# Driver_ETH_PHY#
26 extern ARM_DRIVER_ETH_MAC CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
27 extern ARM_DRIVER_ETH_PHY CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
28 static ARM_DRIVER_ETH_MAC* eth_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
29 static ARM_DRIVER_ETH_PHY* eth_phy = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
30 static ARM_ETH_MAC_CAPABILITIES capab;
33 static uint8_t volatile Event;
36 static void ETH_DrvEvent (uint32_t event) {
41 int8_t ETH_RunTransfer (uint8_t *out, uint8_t *in, uint32_t cnt);
42 int8_t ETH_RunTransfer (uint8_t *out, uint8_t *in, uint32_t cnt) {
45 Event &= ~ARM_ETH_MAC_EVENT_RX_FRAME;
47 eth_mac->SendFrame (out, cnt, 0);
51 if ((Event & ARM_ETH_MAC_EVENT_RX_FRAME) || (eth_mac->GetRxFrameSize() != 0)) {
52 eth_mac->ReadFrame (in, BUFFER[BUFFER_NUM-1]);
56 while ((GET_SYSTICK() - tick) < SYSTICK_MICROSEC(ETH_TRANSFER_TIMEOUT));
62 /*-----------------------------------------------------------------------------
64 *----------------------------------------------------------------------------*/
66 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
68 \defgroup eth_funcs Ethernet Validation
69 \brief Ethernet test cases
71 The Ethernet validation test performs the following checks:
72 - API interface compliance.
73 - Data communication with various transfer sizes and communication parameters.
74 - Loopback communication.
77 Loopback Communication Setup
78 ----------------------------
80 To perform loopback communication tests, it is required to connect the RX and TX lines of the Ethernet cable together:
82 - TX+ (Pin 1) with RX+ (Pin 3) and
83 - TX- (Pin 2) with RX- (Pin 6)
85 \image html ethernet_loopback.png
87 Various \b Ethernet \b loopback \b plugs are available from different vendors that fulfill this purpose.
92 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
94 \brief Test case: ETH_MAC_GetCapabilities
96 The test case \b ETH_MAC_GetCapabilities verifies the Ethernet MAC function \b GetCapabilities.
98 void ETH_MAC_GetCapabilities (void) {
99 /* Get ETH_MAC capabilities */
100 capab = eth_mac->GetCapabilities();
101 ASSERT_TRUE(&capab != NULL);
104 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
106 \brief Test case: ETH_MAC_Initialization
108 The test case \b ETH_MAC_Initialization verifies the Ethernet MAC functions in the following order:
109 - \b Initialize without callback
111 - \b Initialize with callback if supported
114 void ETH_MAC_Initialization (void) {
116 /* Initialize without callback */
117 ASSERT_TRUE(eth_mac->Initialize(NULL) == ARM_DRIVER_OK);
120 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
122 /* Initialize with callback if supported */
123 ASSERT_TRUE(eth_mac->Initialize((capab.event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
126 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
129 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
131 \brief Test case: ETH_MAC_CheckInvalidInit
133 The test case \b ETH_MAC_CheckInvalidInit verifies the driver behaviour when receiving an invalid initialization sequence:
135 - \b PowerControl with Power off
136 - \b PowerControl with Power on
138 - \b PowerControl with Power off
141 void ETH_MAC_CheckInvalidInit (void) {
144 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
147 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
149 /* Try to power on */
150 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) != ARM_DRIVER_OK);
152 /* Try to set configuration */
153 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
154 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL )!= ARM_DRIVER_OK);
157 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
160 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
163 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
165 \brief Test case: ETH_MAC_PowerControl
167 The test case \b ETH_MAC_PowerControl verifies the Ethernet MAC \b PowerControl function with the sequence:
170 - Set bus speed \token{10M}
171 - Set bus speed \token{100M}
172 - Set bus speed \token{1G}
176 void ETH_MAC_PowerControl (void) {
179 /* Initialize with callback if supported */
180 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
183 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
186 val = eth_mac->PowerControl (ARM_POWER_LOW);
187 if (val == ARM_DRIVER_ERROR_UNSUPPORTED) { SET_RESULT(WARNING, "Low power is not supported"); }
188 else { ASSERT_TRUE(val == ARM_DRIVER_OK); }
191 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
194 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
197 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
199 \brief Test case: ETH_MAC_SetBusSpeed
201 The test case \b ETH_MAC_SetBusSpeed verifies the Ethernet MAC \b Control function with the sequence:
204 - Set bus speed \token{10M}
205 - Set bus speed \token{100M}
206 - Set bus speed \token{1G}
210 void ETH_MAC_SetBusSpeed (void) {
213 /* Initialize with callback if supported and power on*/
214 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
215 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
217 /* Set bus speed 10M */
218 val = eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_SPEED_10M);
219 if (val == ARM_DRIVER_ERROR_UNSUPPORTED) { SET_RESULT(WARNING, "Link speed 10M is not supported"); }
220 else { ASSERT_TRUE(val == ARM_DRIVER_OK); }
222 /* Set bus speed 100M */
223 val = eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_SPEED_100M);
224 if (val == ARM_DRIVER_ERROR_UNSUPPORTED) { SET_RESULT(WARNING, "Link speed 100M is not supported"); }
225 else { ASSERT_TRUE(val == ARM_DRIVER_OK); }
227 /* Set bus speed 1G */
228 val = eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_SPEED_1G);
229 if (val == ARM_DRIVER_ERROR_UNSUPPORTED) { SET_RESULT(WARNING, "Link speed 1G is not supported"); }
230 else { ASSERT_TRUE(val == ARM_DRIVER_OK); }
232 /* Power off and uninitialize */
233 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
234 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
237 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
239 \brief Test case: ETH_MAC_Config_Mode
241 The test case \b ETH_MAC_Config_Mode verifies the Ethernet MAC \b Control function with the sequence:
249 void ETH_MAC_Config_Mode (void) {
251 /* Initialize with callback if supported and power on*/
252 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
253 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
255 /* Set full duplex */
256 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_DUPLEX_FULL)== ARM_DRIVER_OK);
258 /* Set half duplex */
259 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_DUPLEX_HALF)== ARM_DRIVER_OK);
261 /* Power off and uninitialize */
262 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
263 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
266 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
268 \brief Test case: ETH_MAC_Config_CommonParams
270 The test case \b ETH_MAC_Config_CommonParams verifies the Ethernet MAC \b Control function with the sequence:
273 - Configure Ethernet MAC bus
275 - Configure transmitter
279 void ETH_MAC_Config_CommonParams (void) {
281 /* Initialize with callback if supported and power on*/
282 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
283 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
285 /* Configure ETH_MAC bus*/
286 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
287 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
289 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
291 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
293 /* Power off and uninitialize */
294 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
295 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
298 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
300 \brief Test case: ETH_PHY_Initialization
302 The test case \b ETH_PHY_Initialization verifies the Ethernet PHY functions in the following order:
303 - \b Initialize with read and write functions
305 void ETH_PHY_Initialization (void) {
307 /* MAC Initialize and power on */
308 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
309 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
312 ASSERT_TRUE(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
315 ASSERT_TRUE(eth_phy->Uninitialize() == ARM_DRIVER_OK);
317 /* MAC Power off and uninitialize */
318 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
319 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
322 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
324 \brief Test case: ETH_PHY_CheckInvalidInit
326 The test case \b ETH_PHY_CheckInvalidInit verifies the driver behaviour when receiving an invalid initialization sequence:
328 - \b PowerControl with Power off
329 - \b PowerControl with Power on
330 - \b SetInterface to configure the Ehternet PHY bus
331 - \b SetMode to configure the Ehternet PHY bus
332 - \b PowerControl with Power off
335 void ETH_PHY_CheckInvalidInit (void) {
338 ASSERT_TRUE(eth_phy->Uninitialize() == ARM_DRIVER_OK);
341 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
344 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_FULL) != ARM_DRIVER_OK);
346 /* Try to configure ETH_PHY bus*/
347 ASSERT_TRUE(eth_phy->SetInterface (capab.media_interface) != ARM_DRIVER_OK);
348 ASSERT_TRUE(eth_phy->SetMode (ARM_ETH_PHY_AUTO_NEGOTIATE) != ARM_DRIVER_OK);
350 /* Try to initialize without read and write functions */
351 ASSERT_TRUE(eth_phy->Initialize(NULL, NULL) != ARM_DRIVER_OK);
354 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
357 ASSERT_TRUE(eth_phy->Uninitialize() == ARM_DRIVER_OK);
360 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
362 \brief Test case: ETH_PHY_PowerControl
364 The test case \b ETH_PHY_PowerControl verifies the Ethernet PHY \b PowerControl function with the sequence:
371 void ETH_PHY_PowerControl (void) {
374 /* MAC Initialize and power on */
375 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
376 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
379 ASSERT_TRUE(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
382 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
385 val = eth_phy->PowerControl (ARM_POWER_LOW);
386 if (val == ARM_DRIVER_ERROR_UNSUPPORTED) { SET_RESULT(WARNING, "Low power is not supported"); }
387 else { ASSERT_TRUE(val == ARM_DRIVER_OK); }
390 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
393 ASSERT_TRUE(eth_phy->Uninitialize() == ARM_DRIVER_OK);
395 /* MAC Power off and uninitialize */
396 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
397 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
400 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
402 \brief Test case: ETH_PHY_Config
404 The test case \b ETH_PHY_Config verifies the PHY functions
412 void ETH_PHY_Config (void) {
414 /* MAC Initialize and power on*/
415 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
416 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
418 /* Initialize and power on*/
419 ASSERT_TRUE(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
420 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
422 /* Configure ETH_PHY bus*/
423 ASSERT_TRUE(eth_phy->SetInterface (capab.media_interface) == ARM_DRIVER_OK);
425 ASSERT_TRUE(eth_phy->SetMode (ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
427 /* Power off and uninitialize */
428 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
429 ASSERT_TRUE(eth_phy->Uninitialize() == ARM_DRIVER_OK);
431 /* MAC Power off and uninitialize */
432 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
433 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
436 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
438 \brief Test case: ETH_Loopback_Transfer
440 The test case \b ETH_Loopback_Transfer verifies data transfer via Ehernet with the following sequence:
444 - Ethernet connection
445 - Set output buffer pattern
446 - Transfer data chunks
447 - Set output buffer with random data
448 - Transfer data chunks
452 void ETH_Loopback_Transfer (void) {
454 uint8_t pattern[] = BUFFER_PATTERN;
458 /* Allocate buffer */
459 buffer_out = (uint8_t*) malloc(BUFFER[BUFFER_NUM-1]*sizeof(uint8_t));
460 ASSERT_TRUE(buffer_out != NULL);
461 buffer_in = (uint8_t*) malloc(BUFFER[BUFFER_NUM-1]*sizeof(uint8_t));
462 ASSERT_TRUE(buffer_in != NULL);
464 /* Initialize, power on and configure MAC and PHY */
465 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
466 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
467 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
468 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
469 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
470 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
471 ASSERT_TRUE(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
472 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
473 ASSERT_TRUE(eth_phy->SetInterface (capab.media_interface) == ARM_DRIVER_OK);
474 ASSERT_TRUE(eth_phy->SetMode (ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
476 /* Check Ethernet link*/
477 tick = GET_SYSTICK();
478 while (eth_phy->GetLinkState() != ARM_ETH_LINK_UP) {
479 if ((GET_SYSTICK() - tick) >= SYSTICK_MICROSEC(ETH_LINK_TIMEOUT)) {
480 SET_RESULT(FAILED, "Link is broken, connect Ethernet cable");
485 /* Set output buffer pattern*/
486 for (cnt = 0; cnt<BUFFER[BUFFER_NUM-1];) {
487 for (i = 0; i<ARRAY_SIZE(pattern); i++) {
488 buffer_out[cnt++] = pattern[i];
492 /* Transfer data chunks */
493 for (cnt = 0; cnt<BUFFER_NUM; cnt++) {
494 /* Clear input buffer*/
495 memset(buffer_in,0,BUFFER[cnt]);
496 if (ETH_RunTransfer(buffer_out, buffer_in, BUFFER[cnt]) != ARM_DRIVER_OK) {
497 sprintf(str,"Fail to transfer block of %d bytes",BUFFER[cnt]);
498 SET_RESULT(FAILED, str);
499 } else SET_RESULT(PASSED, NULL);
500 if (memcmp(buffer_in, buffer_out, BUFFER[cnt])!=0) {
501 sprintf(str,"Fail to check block of %d bytes",BUFFER[cnt]);
502 SET_RESULT(FAILED, str);
503 } else SET_RESULT(PASSED, NULL);
506 /* Set output buffer with random data*/
507 srand(GET_SYSTICK());
508 for (cnt = 0; cnt<BUFFER[BUFFER_NUM-1]; cnt++) {
509 buffer_out[cnt] = (uint8_t)rand();
512 /* Transfer data chunks */
513 for (cnt = 0; cnt<BUFFER_NUM; cnt++) {
514 /* Clear input buffer*/
515 memset(buffer_in,0,BUFFER[cnt]);
516 if (ETH_RunTransfer(buffer_out, buffer_in, BUFFER[cnt]) != ARM_DRIVER_OK) {
517 sprintf(str,"Fail to transfer block of %d bytes",BUFFER[cnt]);
518 SET_RESULT(FAILED, str);
519 } else SET_RESULT(PASSED, NULL);
520 if (memcmp(buffer_in, buffer_out, BUFFER[cnt])!=0) {
521 sprintf(str,"Fail to check block of %d bytes",BUFFER[cnt]);
522 SET_RESULT(FAILED, str);
523 } else SET_RESULT(PASSED, NULL);
526 /* Power off and uninitialize */
527 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
528 ASSERT_TRUE(eth_phy->Uninitialize() == ARM_DRIVER_OK);
529 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
530 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
537 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
539 \brief Test case: ETH_MAC_PTP_ControlTimer
541 The test case \b ETH_MAC_PTP_ControlTimer verifies the PTP ControlTimer function with the sequence:
552 void ETH_MAC_PTP_ControlTimer (void) {
553 ARM_ETH_MAC_TIME time1, time2;
554 int64_t t1ns, t2ns, t, overhead;
558 /* Get capabilities */
559 if (!eth_mac->GetCapabilities().precision_timer) {
560 SET_RESULT(WARNING, "Precision Time Protocol is not supported");
562 /* Initialize, power on and configure MAC */
563 ASSERT_TRUE(eth_mac->Initialize(ETH_DrvEvent) == ARM_DRIVER_OK);
564 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
566 /* Set Time -------------------------------------------------------------------------------- */
569 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_TIME, &time1) == ARM_DRIVER_OK);
571 /* Check System Time */
573 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
574 osDelay(PTP_TIME_REF);
575 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
577 /* Get timestamps in nanoseconds */
578 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
579 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
580 t = t2ns - t1ns - PTP_TIME_REF_NS;
582 /* Check timestamps difference */
583 if (llabs(t)>ETH_PTP_TOLERANCE) {
584 sprintf(str,"PTP measured time is %lldns from expected", t);
585 SET_RESULT(WARNING, str);
586 } else SET_RESULT(PASSED, NULL);
588 /* Adjust clock - Set correction factor ---------------------------------------------------- */
589 /* Calculate rate and convert it to q31 format */
590 rate = (double)PTP_TIME_REF_NS/(t2ns-t1ns);
591 time1.ns = (uint32_t)(0x80000000U*rate);
592 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_ADJUST_CLOCK, &time1) == ARM_DRIVER_OK);
594 /* Check System Time after adjusting clock */
596 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
597 osDelay(PTP_TIME_REF);
598 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
600 /* Get timestamps in nanoseconds */
601 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
602 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
603 t = t2ns - t1ns - PTP_TIME_REF_NS;
605 /* Check timestamps difference */
606 if (llabs(t)>ETH_PTP_TOLERANCE) {
607 sprintf(str,"PTP measured time with adj clk is %lldns from expected", t);
608 SET_RESULT(WARNING, str);
609 } else SET_RESULT(PASSED, NULL);
611 /* Measure time overhead for increment/decrement calls ------------------------------------- */
614 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
615 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_INC_TIME, &time2) == ARM_DRIVER_OK);
616 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
617 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
618 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
619 overhead = t2ns - t1ns;
621 /* Increment time -------------------------------------------------------------------------- */
622 time2.sec = PTP_TIME_REF/1000U;
623 time2.ns = (PTP_TIME_REF-time2.sec*1000U)*1000000U;
624 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
625 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_INC_TIME, &time2) == ARM_DRIVER_OK);
626 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
628 /* Get timestamps in nanoseconds */
629 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
630 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
631 t = t2ns - t1ns - PTP_TIME_REF_NS - overhead;
633 /* Check timestamps difference */
634 if (llabs(t)>ETH_PTP_TOLERANCE) {
635 sprintf(str,"PTP incremented time is %lldns from expected", t);
636 SET_RESULT(WARNING, str);
637 } else SET_RESULT(PASSED, NULL);
639 /* Decrement time -------------------------------------------------------------------------- */
640 time2.sec = PTP_TIME_REF/1000U;
641 time2.ns = (PTP_TIME_REF-time2.sec*1000U)*1000000U;
642 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
643 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_DEC_TIME, &time2) == ARM_DRIVER_OK);
644 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
646 /* Get timestamps in nanoseconds */
647 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
648 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
649 t = t2ns - t1ns + PTP_TIME_REF_NS - overhead;
651 /* Check timestamps difference */
652 if (llabs(t)>ETH_PTP_TOLERANCE) {
653 sprintf(str,"PTP decremented time is %lldns from expected", t);
654 SET_RESULT(WARNING, str);
655 } else SET_RESULT(PASSED, NULL);
657 /* Set Alarm (1s) -------------------------------------------------------------------------- */
658 Event &= ~ARM_ETH_MAC_EVENT_TIMER_ALARM;
659 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
661 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_ALARM, &time1) == ARM_DRIVER_OK);
663 /* Check alarm event after 999ms */
665 if ((Event & ARM_ETH_MAC_EVENT_TIMER_ALARM) != 0) {
666 SET_RESULT(FAILED, "PTP Alarm event triggered too early");
667 } else SET_RESULT(PASSED, NULL);
669 /* Check alarm event after 1001ms */
671 if ((Event & ARM_ETH_MAC_EVENT_TIMER_ALARM) == 0) {
672 SET_RESULT(FAILED, "PTP Alarm event timeout");
673 } else SET_RESULT(PASSED, NULL);
675 /* Power off and uninitialize */
676 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
677 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
681 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
683 \brief Test case: ETH_Loopback_PTP
685 The test case \b ETH_Loopback_PTP verifies the Precision Time Protocol functions ControlTimer, GetRxFrameTime and
686 GetTxFrameTime with the sequence:
696 void ETH_Loopback_PTP (void) {
697 ARM_ETH_MAC_TIME time1, time2;
700 // PTP over Ethernet IPv4 sample frame
701 const uint8_t PTP_frame[] = {
702 0x01, 0x00, 0x5e, 0x00, 0x01, 0x81, 0x00, 0x30, 0x05, 0x1d, 0x1e, 0x27, 0x08, 0x00, 0x45, 0x00,
703 0x00, 0x98, 0x00, 0x5d, 0x40, 0x00, 0x01, 0x11, 0x29, 0x68, 0x0a, 0x0a, 0x64, 0x05, 0xe0, 0x00,
704 0x01, 0x81, 0x01, 0x3f, 0x01, 0x3f, 0x00, 0x84, 0xc0, 0x7b, 0x00, 0x01, 0x00, 0x01, 0x5f, 0x44,
705 0x46, 0x4c, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
706 0x00, 0x30, 0x05, 0x1d, 0x1e, 0x27, 0x00, 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
707 0x00, 0x00, 0x45, 0x5b, 0x0a, 0x38, 0x0e, 0xb9, 0x26, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
708 0x00, 0x30, 0x05, 0x1d, 0x1e, 0x27, 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x04, 0x44, 0x46,
709 0x4c, 0x54, 0x00, 0x00, 0xf0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
710 0xf0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x44, 0x46, 0x4c, 0x54, 0x00, 0x01,
711 0x00, 0x30, 0x05, 0x1d, 0x1e, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
712 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
714 const uint32_t PTP_frame_len = sizeof(PTP_frame);
716 /* Get capabilities */
717 if (!eth_mac->GetCapabilities().precision_timer) {
718 SET_RESULT(WARNING, "Precision Time Protocol is not supported");
720 /* Allocate buffer */
721 buffer_in = (uint8_t*) malloc(PTP_frame_len*sizeof(uint8_t));
722 ASSERT_TRUE(buffer_in != NULL);
724 /* Initialize, power on and configure MAC and PHY */
725 ASSERT_TRUE(eth_mac->Initialize((eth_mac->GetCapabilities().event_rx_frame) ? ETH_DrvEvent : NULL) == ARM_DRIVER_OK);
726 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
727 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONFIGURE, ARM_ETH_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
728 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
729 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
730 ASSERT_TRUE(eth_mac->Control (ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
731 ASSERT_TRUE(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
732 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_FULL) == ARM_DRIVER_OK);
733 ASSERT_TRUE(eth_phy->SetInterface (capab.media_interface) == ARM_DRIVER_OK);
734 ASSERT_TRUE(eth_phy->SetMode (ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
739 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_TIME, &time1) == ARM_DRIVER_OK);
741 /* Check timestamps - verify if control timer is running */
742 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
743 ASSERT_TRUE(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
744 ASSERT_TRUE((time2.sec==time1.sec)?(time2.ns>time1.ns):(time2.sec>time1.sec));
746 /* Check Ethernet link */
747 tick = GET_SYSTICK();
748 while (eth_phy->GetLinkState() != ARM_ETH_LINK_UP) {
749 if ((GET_SYSTICK() - tick) >= SYSTICK_MICROSEC(ETH_LINK_TIMEOUT)) {
750 SET_RESULT(FAILED, "Link is broken, connect Ethernet cable");
756 ASSERT_TRUE(eth_mac->SendFrame (PTP_frame, PTP_frame_len, ARM_ETH_MAC_TX_FRAME_TIMESTAMP) == ARM_DRIVER_OK);
757 tick = GET_SYSTICK();
758 while (eth_mac->GetRxFrameSize() == 0) {
759 if ((GET_SYSTICK() - tick) >= SYSTICK_MICROSEC(ETH_TRANSFER_TIMEOUT)) {
760 SET_RESULT(FAILED, "Transfer timeout");
765 /* Get TX Frame Time */
766 ASSERT_TRUE(eth_mac->GetTxFrameTime(&time1) == ARM_DRIVER_OK);
768 /* Get RX Frame Time */
769 ASSERT_TRUE(eth_mac->GetRxFrameTime(&time2) == ARM_DRIVER_OK);
771 /* Check timestamps */
772 ASSERT_TRUE((time2.sec==time1.sec)?(time2.ns>time1.ns):(time2.sec>time1.sec));
775 eth_mac->ReadFrame(buffer_in, PTP_frame_len);
776 ASSERT_TRUE(memcmp(buffer_in, PTP_frame, PTP_frame_len) == 0);
778 /* Power off and uninitialize */
779 ASSERT_TRUE(eth_phy->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
780 ASSERT_TRUE(eth_phy->Uninitialize() == ARM_DRIVER_OK);
781 ASSERT_TRUE(eth_mac->PowerControl (ARM_POWER_OFF) == ARM_DRIVER_OK);
782 ASSERT_TRUE(eth_mac->Uninitialize() == ARM_DRIVER_OK);
793 // end of group eth_funcs