2 * Copyright (c) 2015-2023 Arm Limited. All rights reserved.
4 * SPDX-License-Identifier: Apache-2.0
6 * Licensed under the Apache License, Version 2.0 (the License); you may
7 * not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * -----------------------------------------------------------------------------
20 * Project: CMSIS-Driver Validation
21 * Title: Ethernet (ETH) Driver Validation tests
23 * -----------------------------------------------------------------------------
31 #include "DV_ETH_Config.h"
32 #include "DV_Framework.h"
34 #include "Driver_ETH_MAC.h"
35 #include "Driver_ETH_PHY.h"
38 #error Please update DV_ETH_Config.h
43 // Ethernet PTP time definitions
44 #define PTP_S_NS 1000000000U
45 #define PTP_TIME_REF ETH_PTP_TIME_REF
46 #define PTP_TIME_REF_NS ETH_PTP_TIME_REF*1000000U
48 static const ARM_ETH_MAC_ADDR mac_addr = {0x02, 0x30, 0x05, 0x1D, 0x1E, 0x27};
49 static const ARM_ETH_MAC_ADDR mac_bcast = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
50 static const ARM_ETH_MAC_ADDR mac_mcast[6] ={{0x01, 0x00, 0x5E, 0x00, 0x00, 0x01},
51 {0x01, 0x00, 0x5E, 0x00, 0x00, 0x02},
52 {0x01, 0x00, 0x5E, 0x7F, 0xFF, 0xFF},
53 {0x33, 0x33, 0x00, 0x00, 0x00, 0x01},
54 {0x33, 0x33, 0x00, 0x00, 0x00, 0x02},
55 {0x33, 0x33, 0xFF, 0xFF, 0xFF, 0xFF}};
57 // Register Driver_ETH_MAC# Driver_ETH_PHY#
58 extern ARM_DRIVER_ETH_MAC CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
59 extern ARM_DRIVER_ETH_PHY CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
61 static ARM_DRIVER_ETH_MAC *eth_mac;
62 static ARM_DRIVER_ETH_PHY *eth_phy;
63 static ARM_ETH_MAC_CAPABILITIES capab;
64 static ARM_ETH_MAC_SignalEvent_t cb_event;
67 static volatile uint8_t phy_power;
68 static volatile uint8_t mac_lockup;
71 // Allocated buffer pointers
72 static uint8_t *buffer_out;
73 static uint8_t *buffer_in;
76 static uint8_t volatile Event;
79 static void ETH_DrvEvent (uint32_t event) {
84 static int32_t ETH_RunTransfer (const uint8_t *out, uint8_t *in, uint32_t len, uint32_t frag) {
87 Event &= ~ARM_ETH_MAC_EVENT_RX_FRAME;
89 // Send the entire frame at once
90 eth_mac->SendFrame(out, len, 0);
93 // Split the frame into two fragments
94 eth_mac->SendFrame(out, frag, ARM_ETH_MAC_TX_FRAME_FRAGMENT);
95 eth_mac->SendFrame(out+frag, len-frag, 0);
100 // Wait for RX event or run the polling mode
101 if ((Event & ARM_ETH_MAC_EVENT_RX_FRAME) || !capab.event_rx_frame) {
102 size = eth_mac->GetRxFrameSize();
104 eth_mac->ReadFrame(in, size);
105 return ARM_DRIVER_OK;
109 while ((GET_SYSTICK() - tick) < SYSTICK_MICROSEC(ETH_TRANSFER_TIMEOUT*1000));
111 return ARM_DRIVER_ERROR;
114 // Initialize MAC driver wrapper for RMII interface
115 static int32_t mac_initialize (ARM_ETH_MAC_SignalEvent_t cb_event) {
116 ARM_DRIVER_ETH_MAC *drv_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
119 return drv_mac->Initialize(cb_event);
122 // Uninitialize MAC driver wrapper for RMII interface
123 static int32_t mac_uninitialize (void) {
124 ARM_DRIVER_ETH_MAC *drv_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
127 return drv_mac->Uninitialize();
130 // MAC driver power control wrapper for RMII interface
131 static int32_t mac_power_control (ARM_POWER_STATE state) {
132 ARM_DRIVER_ETH_MAC *drv_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
133 ARM_DRIVER_ETH_PHY *drv_phy = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
136 retv = drv_mac->PowerControl(state);
137 if ((state == ARM_POWER_FULL) && (retv == ARM_DRIVER_ERROR) && (phy_power == 1U)) {
138 /* RMII solution when the PHY is a 50 MHz reference clock source */
139 /* MAC never exits soft reset when PHY is powered down (no 50 MHz) */
140 /* So turn on the power for the PHY here to prevent deadlock */
141 drv_phy->Initialize(drv_mac->PHY_Read, drv_mac->PHY_Write);
142 if (drv_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK) {
145 retv = drv_mac->PowerControl(state);
146 if (retv == ARM_DRIVER_OK) {
147 /* RMII lockup detected */
155 // PHY driver power control wrapper for RMII interface
156 static int32_t phy_power_control (ARM_POWER_STATE state) {
157 ARM_DRIVER_ETH_PHY *drv_phy = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
160 retv = drv_phy->PowerControl(state);
161 if ((state == ARM_POWER_OFF) && (retv == ARM_DRIVER_OK) && (phy_power == 2U)) {
167 /* Helper function that is called before tests start executing */
168 void ETH_DV_Initialize (void) {
169 static struct _ARM_DRIVER_ETH_MAC s_mac;
170 static struct _ARM_DRIVER_ETH_PHY s_phy;
172 eth_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
173 eth_phy = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
174 capab = eth_mac->GetCapabilities();
175 if (capab.media_interface == ARM_ETH_INTERFACE_RMII) {
176 memcpy(&s_mac, eth_mac, sizeof(s_mac));
177 memcpy(&s_phy, eth_phy, sizeof(s_phy));
178 /* Use wrapper functions in RMII interface mode */
179 s_mac.Initialize = &mac_initialize;
180 s_mac.Uninitialize = &mac_uninitialize;
181 s_mac.PowerControl = &mac_power_control;
182 s_phy.PowerControl = &phy_power_control;
188 cb_event = (capab.event_rx_frame) ? ETH_DrvEvent : NULL;
191 /* Helper function that is called after tests stop executing */
192 void ETH_DV_Uninitialize (void) {
193 eth_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
194 eth_phy = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
198 /*-----------------------------------------------------------------------------
200 *----------------------------------------------------------------------------*/
202 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
204 \defgroup dv_eth Ethernet Validation
205 \brief Ethernet driver validation
207 The Ethernet validation test performs the following checks:
208 - API interface compliance.
209 - Data communication with various transfer sizes and communication parameters.
210 - Loopback communication.
213 Loopback Communication Setup
214 ----------------------------
216 To perform loopback communication tests, it is required to connect the RX and TX lines of the Ethernet cable together:
218 - TX+ (Pin 1) with RX+ (Pin 3) and
219 - TX- (Pin 2) with RX- (Pin 6)
221 \image html ethernet_loopback.png
223 Various \b Ethernet \b loopback \b plugs are available from different vendors that fulfill this purpose.
225 \defgroup eth_tests Tests
231 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
233 \brief Function: Function ETH_MAC_GetVersion
235 The function \b ETH_MAC_GetVersion verifies the Ethernet MAC \b GetVersion function.
237 void ETH_MAC_GetVersion (void) {
238 ARM_DRIVER_VERSION ver;
240 ver = eth_mac->GetVersion();
242 TEST_ASSERT((ver.api >= ARM_DRIVER_VERSION_MAJOR_MINOR(1UL,0UL)) && (ver.drv >= ARM_DRIVER_VERSION_MAJOR_MINOR(1UL,0UL)));
244 snprintf(str,sizeof(str),"[INFO] API version %d.%d, Driver version %d.%d",(ver.api>>8),(ver.api&0xFFU),(ver.drv>>8),(ver.drv&0xFFU));
248 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
250 \brief Function: ETH_MAC_GetCapabilities
252 The function \b ETH_MAC_GetCapabilities verifies the Ethernet MAC \b GetCapabilities function.
254 void ETH_MAC_GetCapabilities (void) {
255 ARM_ETH_MAC_CAPABILITIES cap;
257 /* Get ETH_MAC capabilities */
258 cap = eth_mac->GetCapabilities();
260 TEST_ASSERT_MESSAGE((cap.reserved == 0U), "[FAILED] Capabilities reserved field must be 0");
263 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
265 \brief Function: ETH_MAC_Initialization
267 The function \b ETH_MAC_Initialization verifies the Ethernet MAC functions in the following order:
268 - \b Initialize without callback
270 - \b Initialize with callback if supported
273 void ETH_MAC_Initialization (void) {
275 /* Initialize without callback */
276 TEST_ASSERT(eth_mac->Initialize(NULL) == ARM_DRIVER_OK);
279 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
281 /* Initialize with callback if supported */
282 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
285 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
288 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
290 \brief Function: ETH_MAC_CheckInvalidInit
292 The function \b ETH_MAC_CheckInvalidInit verifies the driver behavior when receiving an invalid initialization sequence:
294 - \b PowerControl with Power off
295 - \b PowerControl with Power on
297 - \b PowerControl with Power off
300 void ETH_MAC_CheckInvalidInit (void) {
303 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
306 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
308 /* Try to power on */
309 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) != ARM_DRIVER_OK);
311 /* Try to set configuration */
312 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
313 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL) != ARM_DRIVER_OK);
316 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
319 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
322 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
324 \brief Function: ETH_MAC_PowerControl
326 The function \b ETH_MAC_PowerControl verifies the Ethernet MAC \b PowerControl function with the sequence:
333 void ETH_MAC_PowerControl (void) {
336 /* Initialize with callback if supported */
337 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
340 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
343 retv = eth_mac->PowerControl(ARM_POWER_LOW);
344 if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Low power is not supported"); }
345 else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
348 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
351 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
354 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
356 \brief Function: ETH_MAC_MacAddress
358 The function \b ETH_MAC_MacAddress verifies the Ethernet MAC \b GetMacAddress and \b SetMacAddress functions
362 - Set Ethernet MAC Address
363 - Get Ethernet MAC Address
367 void ETH_MAC_MacAddress (void) {
368 ARM_ETH_MAC_ADDR my_addr;
370 /* Initialize with callback if supported and power on */
371 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
372 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
374 /* Set MAC Address */
375 TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
377 /* Verify MAC Address */
378 memset(&my_addr, 0, 6);
379 TEST_ASSERT(eth_mac->GetMacAddress(&my_addr) == ARM_DRIVER_OK);
380 if (memcmp(&mac_addr, &my_addr, 6) != 0) {
381 TEST_FAIL_MESSAGE("[FAILED] Verify MAC address");
385 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
388 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
391 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
393 \brief Function: ETH_MAC_SetBusSpeed
395 The function \b ETH_MAC_SetBusSpeed verifies the Ethernet MAC \b Control function with the sequence:
398 - Set bus speed \token{10M}
399 - Set bus speed \token{100M}
400 - Set bus speed \token{1G}
404 void ETH_MAC_SetBusSpeed (void) {
407 /* Initialize with callback if supported and power on */
408 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
409 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
411 /* Set bus speed 10M */
412 retv = eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_10M);
413 if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Link speed 10M is not supported"); }
414 else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
416 /* Set bus speed 100M */
417 retv = eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M);
418 if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Link speed 100M is not supported"); }
419 else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
421 /* Set bus speed 1G */
422 retv = eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_1G);
423 if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Link speed 1G is not supported"); }
424 else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
426 /* Power off and uninitialize */
427 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
428 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
431 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
433 \brief Function: ETH_MAC_Config_Mode
435 The function \b ETH_MAC_Config_Mode verifies the Ethernet MAC \b Control function with the sequence:
443 void ETH_MAC_Config_Mode (void) {
445 /* Initialize with callback if supported and power on */
446 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
447 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
449 /* Set full duplex */
450 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_DUPLEX_FULL) == ARM_DRIVER_OK);
452 /* Set half duplex */
453 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_DUPLEX_HALF) == ARM_DRIVER_OK);
455 /* Power off and uninitialize */
456 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
457 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
460 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
462 \brief Function: ETH_MAC_Config_CommonParams
464 The function \b ETH_MAC_Config_CommonParams verifies the Ethernet MAC \b Control function with the sequence:
467 - Configure Ethernet MAC bus
469 - Configure transmitter
473 void ETH_MAC_Config_CommonParams (void) {
475 /* Initialize with callback if supported and power on */
476 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
477 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
479 /* Configure ETH_MAC bus*/
480 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
481 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
483 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
485 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
487 /* Power off and uninitialize */
488 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
489 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
492 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
494 \brief Function: ETH_MAC_Control_Filtering
496 The function \b ETH_MAC_Control_Filtering verifies the Ethernet MAC \b Control function with the following sequence:
501 - Receive with broadcast disabled
503 - Receive with multicast disabled
505 - Promiscuous mode receive
510 The internal Ethernet MAC loopback is used for the test.
512 void ETH_MAC_Control_Filtering (void) {
515 /* Allocate buffers */
516 buffer_out = (uint8_t *)malloc(64);
517 TEST_ASSERT(buffer_out != NULL);
518 if (buffer_out == NULL) return;
519 buffer_in = (uint8_t *)malloc(64);
520 TEST_ASSERT(buffer_in != NULL);
521 if (buffer_in == NULL) { free(buffer_out); return; }
523 /* Initialize, power on and configure MAC and PHY */
524 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
525 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
526 TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
527 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M |
528 ARM_ETH_MAC_DUPLEX_FULL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
529 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
530 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
532 TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
533 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
534 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
535 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
537 /* Set Ethernet header */
538 memcpy(&buffer_out[6], &mac_addr, 6);
542 for (i = 14; i < 64; i++) {
543 buffer_out[i] = i + 'A' - 14;
546 /* Broadcast receive */
547 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK |
548 ARM_ETH_MAC_ADDRESS_BROADCAST) == ARM_DRIVER_OK);
549 memcpy(&buffer_out[0], &mac_bcast, 6);
550 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
551 TEST_FAIL_MESSAGE("[FAILED] Receive broadcast");
554 /* Receive with broadcast disabled */
555 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
556 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
557 TEST_MESSAGE("[WARNING] Broadcast receive not disabled");
560 /* Multicast receive */
561 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK |
562 ARM_ETH_MAC_ADDRESS_MULTICAST) == ARM_DRIVER_OK);
563 for (i = 0; i < 6; i++) {
564 memcpy(&buffer_out[0], &mac_mcast[i], 6);
565 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
566 snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
567 TEST_FAIL_MESSAGE(str);
571 /* Receive with multicast disabled */
572 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
573 memcpy(&buffer_out[0], &mac_mcast[0], 6);
574 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
575 TEST_MESSAGE("[WARNING] Multicast receive not disabled");
578 /* Unicast receive */
579 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
580 memcpy(&buffer_out[0], &mac_addr, 6);
581 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
582 TEST_FAIL_MESSAGE("[FAILED] Receive unicast");
585 /* Promiscuous mode receive */
586 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK |
587 ARM_ETH_MAC_ADDRESS_ALL) == ARM_DRIVER_OK);
588 /* Test broadcast receive */
589 memcpy(&buffer_out[0], &mac_bcast, 6);
590 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
591 TEST_FAIL_MESSAGE("[FAILED] Receive broadcast in promiscuous mode");
593 /* Test multicast receive */
594 memcpy(&buffer_out[0], &mac_mcast[0], 6);
595 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
596 TEST_FAIL_MESSAGE("[FAILED] Receive multicast in promiscuous mode");
598 /* Test unicast receive */
599 memcpy(&buffer_out[0], &mac_addr, 6);
600 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
601 TEST_FAIL_MESSAGE("[FAILED] Receive unicast in promiscuous mode");
604 /* Power off and uninitialize */
605 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
606 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
607 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
608 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
615 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
617 \brief Function: ETH_MAC_SetAddressFilter
619 The function \b ETH_MAC_SetAddressFilter verifies the Ethernet MAC \b SetAddressFilter function with the following sequence:
623 - Receive one multicast address
624 - Receive two multicast addresses
625 - Receive three multicast addresses
626 - Receive four multicast addresses
627 - Receive six multicast addresses
632 The internal Ethernet MAC loopback is used for the test.
634 void ETH_MAC_SetAddressFilter (void) {
637 /* Allocate buffers */
638 buffer_out = (uint8_t *)malloc(64);
639 TEST_ASSERT(buffer_out != NULL);
640 if (buffer_out == NULL) return;
641 buffer_in = (uint8_t *)malloc(64);
642 TEST_ASSERT(buffer_in != NULL);
643 if (buffer_in == NULL) { free(buffer_out); return; }
645 /* Initialize, power on and configure MAC and PHY */
646 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
647 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
648 TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
649 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M |
650 ARM_ETH_MAC_DUPLEX_FULL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
651 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
652 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
654 TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
655 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
656 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
657 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
659 /* Set Ethernet header */
660 memcpy(&buffer_out[6], &mac_addr, 6);
664 for (i = 14; i < 64; i++) {
665 buffer_out[i] = i + 'A' - 14;
668 /* Receive one multicast address */
669 TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 1) == ARM_DRIVER_OK);
671 memcpy(&buffer_out[0], &mac_mcast[0], 6);
672 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
673 /* Error, enabled multicast address not received */
674 TEST_FAIL_MESSAGE("[FAILED] Receive multicast 0 address");
677 for (i = 1; i < 6; i++) {
678 memcpy(&buffer_out[0], &mac_mcast[i], 6);
679 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
680 /* Warning, disabled multicast address received */
681 snprintf(str,sizeof(str),"[WARNING] Receive multicast %d address",i);
686 /* Receive two multicast addresses */
687 TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 2) == ARM_DRIVER_OK);
689 for (i = 0; i < 2; i++) {
690 memcpy(&buffer_out[0], &mac_mcast[i], 6);
691 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
692 /* Error, enabled multicast address not received */
693 snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
694 TEST_FAIL_MESSAGE(str);
699 memcpy(&buffer_out[0], &mac_mcast[i], 6);
700 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
701 /* Warning, disabled multicast address received */
702 snprintf(str,sizeof(str),"[WARNING] Receive multicast %d address",i);
707 /* Receive three multicast addresses */
708 TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 3) == ARM_DRIVER_OK);
710 for (i = 0; i < 3; i++) {
711 memcpy(&buffer_out[0], &mac_mcast[i], 6);
712 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
713 /* Error, enabled multicast address not received */
714 snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
715 TEST_FAIL_MESSAGE(str);
720 memcpy(&buffer_out[0], &mac_mcast[i], 6);
721 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
722 /* Warning, disabled multicast address received */
723 snprintf(str,sizeof(str),"[WARNING] Receive multicast %d address",i);
728 /* Receive four multicast addresses */
729 TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 4) == ARM_DRIVER_OK);
731 for (i = 0; i < 4; i++) {
732 memcpy(&buffer_out[0], &mac_mcast[i], 6);
733 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
734 /* Error, enabled multicast address not received */
735 snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
736 TEST_FAIL_MESSAGE(str);
741 memcpy(&buffer_out[0], &mac_mcast[i], 6);
742 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
743 /* Warning, disabled multicast address received */
744 snprintf(str,sizeof(str),"[WARNING] Receive multicast %d address",i);
749 /* Receive all multicast addresses */
750 TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 6) == ARM_DRIVER_OK);
752 for (i = 0; i < 6; i++) {
753 memcpy(&buffer_out[0], &mac_mcast[i], 6);
754 if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
755 /* Error, enabled multicast address not received */
756 snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
757 TEST_FAIL_MESSAGE(str);
761 /* Power off and uninitialize */
762 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
763 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
764 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
765 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
772 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
774 \brief Function: ETH_MAC_SignalEvent
776 The function \b ETH_MAC_SignalEvent verifies the Ethernet MAC interrupt operation with the sequence:
780 - Configure transmitter
781 - Set output buffer pattern
782 - Send data and check receive interrupts
787 The internal Ethernet MAC loopback is used for the test.
789 void ETH_MAC_SignalEvent (void) {
792 if (!capab.event_rx_frame) {
793 TEST_MESSAGE("[WARNING] Interrupt mode is not supported");
797 /* Allocate buffer */
798 buffer_out = (uint8_t *)malloc(64);
799 TEST_ASSERT(buffer_out != NULL);
800 if (buffer_out == NULL) return;
802 /* Initialize, power on and configure MAC */
803 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
804 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
805 TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
806 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
807 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
808 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
809 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
811 TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
812 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
813 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
814 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
816 /* Set Ethernet header */
817 memcpy(&buffer_out[0], &mac_bcast, 6);
818 memcpy(&buffer_out[6], &mac_addr, 6);
822 for (i = 14; i < 64; i++) {
823 buffer_out[i] = i + 'A' - 14;
826 Event &= ~ARM_ETH_MAC_EVENT_RX_FRAME;
827 TEST_ASSERT(eth_mac->SendFrame(buffer_out, 64, 0) == ARM_DRIVER_OK);
829 /* Wait for RX interrupt event */
830 tick = GET_SYSTICK();
832 if (Event & ARM_ETH_MAC_EVENT_RX_FRAME) {
836 while ((GET_SYSTICK() - tick) < SYSTICK_MICROSEC(ETH_TRANSFER_TIMEOUT*1000));
838 if (!(Event & ARM_ETH_MAC_EVENT_RX_FRAME)) {
839 TEST_FAIL_MESSAGE("[FAILED] Interrupt mode not working");
842 /* Power off and uninitialize */
843 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
844 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
845 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
846 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
849 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
851 \brief Function: Function ETH_PHY_GetVersion
853 The function \b ETH_PHY_GetVersion verifies the Ethernet PHY \b GetVersion function.
855 void ETH_PHY_GetVersion (void) {
856 ARM_DRIVER_VERSION ver;
858 ver = eth_phy->GetVersion();
860 TEST_ASSERT((ver.api >= ARM_DRIVER_VERSION_MAJOR_MINOR(1UL,0UL)) && (ver.drv >= ARM_DRIVER_VERSION_MAJOR_MINOR(1UL,0UL)));
862 snprintf(str,sizeof(str),"[INFO] API version %d.%d, Driver version %d.%d",(ver.api>>8),(ver.api&0xFFU),(ver.drv>>8),(ver.drv&0xFFU));
866 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
868 \brief Function: ETH_PHY_Initialization
870 The function \b ETH_PHY_Initialization verifies the Ethernet PHY functions in the following order:
871 - \b Initialize with read and write functions
873 void ETH_PHY_Initialization (void) {
875 /* MAC Initialize and power on */
876 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
877 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
880 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
883 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
885 /* MAC Power off and uninitialize */
886 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
887 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
890 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
892 \brief Function: ETH_PHY_CheckInvalidInit
894 The function \b ETH_PHY_CheckInvalidInit verifies the driver behavior when receiving an invalid initialization sequence:
896 - \b PowerControl with Power off
897 - \b PowerControl with Power on
898 - \b SetInterface to configure the Ethernet PHY bus
899 - \b SetMode to configure the Ethernet PHY bus
900 - \b PowerControl with Power off
903 void ETH_PHY_CheckInvalidInit (void) {
906 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
909 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) != ARM_DRIVER_OK);
911 /* Try to power on */
912 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) != ARM_DRIVER_OK);
914 /* Try to configure ETH_PHY bus*/
915 TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) != ARM_DRIVER_OK);
916 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) != ARM_DRIVER_OK);
918 /* Try to initialize without read and write functions */
919 TEST_ASSERT(eth_phy->Initialize(NULL, NULL) != ARM_DRIVER_OK);
922 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) != ARM_DRIVER_OK);
925 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
928 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
930 \brief Function: ETH_PHY_PowerControl
932 The function \b ETH_PHY_PowerControl verifies the Ethernet PHY \b PowerControl function with the sequence:
941 When the Ethernet PHY is the 50 MHz clock source for the MAC in RMII mode, the MAC may lock up if the PHY power is off
942 and therefore not generating a reference clock.
944 void ETH_PHY_PowerControl (void) {
947 /* MAC Initialize and power on */
948 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
949 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
952 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
955 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
958 retv = eth_phy->PowerControl(ARM_POWER_LOW);
959 if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Low power is not supported"); }
960 else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
963 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
966 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
968 /* Check RMII lockup */
969 if ((capab.media_interface == ARM_ETH_INTERFACE_RMII) && (!mac_lockup)) {
970 eth_mac->PowerControl(ARM_POWER_OFF);
971 eth_mac->PowerControl(ARM_POWER_FULL);
972 eth_phy->PowerControl(ARM_POWER_OFF);
973 eth_phy->Uninitialize();
976 TEST_MESSAGE("[WARNING] MAC is locked when PHY power is off");
979 /* MAC Power off and uninitialize */
980 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
981 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
984 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
986 \brief Function: ETH_PHY_Config
988 The function \b ETH_PHY_Config verifies the PHY functions
996 void ETH_PHY_Config (void) {
998 /* MAC Initialize and power on */
999 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1000 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1002 /* Initialize and power on */
1003 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1004 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1006 /* Configure ETH_PHY bus */
1007 TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
1009 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
1011 /* Power off and uninitialize */
1012 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1013 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1015 /* MAC Power off and uninitialize */
1016 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1017 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1020 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1022 \brief Function: ETH_Loopback_Transfer
1024 The function \b ETH_Loopback_Transfer verifies data transfer via Ethernet with the following sequence:
1028 - Set output buffer pattern
1029 - Transfer data chunks
1030 - Set output buffer with random data
1031 - Transfer data chunks
1032 - Transfer data by sending in two fragments
1037 The internal Ethernet MAC loopback is used as a data loopback, so there is no need to use an external loopback cable.
1039 void ETH_Loopback_Transfer (void) {
1040 const uint16_t test_len[] = {
1041 28,36,40,44,45,46,47,48,49,50,55,60,65,70,75,80,85,90,95,100,110,120,127,128,
1042 129,140,150,160,170,180,190,196,200,220,240,250,256,270,300,325,350,375,400,
1043 425,450,475,500,511,512,513,525,550,575,600,625,650,700,750,800,850,900,950,
1044 1000,1024,1050,1100,1150,1200,1250,1300,1320,1420,1480,1490,1491,1492,1493,
1045 1494,1495,1496,1497,1498,1499,1500};
1046 const uint32_t test_num = ARRAY_SIZE(test_len);
1047 uint32_t i,cnt,tick;
1049 /* Allocate buffers, add space for Ethernet header */
1050 buffer_out = (uint8_t *)malloc(14+ETH_MTU);
1051 TEST_ASSERT(buffer_out != NULL);
1052 if (buffer_out == NULL) return;
1053 buffer_in = (uint8_t *)malloc(14+ETH_MTU);
1054 TEST_ASSERT(buffer_in != NULL);
1055 if (buffer_in == NULL) { free(buffer_out); return; }
1057 /* Initialize, power on and configure MAC */
1058 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1059 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1060 TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
1061 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
1062 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
1063 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1064 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1066 TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
1067 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
1068 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
1069 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
1071 /* Set output buffer pattern */
1072 for (i = 0; i < ETH_MTU; i+=2) {
1073 buffer_out[14+i] = 0x55;
1074 buffer_out[15+i] = 0xAA;
1077 /* Set Ethernet header */
1078 memcpy(&buffer_out[0], &mac_bcast, 6);
1079 memcpy(&buffer_out[6], &mac_addr, 6);
1081 /* Transfer data chunks */
1082 for (cnt = 0; cnt < test_num; cnt++) {
1083 /* Clear input buffer */
1084 memset(buffer_in, 0, test_len[cnt]);
1085 /* Set Ethernet type/length */
1086 buffer_out[12] = test_len[cnt] >> 8;
1087 buffer_out[13] = test_len[cnt] & 0xFF;
1088 if (ETH_RunTransfer(buffer_out, buffer_in, 14+test_len[cnt], 0) != ARM_DRIVER_OK) {
1089 snprintf(str,sizeof(str),"[FAILED] Transfer block of %d bytes",test_len[cnt]);
1090 TEST_FAIL_MESSAGE(str);
1091 } else if (memcmp(buffer_in, buffer_out, 14+test_len[cnt]) != 0) {
1092 snprintf(str,sizeof(str),"[FAILED] Verify block of %d bytes",test_len[cnt]);
1093 TEST_FAIL_MESSAGE(str);
1097 /* Set output buffer with random data */
1098 srand(GET_SYSTICK());
1099 for (i = 0; i < ETH_MTU; i++) {
1100 buffer_out[14+cnt] = (uint8_t)rand();
1103 /* Transfer data chunks */
1104 for (cnt = 0; cnt < test_num; cnt++) {
1105 /* Clear input buffer */
1106 memset(buffer_in, 0, test_len[cnt]);
1107 /* Set Ethernet type/length */
1108 buffer_out[12] = test_len[cnt] >> 8;
1109 buffer_out[13] = test_len[cnt] & 0xFF;
1110 if (ETH_RunTransfer(buffer_out, buffer_in, 14+test_len[cnt], 0) != ARM_DRIVER_OK) {
1111 snprintf(str,sizeof(str),"[FAILED] Transfer block of %d bytes",test_len[cnt]);
1112 TEST_FAIL_MESSAGE(str);
1113 } else if (memcmp(buffer_in, buffer_out, 14+test_len[cnt]) != 0) {
1114 snprintf(str,sizeof(str),"[FAILED] Verify block of %d bytes",test_len[cnt]);
1115 TEST_FAIL_MESSAGE(str);
1119 /* Block transfer in two fragments: header and data */
1120 for (cnt = 0; cnt < test_num; cnt++) {
1121 /* Clear input buffer */
1122 memset(buffer_in, 0, test_len[cnt]);
1123 /* Set Ethernet type/length */
1124 buffer_out[12] = test_len[cnt] >> 8;
1125 buffer_out[13] = test_len[cnt] & 0xFF;
1126 if (ETH_RunTransfer(buffer_out, buffer_in, 14+test_len[cnt], 0) != ARM_DRIVER_OK) {
1127 snprintf(str,sizeof(str),"[FAILED] Fragmented block transfer of %d bytes",test_len[cnt]);
1128 TEST_FAIL_MESSAGE(str);
1129 } else if (memcmp(buffer_in, buffer_out, 14+test_len[cnt]) != 0) {
1130 snprintf(str,sizeof(str),"[FAILED] Fragmented block check of %d bytes",test_len[cnt]);
1131 TEST_FAIL_MESSAGE(str);
1135 /* Power off and uninitialize */
1136 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1137 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1138 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1139 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1146 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1148 \brief Function: ETH_Loopback_External
1150 The function \b ETH_Loopback_External verifies data transfer via Ethernet with the following sequence:
1154 - Set output buffer pattern
1155 - Transfer data on PHY internal loopback
1156 - Ethernet connection
1157 - Transfer data on external cable loopback
1162 An external loopback cable is required for this test.
1164 void ETH_Loopback_External (void) {
1165 ARM_ETH_LINK_INFO info;
1166 uint32_t i,cnt,tick;
1168 /* Allocate buffers, add space for Ethernet header */
1169 buffer_out = (uint8_t *)malloc(14+ETH_MTU);
1170 TEST_ASSERT(buffer_out != NULL);
1171 if (buffer_out == NULL) return;
1172 buffer_in = (uint8_t *)malloc(14+ETH_MTU);
1173 TEST_ASSERT(buffer_in != NULL);
1174 if (buffer_in == NULL) { free(buffer_out); return; }
1176 /* Initialize, power on and configure MAC and PHY */
1177 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1178 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1179 TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
1180 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
1181 ARM_ETH_MAC_ADDRESS_BROADCAST) == ARM_DRIVER_OK);
1182 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1183 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1185 TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
1186 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_SPEED_100M |
1187 ARM_ETH_PHY_DUPLEX_FULL | ARM_ETH_PHY_LOOPBACK) == ARM_DRIVER_OK);
1188 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
1189 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
1191 /* Fill output buffer */
1192 for (cnt = 0; cnt < ETH_MTU; cnt++) {
1193 buffer_out[14+cnt] = (cnt ^ 0x20) & 0x7F;
1196 /* Set Ethernet header */
1197 memcpy(&buffer_out[0], &mac_bcast, 6);
1198 memcpy(&buffer_out[6], &mac_addr, 6);
1200 /* Set Ethernet type/length */
1201 buffer_out[12] = (ETH_MTU >> 8) & 0xFF;
1202 buffer_out[13] = ETH_MTU & 0xFF;
1204 /* Check PHY internal loopback */
1205 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_SPEED_100M |
1206 ARM_ETH_PHY_DUPLEX_FULL | ARM_ETH_PHY_LOOPBACK) == ARM_DRIVER_OK);
1209 /* Clear input buffer*/
1210 memset(buffer_in, 0, 14+ETH_MTU);
1211 if (ETH_RunTransfer(buffer_out, buffer_in, 14+ETH_MTU, 0) != ARM_DRIVER_OK) {
1212 TEST_MESSAGE("[WARNING] PHY internal loopback is not active");
1213 } else if (memcmp(buffer_in, buffer_out, 14+ETH_MTU) != 0) {
1214 TEST_FAIL_MESSAGE("[FAILED] Verify received data");
1217 /* Check external cable loopback */
1218 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
1220 /* Check Ethernet link */
1221 tick = GET_SYSTICK();
1222 while (eth_phy->GetLinkState() != ARM_ETH_LINK_UP) {
1223 if ((GET_SYSTICK() - tick) >= SYSTICK_MICROSEC(ETH_LINK_TIMEOUT*1000)) {
1224 TEST_FAIL_MESSAGE("[FAILED] Link down, connect Ethernet cable");
1229 info = eth_phy->GetLinkInfo();
1230 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE,
1231 (uint32_t)info.speed << ARM_ETH_MAC_SPEED_Pos |
1232 (uint32_t)info.duplex << ARM_ETH_MAC_DUPLEX_Pos |
1233 ARM_ETH_MAC_ADDRESS_BROADCAST) == ARM_DRIVER_OK);
1235 /* Clear input buffer*/
1236 memset(buffer_in, 0, 14+ETH_MTU);
1237 if (ETH_RunTransfer(buffer_out, buffer_in, 14+ETH_MTU, 0) != ARM_DRIVER_OK) {
1238 TEST_FAIL_MESSAGE("[FAILED] Transfer external cable loopback");
1239 } else if (memcmp(buffer_in, buffer_out, 14+ETH_MTU) != 0) {
1240 TEST_FAIL_MESSAGE("[FAILED] Verify received data");
1243 /* Power off and uninitialize */
1244 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1245 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1246 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1247 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1254 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1256 \brief Function: ETH_MAC_PTP_ControlTimer
1258 The function \b ETH_MAC_PTP_ControlTimer verifies the PTP \b ControlTimer function with the sequence:
1269 void ETH_MAC_PTP_ControlTimer (void) {
1270 ARM_ETH_MAC_TIME time1,time2;
1271 int64_t t,t1ns,t2ns,overhead;
1274 /* Get capabilities */
1275 if (!capab.precision_timer) {
1276 TEST_MESSAGE("[WARNING] Precision Time Protocol is not supported");
1280 /* Initialize, power on and configure MAC */
1281 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1282 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1284 /* Set Time -------------------------------------------------------------------------------- */
1287 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_TIME, &time1) == ARM_DRIVER_OK);
1289 /* Check System Time */
1291 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1292 osDelay(PTP_TIME_REF);
1293 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1295 /* Get timestamps in nanoseconds */
1296 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1297 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1298 t = t2ns - t1ns - PTP_TIME_REF_NS;
1300 /* Check timestamps difference */
1301 if (llabs(t) > ETH_PTP_TOLERANCE) {
1302 snprintf(str,sizeof(str),"[WARNING] PTP measured time is %lldns from expected", t);
1306 /* Adjust clock - Set correction factor ---------------------------------------------------- */
1307 /* Calculate rate and convert it to q31 format */
1308 rate = (double)PTP_TIME_REF_NS / (t2ns-t1ns);
1309 time1.ns = (uint32_t)(0x80000000U*rate);
1310 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_ADJUST_CLOCK, &time1) == ARM_DRIVER_OK);
1312 /* Check System Time after adjusting clock */
1314 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1315 osDelay(PTP_TIME_REF);
1316 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1318 /* Get timestamps in nanoseconds */
1319 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1320 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1321 t = t2ns - t1ns - PTP_TIME_REF_NS;
1323 /* Check timestamps difference */
1324 if (llabs(t) > ETH_PTP_TOLERANCE) {
1325 snprintf(str,sizeof(str),"[WARNING] PTP measured time with adj clk is %lldns from expected", t);
1329 /* Measure time overhead for increment/decrement calls ------------------------------------- */
1332 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1333 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_INC_TIME, &time2) == ARM_DRIVER_OK);
1334 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1335 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1336 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1337 overhead = t2ns - t1ns;
1339 /* Increment time -------------------------------------------------------------------------- */
1340 time2.sec = PTP_TIME_REF/1000U;
1341 time2.ns = (PTP_TIME_REF-time2.sec*1000U)*1000000U;
1342 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1343 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_INC_TIME, &time2) == ARM_DRIVER_OK);
1344 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1346 /* Get timestamps in nanoseconds */
1347 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1348 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1349 t = t2ns - t1ns - PTP_TIME_REF_NS - overhead;
1351 /* Check timestamps difference */
1352 if (llabs(t) > ETH_PTP_TOLERANCE) {
1353 snprintf(str,sizeof(str),"[WARNING] PTP incremented time is %lldns from expected", t);
1357 /* Decrement time -------------------------------------------------------------------------- */
1358 time2.sec = PTP_TIME_REF/1000U;
1359 time2.ns = (PTP_TIME_REF-time2.sec*1000U)*1000000U;
1360 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1361 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_DEC_TIME, &time2) == ARM_DRIVER_OK);
1362 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1364 /* Get timestamps in nanoseconds */
1365 t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1366 t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1367 t = t2ns - t1ns + PTP_TIME_REF_NS - overhead;
1369 /* Check timestamps difference */
1370 if (llabs(t) > ETH_PTP_TOLERANCE) {
1371 snprintf(str,sizeof(str),"[WARNING] PTP decremented time is %lldns from expected", t);
1375 /* Set Alarm (1s) -------------------------------------------------------------------------- */
1376 Event &= ~ARM_ETH_MAC_EVENT_TIMER_ALARM;
1377 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1379 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_ALARM, &time1) == ARM_DRIVER_OK);
1381 /* Check alarm event after 999ms */
1383 if ((Event & ARM_ETH_MAC_EVENT_TIMER_ALARM) != 0) {
1384 TEST_FAIL_MESSAGE("[FAILED] PTP Alarm event triggered too early");
1387 /* Check alarm event after 1001ms */
1389 if ((Event & ARM_ETH_MAC_EVENT_TIMER_ALARM) == 0) {
1390 TEST_FAIL_MESSAGE("[FAILED] PTP Alarm event timeout");
1393 /* Power off and uninitialize */
1394 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1395 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1398 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1400 \brief Function: ETH_Loopback_PTP
1402 The function \b ETH_Loopback_PTP verifies the Precision Time Protocol functions \b ControlTimer, \b GetRxFrameTime and
1403 \b GetTxFrameTime with the sequence:
1414 The internal Ethernet MAC loopback is used as the data loopback.
1416 void ETH_Loopback_PTP (void) {
1417 ARM_ETH_MAC_TIME time1,time2;
1420 // PTP over Ethernet IPv4 sample frame
1421 const uint8_t PTP_frame[] = {
1422 0x01,0x00,0x5e,0x00,0x01,0x81,0x02,0x30,0x05,0x1d,0x1e,0x27,0x08,0x00,0x45,0x00,
1423 0x00,0x98,0x00,0x5d,0x40,0x00,0x01,0x11,0x29,0x68,0x0a,0x0a,0x64,0x05,0xe0,0x00,
1424 0x01,0x81,0x01,0x3f,0x01,0x3f,0x00,0x84,0xc0,0x7b,0x00,0x01,0x00,0x01,0x5f,0x44,
1425 0x46,0x4c,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
1426 0x00,0x30,0x05,0x1d,0x1e,0x27,0x00,0x01,0x00,0x5e,0x00,0x00,0x00,0x08,0x00,0x00,
1427 0x00,0x00,0x45,0x5b,0x0a,0x38,0x0e,0xb9,0x26,0x58,0x00,0x00,0x00,0x00,0x00,0x01,
1428 0x00,0x30,0x05,0x1d,0x1e,0x27,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x04,0x44,0x46,
1429 0x4c,0x54,0x00,0x00,0xf0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
1430 0xf0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x44,0x46,0x4c,0x54,0x00,0x01,
1431 0x00,0x30,0x05,0x1d,0x1e,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1432 0x00,0x00,0x00,0x00,0x00,0x00
1434 const uint32_t PTP_frame_len = sizeof(PTP_frame);
1436 /* Get capabilities */
1437 if (!capab.precision_timer) {
1438 TEST_MESSAGE("[WARNING] Precision Time Protocol is not supported");
1442 /* Allocate buffer */
1443 buffer_in = (uint8_t *)malloc(PTP_frame_len);
1444 TEST_ASSERT(buffer_in != NULL);
1445 if (buffer_in == NULL) return;
1447 /* Initialize, power on and configure MAC and PHY */
1448 TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1449 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1450 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
1451 ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
1452 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
1453 TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
1454 TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1455 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1457 TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
1458 TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
1463 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_TIME, &time1) == ARM_DRIVER_OK);
1465 /* Check timestamps - verify if control timer is running */
1466 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1467 TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1468 TEST_ASSERT((time2.sec==time1.sec)?(time2.ns>time1.ns):(time2.sec>time1.sec));
1470 /* Transfer frame */
1471 TEST_ASSERT(eth_mac->SendFrame(PTP_frame, PTP_frame_len, ARM_ETH_MAC_TX_FRAME_TIMESTAMP) == ARM_DRIVER_OK);
1472 tick = GET_SYSTICK();
1473 while (eth_mac->GetRxFrameSize() == 0) {
1474 if ((GET_SYSTICK() - tick) >= SYSTICK_MICROSEC(ETH_TRANSFER_TIMEOUT*1000)) {
1475 TEST_FAIL_MESSAGE("[FAILED] Transfer timeout");
1480 /* Get TX Frame Time */
1481 TEST_ASSERT(eth_mac->GetTxFrameTime(&time1) == ARM_DRIVER_OK);
1483 /* Get RX Frame Time */
1484 TEST_ASSERT(eth_mac->GetRxFrameTime(&time2) == ARM_DRIVER_OK);
1486 /* Check timestamps */
1487 TEST_ASSERT((time2.sec==time1.sec) ? (time2.ns>time1.ns) : (time2.sec>time1.sec));
1490 eth_mac->ReadFrame(buffer_in, PTP_frame_len);
1491 TEST_ASSERT(memcmp(buffer_in, PTP_frame, PTP_frame_len) == 0);
1493 /* Power off and uninitialize */
1494 TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1495 TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1496 TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1497 TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1507 // end of group dv_eth