]> begriffs open source - cmsis-driver-validation/blob - Source/DV_ETH.c
Update GitHub Actions runner to ubuntu-22.04 (#18)
[cmsis-driver-validation] / Source / DV_ETH.c
1 /*
2  * Copyright (c) 2015-2025 Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
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
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  * -----------------------------------------------------------------------------
19  *
20  * Project:     CMSIS-Driver Validation
21  * Title:       Ethernet (ETH) Driver Validation tests
22  *
23  * -----------------------------------------------------------------------------
24  */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "cmsis_dv.h"
31 #include "DV_ETH_Config.h"
32 #include "DV_Framework.h"
33
34 #include "Driver_ETH_MAC.h"
35 #include "Driver_ETH_PHY.h"
36
37 #ifdef BUFFER_PATTERN
38 #error Please update DV_ETH_Config.h
39 #endif
40
41 #define ETH_MTU          1500
42
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
47
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}};
56
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);
60
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;
65
66 // Local variables
67 static volatile uint8_t phy_power;
68 static volatile uint8_t mac_lockup;
69 static char str[128];
70
71 // Allocated buffer pointers
72 static uint8_t *buffer_out;
73 static uint8_t *buffer_in;
74
75 // Event flags
76 static uint8_t volatile Event;
77
78 // Ethernet event
79 static void ETH_DrvEvent (uint32_t event) {
80   Event |= event;
81 }
82
83 // Ethernet transfer
84 static int32_t ETH_RunTransfer (const uint8_t *out, uint8_t *in, uint32_t len, uint32_t frag) {
85   uint32_t tick,size;
86
87   Event &= ~ARM_ETH_MAC_EVENT_RX_FRAME;
88   if (frag == 0U) {
89     // Send the entire frame at once
90     eth_mac->SendFrame(out, len, 0);
91   }
92   else {
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);
96   }
97
98   tick = GET_SYSTICK();
99   do {
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();
103       if (size > 0) {
104         if ((size < 14) || (size > 14+ETH_MTU)) {
105           eth_mac->ReadFrame(NULL, 0U);
106           return ARM_DRIVER_ERROR;
107         }
108         eth_mac->ReadFrame(in, size);
109         return ARM_DRIVER_OK;
110       }
111     }
112   }
113   while ((GET_SYSTICK() - tick) < SYSTICK_MICROSEC(ETH_TRANSFER_TIMEOUT*1000));
114
115   return ARM_DRIVER_ERROR_TIMEOUT;
116 }
117
118 #define ETH_CheckAddressFilter()    ETH_CheckFilter(0)
119 #define ETH_CheckVlanFilter()       ETH_CheckFilter(1)
120
121 // Check multicast address and VLAN filtering support
122 static int32_t ETH_CheckFilter (int32_t vlan) {
123   int32_t retv;
124
125   eth_mac->Initialize(cb_event);
126   eth_mac->PowerControl(ARM_POWER_FULL);
127   retv = (!vlan) ? eth_mac->SetAddressFilter(NULL, 0)         :
128                    eth_mac->Control (ARM_ETH_MAC_VLAN_FILTER, 0);
129   eth_mac->PowerControl(ARM_POWER_OFF);
130   eth_mac->Uninitialize();
131
132   return retv;
133 }
134
135 // Initialize MAC driver wrapper for RMII interface
136 static int32_t mac_initialize (ARM_ETH_MAC_SignalEvent_t cb_event) {
137   ARM_DRIVER_ETH_MAC *drv_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
138
139   phy_power = 1U;
140   return drv_mac->Initialize(cb_event);
141 }
142
143 // Uninitialize MAC driver wrapper for RMII interface
144 static int32_t mac_uninitialize (void) {
145   ARM_DRIVER_ETH_MAC *drv_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
146
147   phy_power = 0U;
148   return drv_mac->Uninitialize();
149 }
150
151 // MAC driver power control wrapper for RMII interface
152 static int32_t mac_power_control (ARM_POWER_STATE state) {
153   ARM_DRIVER_ETH_MAC *drv_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
154   ARM_DRIVER_ETH_PHY *drv_phy = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
155   int32_t retv;
156
157   retv = drv_mac->PowerControl(state);
158   if ((state == ARM_POWER_FULL) && (retv == ARM_DRIVER_ERROR) && (phy_power == 1U)) {
159     /* RMII solution when the PHY is a 50 MHz reference clock source   */
160     /* MAC never exits soft reset when PHY is powered down (no 50 MHz) */
161     /* So turn on the power for the PHY here to prevent deadlock       */
162     drv_phy->Initialize(drv_mac->PHY_Read, drv_mac->PHY_Write);
163     if (drv_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK) {
164       phy_power = 2U;
165       osDelay (10);
166       retv = drv_mac->PowerControl(state);
167       if (retv == ARM_DRIVER_OK) {
168         /* RMII lockup detected */
169         mac_lockup = 1U;
170       }
171     }
172   }
173   return (retv);
174 }
175
176 // PHY driver power control wrapper for RMII interface
177 static int32_t phy_power_control (ARM_POWER_STATE state) {
178   ARM_DRIVER_ETH_PHY *drv_phy = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
179   int32_t retv;
180
181   retv = drv_phy->PowerControl(state);
182   if ((state == ARM_POWER_OFF) && (retv == ARM_DRIVER_OK) && (phy_power == 2U)) {
183     phy_power = 1U;
184   }
185   return (retv);
186 }
187
188 /* Helper function that is called before tests start executing */
189 void ETH_DV_Initialize (void) {
190   static struct _ARM_DRIVER_ETH_MAC s_mac;
191   static struct _ARM_DRIVER_ETH_PHY s_phy;
192
193   eth_mac = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
194   eth_phy = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
195   capab   = eth_mac->GetCapabilities();
196   if (capab.media_interface == ARM_ETH_INTERFACE_RMII) {
197     memcpy(&s_mac, eth_mac, sizeof(s_mac));
198     memcpy(&s_phy, eth_phy, sizeof(s_phy));
199     /* Use wrapper functions in RMII interface mode */
200     s_mac.Initialize   = &mac_initialize;
201     s_mac.Uninitialize = &mac_uninitialize;
202     s_mac.PowerControl = &mac_power_control;
203     s_phy.PowerControl = &phy_power_control;
204     eth_mac = &s_mac;
205     eth_phy = &s_phy;
206     phy_power  = 0U;
207     mac_lockup = 0U;
208   }
209   cb_event = (capab.event_rx_frame) ? ETH_DrvEvent : NULL;
210 }
211
212 /* Helper function that is called after tests stop executing */
213 void ETH_DV_Uninitialize (void) {
214   eth_mac  = &CREATE_SYMBOL(Driver_ETH_MAC, DRV_ETH);
215   eth_phy  = &CREATE_SYMBOL(Driver_ETH_PHY, DRV_ETH);
216   cb_event = NULL;
217 }
218
219 /*-----------------------------------------------------------------------------
220  *      Tests
221  *----------------------------------------------------------------------------*/
222
223 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
224 /**
225 \defgroup dv_eth Ethernet Validation
226 \brief Ethernet driver validation
227 \details
228 The Ethernet validation test performs the following checks:
229 - API interface compliance.
230 - Data communication with various transfer sizes and communication parameters.
231 - Loopback communication.
232
233 \anchor eth_loopback
234 Loopback Communication Setup
235 ----------------------------
236
237 To perform loopback communication tests, it is required to connect the RX and TX lines of the Ethernet cable together:
238
239 - TX+ (Pin 1) with RX+ (Pin 3) and
240 - TX- (Pin 2) with RX- (Pin 6)
241
242 \image html ethernet_loopback.png
243
244 Various \b Ethernet \b loopback \b plugs are available from different vendors that fulfill this purpose.
245
246 \defgroup eth_tests Tests
247 \ingroup dv_eth
248
249 @{
250 */
251
252 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
253 /**
254 \brief Function: Function ETH_MAC_GetVersion
255 \details
256 The function \b ETH_MAC_GetVersion verifies the Ethernet MAC \b GetVersion function.
257 */
258 void ETH_MAC_GetVersion (void) {
259   ARM_DRIVER_VERSION ver;
260
261   ver = eth_mac->GetVersion();
262
263   TEST_ASSERT((ver.api >= ARM_DRIVER_VERSION_MAJOR_MINOR(1UL,0UL)) && (ver.drv >= ARM_DRIVER_VERSION_MAJOR_MINOR(1UL,0UL)));
264
265   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));
266   TEST_MESSAGE(str);
267 }
268
269 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
270 /**
271 \brief Function: ETH_MAC_GetCapabilities
272 \details
273 The function \b ETH_MAC_GetCapabilities verifies the Ethernet MAC \b GetCapabilities function.
274 */
275 void ETH_MAC_GetCapabilities (void) {
276   ARM_ETH_MAC_CAPABILITIES cap;
277
278   /* Get ETH_MAC capabilities */
279   cap = eth_mac->GetCapabilities();
280
281   TEST_ASSERT_MESSAGE((cap.reserved == 0U), "[FAILED] Capabilities reserved field must be 0");
282 }
283
284 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
285 /**
286 \brief Function: ETH_MAC_Initialization
287 \details
288 The function \b ETH_MAC_Initialization verifies the Ethernet MAC functions in the following order:
289   - \b Initialize without callback
290   - \b Uninitialize
291   - \b Initialize with callback if supported
292   - \b Uninitialize
293 */
294 void ETH_MAC_Initialization (void) {
295
296   /* Initialize without callback */
297   TEST_ASSERT(eth_mac->Initialize(NULL) == ARM_DRIVER_OK);
298
299   /* Uninitialize */
300   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
301
302   /* Initialize with callback if supported */
303   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
304
305   /* Uninitialize */
306   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
307 }
308
309 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
310 /**
311 \brief Function: ETH_MAC_CheckInvalidInit
312 \details
313 The function \b ETH_MAC_CheckInvalidInit verifies the driver behavior when receiving an invalid initialization sequence:
314   - \b Uninitialize
315   - \b PowerControl with Power off
316   - \b PowerControl with Power on
317   - \b Control
318   - \b PowerControl with Power off
319   - \b Uninitialize
320 */
321 void ETH_MAC_CheckInvalidInit (void) {
322
323   /* Uninitialize */
324   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
325
326   /* Power off */
327   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
328
329   /* Try to power on */
330   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) != ARM_DRIVER_OK);
331
332   /* Try to set configuration */
333   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
334     ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL) != ARM_DRIVER_OK);
335
336   /* Power off */
337   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
338
339   /* Uninitialize */
340   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
341 }
342
343 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
344 /**
345 \brief Function: ETH_MAC_PowerControl
346 \details
347 The function \b ETH_MAC_PowerControl verifies the Ethernet MAC \b PowerControl function with the sequence:
348   - Initialize
349   - Power on
350   - Power low
351   - Power off
352   - Uninitialize
353 */
354 void ETH_MAC_PowerControl (void) {
355   int32_t retv;
356
357   /* Initialize with callback if supported */
358   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
359
360   /* Power on */
361   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
362
363   /* Power low */
364   retv = eth_mac->PowerControl(ARM_POWER_LOW);
365   if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Low power is not supported"); }
366   else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
367
368   /* Power off */
369   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
370
371   /* Uninitialize */
372   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
373 }
374
375 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
376 /**
377 \brief Function: ETH_MAC_MacAddress
378 \details
379 The function \b ETH_MAC_MacAddress verifies the Ethernet MAC \b GetMacAddress and \b SetMacAddress functions
380 with the sequence:
381   - Initialize
382   - Power on
383   - Set Ethernet MAC Address
384   - Get Ethernet MAC Address
385   - Power off
386   - Uninitialize
387 */
388 void ETH_MAC_MacAddress (void) {
389   ARM_ETH_MAC_ADDR my_addr;
390
391   /* Initialize with callback if supported and power on */
392   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
393   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
394
395   /* Set MAC Address */
396   TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
397
398   /* Verify MAC Address */
399   memset(&my_addr, 0, 6);
400   TEST_ASSERT(eth_mac->GetMacAddress(&my_addr) == ARM_DRIVER_OK);
401   if (memcmp(&mac_addr, &my_addr, 6) != 0) {
402     TEST_FAIL_MESSAGE("[FAILED] Verify MAC address");
403   } else TEST_PASS();
404
405   /* Power off */
406   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
407
408   /* Uninitialize */
409   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
410 }
411
412 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
413 /**
414 \brief Function: ETH_MAC_SetBusSpeed
415 \details
416 The function \b ETH_MAC_SetBusSpeed verifies the Ethernet MAC \b Control function with the sequence:
417   - Initialize
418   - Power on
419   - Set bus speed \token{10M}
420   - Set bus speed \token{100M}
421   - Set bus speed \token{1G}
422   - Power off
423   - Uninitialize
424 */
425 void ETH_MAC_SetBusSpeed (void) {
426   int32_t retv;
427
428   /* Initialize with callback if supported and power on */
429   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
430   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
431
432   /* Set bus speed 10M */
433   retv = eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_10M);
434   if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Link speed 10M is not supported"); }
435   else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
436
437   /* Set bus speed 100M */
438   retv = eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M);
439   if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Link speed 100M is not supported"); }
440   else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
441
442   /* Set bus speed 1G */
443   retv = eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_1G);
444   if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Link speed 1G is not supported"); }
445   else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
446
447   /* Power off and uninitialize */
448   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
449   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
450 }
451
452 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
453 /**
454 \brief Function: ETH_MAC_Config_Mode
455 \details
456 The function \b ETH_MAC_Config_Mode verifies the Ethernet MAC \b Control function with the sequence:
457   - Initialize
458   - Power on
459   - Set full duplex
460   - Set half duplex
461   - Power off
462   - Uninitialize
463 */
464 void ETH_MAC_Config_Mode (void) {
465
466   /* Initialize with callback if supported and power on */
467   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
468   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
469
470   /* Set full duplex */
471   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_DUPLEX_FULL) == ARM_DRIVER_OK);
472
473   /* Set half duplex */
474   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_DUPLEX_HALF) == ARM_DRIVER_OK);
475
476   /* Power off and uninitialize */
477   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
478   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
479 }
480
481 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
482 /**
483 \brief Function: ETH_MAC_Config_CommonParams
484 \details
485 The function \b ETH_MAC_Config_CommonParams verifies the Ethernet MAC \b Control function with the sequence:
486   - Initialize
487   - Power on
488   - Configure Ethernet MAC bus
489   - Configure receiver
490   - Configure transmitter
491   - Power off
492   - Uninitialize
493 */
494 void ETH_MAC_Config_CommonParams (void) {
495
496   /* Initialize with callback if supported and power on */
497   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
498   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
499
500   /* Configure ETH_MAC bus*/
501   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
502     ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
503
504   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
505
506   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
507
508   /* Power off and uninitialize */
509   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
510   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
511 }
512
513 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
514 /**
515 \brief  Function: ETH_MAC_Control_Filtering
516 \details
517 The function \b ETH_MAC_Control_Filtering verifies the Ethernet MAC \b Control function with the following sequence:
518   - Buffer allocation
519   - Initialize
520   - Power on
521   - Broadcast receive
522   - Receive with broadcast disabled
523   - Multicast receive
524   - Receive with multicast disabled
525   - Unicast receive
526   - Promiscuous mode receive
527   - Power off
528   - Uninitialize
529
530 \note
531 The internal Ethernet MAC loopback is used for the test.
532 */
533 void ETH_MAC_Control_Filtering (void) {
534   uint32_t i,tick;
535
536   /* Allocate buffers */
537   buffer_out = (uint8_t *)malloc(64);
538   TEST_ASSERT(buffer_out != NULL);
539   if (buffer_out == NULL) return;
540   buffer_in = (uint8_t *)malloc(64);
541   TEST_ASSERT(buffer_in != NULL);
542   if (buffer_in == NULL) { free(buffer_out); return; }
543
544   /* Initialize, power on and configure MAC and PHY */
545   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
546   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
547   TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
548   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M |
549     ARM_ETH_MAC_DUPLEX_FULL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
550   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
551   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
552   osDelay (100);
553   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
554   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
555   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
556   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
557
558   /* Set Ethernet header */
559   memcpy(&buffer_out[6], &mac_addr, 6);
560   buffer_out[12] = 0;
561   buffer_out[13] = 50;
562
563   for (i = 14; i < 64; i++) {
564     buffer_out[i] = i + 'A' - 14;
565   }
566
567   /* Broadcast receive */
568   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK |
569     ARM_ETH_MAC_ADDRESS_BROADCAST) == ARM_DRIVER_OK);
570   memcpy(&buffer_out[0], &mac_bcast, 6);
571   if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
572     TEST_FAIL_MESSAGE("[FAILED] Receive broadcast");
573   } else TEST_PASS();
574
575   /* Receive with broadcast disabled */
576   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
577   if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
578     TEST_MESSAGE("[WARNING] Broadcast receive not disabled");
579   }
580
581   /* Multicast receive */
582   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK |
583     ARM_ETH_MAC_ADDRESS_MULTICAST) == ARM_DRIVER_OK);
584   for (i = 0; i < 6; i++) {
585     memcpy(&buffer_out[0], &mac_mcast[i], 6);
586     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
587       snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
588       TEST_FAIL_MESSAGE(str);
589     } else TEST_PASS();
590   }
591
592   /* Receive with multicast disabled */
593   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
594   memcpy(&buffer_out[0], &mac_mcast[0], 6);
595   if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
596     TEST_MESSAGE("[WARNING] Multicast receive not disabled");
597   }
598
599   /* Unicast receive */
600   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
601   memcpy(&buffer_out[0], &mac_addr, 6);
602   if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
603     TEST_FAIL_MESSAGE("[FAILED] Receive unicast");
604   } else TEST_PASS();
605
606   /* Promiscuous mode receive */
607   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_LOOPBACK |
608     ARM_ETH_MAC_ADDRESS_ALL) == ARM_DRIVER_OK);
609   /* Test broadcast receive */
610   memcpy(&buffer_out[0], &mac_bcast, 6);
611   if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
612     TEST_FAIL_MESSAGE("[FAILED] Receive broadcast in promiscuous mode");
613   } else TEST_PASS();
614   /* Test multicast receive */
615   memcpy(&buffer_out[0], &mac_mcast[0], 6);
616   if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
617     TEST_FAIL_MESSAGE("[FAILED] Receive multicast in promiscuous mode");
618   } else TEST_PASS();
619   /* Test unicast receive */
620   memcpy(&buffer_out[0], &mac_addr, 6);
621   if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
622     TEST_FAIL_MESSAGE("[FAILED] Receive unicast in promiscuous mode");
623   } else TEST_PASS();
624
625   /* Power off and uninitialize */
626   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
627   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
628   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
629   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
630
631   /* Free buffers */
632   free(buffer_out);
633   free(buffer_in);
634 }
635
636 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
637 /**
638 \brief  Function: ETH_MAC_SetAddressFilter
639 \details
640 The function \b ETH_MAC_SetAddressFilter verifies the Ethernet MAC \b SetAddressFilter function with the following sequence:
641   - Buffer allocation
642   - Initialize
643   - Power on
644   - Receive one multicast address
645   - Receive two multicast addresses
646   - Receive three multicast addresses
647   - Receive four multicast addresses
648   - Receive six multicast addresses
649   - Power off
650   - Uninitialize
651
652 \note
653 The internal Ethernet MAC loopback is used for the test.
654 */
655 void ETH_MAC_SetAddressFilter (void) {
656   uint32_t i,tick;
657
658   if (ETH_CheckAddressFilter() == ARM_DRIVER_ERROR_UNSUPPORTED) {
659     /* Multicast address filtering not supported */
660     TEST_MESSAGE("[WARNING] Multicast address filtering is not supported");
661     return;
662   }
663
664   /* Allocate buffers */
665   buffer_out = (uint8_t *)malloc(64);
666   TEST_ASSERT(buffer_out != NULL);
667   if (buffer_out == NULL) return;
668   buffer_in = (uint8_t *)malloc(64);
669   TEST_ASSERT(buffer_in != NULL);
670   if (buffer_in == NULL) { free(buffer_out); return; }
671
672   /* Initialize, power on and configure MAC and PHY */
673   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
674   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
675   TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
676   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M |
677     ARM_ETH_MAC_DUPLEX_FULL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
678   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
679   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
680   osDelay (100);
681   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
682   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
683   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
684   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
685
686   /* Set Ethernet header */
687   memcpy(&buffer_out[6], &mac_addr, 6);
688   buffer_out[12] = 0;
689   buffer_out[13] = 50;
690
691   for (i = 14; i < 64; i++) {
692     buffer_out[i] = i + 'A' - 14;
693   }
694
695   /* Receive one multicast address */
696   TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 1) == ARM_DRIVER_OK);
697
698   memcpy(&buffer_out[0], &mac_mcast[0], 6);
699   if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
700     /* Error, enabled multicast address not received */
701     TEST_FAIL_MESSAGE("[FAILED] Receive multicast 0 address");
702   } else TEST_PASS();
703
704   for (i = 1; i < 6; i++) {
705     memcpy(&buffer_out[0], &mac_mcast[i], 6);
706     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
707       /* Warning, disabled multicast address received */
708       snprintf(str,sizeof(str),"[WARNING] Receive multicast %d address",i);
709       TEST_MESSAGE(str);
710     }
711   }
712
713   /* Receive two multicast addresses */
714   TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 2) == ARM_DRIVER_OK);
715
716   for (i = 0; i < 2; i++) {
717     memcpy(&buffer_out[0], &mac_mcast[i], 6);
718     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
719       /* Error, enabled multicast address not received */
720       snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
721       TEST_FAIL_MESSAGE(str);
722     } else TEST_PASS();
723   }
724
725   for (; i < 6; i++) {
726     memcpy(&buffer_out[0], &mac_mcast[i], 6);
727     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
728       /* Warning, disabled multicast address received */
729       snprintf(str,sizeof(str),"[WARNING] Receive multicast %d address",i);
730       TEST_MESSAGE(str);
731     }
732   }
733
734   /* Receive three multicast addresses */
735   TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 3) == ARM_DRIVER_OK);
736
737   for (i = 0; i < 3; i++) {
738     memcpy(&buffer_out[0], &mac_mcast[i], 6);
739     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
740       /* Error, enabled multicast address not received */
741       snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
742       TEST_FAIL_MESSAGE(str);
743     } else TEST_PASS();
744   }
745
746   for (; i < 6; i++) {
747     memcpy(&buffer_out[0], &mac_mcast[i], 6);
748     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
749       /* Warning, disabled multicast address received */
750       snprintf(str,sizeof(str),"[WARNING] Receive multicast %d address",i);
751       TEST_MESSAGE(str);
752     }
753   }
754
755   /* Receive four multicast addresses */
756   TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 4) == ARM_DRIVER_OK);
757
758   for (i = 0; i < 4; i++) {
759     memcpy(&buffer_out[0], &mac_mcast[i], 6);
760     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
761       /* Error, enabled multicast address not received */
762       snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
763       TEST_FAIL_MESSAGE(str);
764     } else TEST_PASS();
765   }
766
767   for (; i < 6; i++) {
768     memcpy(&buffer_out[0], &mac_mcast[i], 6);
769     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) == ARM_DRIVER_OK) {
770       /* Warning, disabled multicast address received */
771       snprintf(str,sizeof(str),"[WARNING] Receive multicast %d address",i);
772       TEST_MESSAGE(str);
773     }
774   }
775
776   /* Receive all multicast addresses */
777   TEST_ASSERT(eth_mac->SetAddressFilter(mac_mcast, 6) == ARM_DRIVER_OK);
778
779   for (i = 0; i < 6; i++) {
780     memcpy(&buffer_out[0], &mac_mcast[i], 6);
781     if (ETH_RunTransfer(buffer_out, buffer_in, 64, 0) != ARM_DRIVER_OK) {
782       /* Error, enabled multicast address not received */
783       snprintf(str,sizeof(str),"[FAILED] Receive multicast %d address",i);
784       TEST_FAIL_MESSAGE(str);
785     } else TEST_PASS();
786   }
787
788   /* Power off and uninitialize */
789   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
790   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
791   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
792   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
793
794   /* Free buffers */
795   free(buffer_out);
796   free(buffer_in);
797 }
798
799 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
800 /**
801 \brief  Function: ETH_MAC_VLAN_Filter
802 \details
803 The function \b ETH_MAC_VLAN_Filter verifies the Ethernet MAC Virtual LAN filtering with the following sequence:
804   - Buffer allocation
805   - Initialize
806   - Power on
807   - Transfer VLAN packets
808   - Receive VLAN packets
809   - Power off
810   - Uninitialize
811
812 \note
813 The internal Ethernet MAC loopback is used for the test.
814 */
815 void ETH_MAC_VLAN_Filter (void) {
816   const uint8_t IP_frame[] = {
817     0x01,0x00,0x5e,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x81,0x00,0x00,0x00,
818     0x08,0x00,0x45,0x00,0x00,0x1c,0x65,0x51,0x00,0x00,0x01,0x02,0xb2,0xe3,0xc0,0xa8,
819     0x01,0x02,0xe0,0x00,0x00,0x01,0x11,0x64,0xee,0x9b,0x00,0x00,0x00,0x00,0x00,0x00,
820     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
821   };
822   const uint16_t test_id[] = { 1,2,100,500,1000,1005,1006,1500,2000,4000,4093 };
823   const uint16_t vlan_id[] = { 1,20,100,1000,2000,4093 };
824   uint32_t i,j;
825
826   if (ETH_CheckVlanFilter() == ARM_DRIVER_ERROR_UNSUPPORTED) {
827     /* VLAN tagged frame filtering not supported */
828     TEST_MESSAGE("[WARNING] VLAN filtering is not supported");
829     return;
830   }
831
832   /* Allocate buffers */
833   buffer_out = (uint8_t *)malloc(64);
834   TEST_ASSERT(buffer_out != NULL);
835   if (buffer_out == NULL) return;
836   buffer_in = (uint8_t *)malloc(64);
837   TEST_ASSERT(buffer_in != NULL);
838   if (buffer_in == NULL) { free(buffer_out); return; }
839
840   /* Initialize, power on and configure MAC and PHY */
841   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
842   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
843   TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
844   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M |
845     ARM_ETH_MAC_DUPLEX_FULL | ARM_ETH_MAC_ADDRESS_BROADCAST) == ARM_DRIVER_OK);
846   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
847   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
848   osDelay (100);
849   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
850   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
851   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
852   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
853
854   /* Set Ethernet frame */
855   memcpy (buffer_out, IP_frame, sizeof (IP_frame));
856   memcpy (&buffer_out[6], &mac_addr,  6);
857
858   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
859     ARM_ETH_MAC_ADDRESS_MULTICAST | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
860
861   for (i = 0; i < ARRAY_SIZE(vlan_id); i++) {
862     TEST_ASSERT(eth_mac->Control (ARM_ETH_MAC_VLAN_FILTER,
863       ARM_ETH_MAC_VLAN_FILTER_ID_ONLY | vlan_id[i]) == ARM_DRIVER_OK);
864     for (j = 0; j < ARRAY_SIZE(test_id); j++) {
865       int32_t retv;
866       /* Set VLAN ID tag */
867       buffer_out[14] = (test_id[j] >> 8) & 0xFF;
868       buffer_out[15] =  test_id[j]       & 0xFF;
869       retv = ETH_RunTransfer(buffer_out, buffer_in, 64, 0);
870       if (((test_id[j] == vlan_id[i]) && (retv != ARM_DRIVER_OK)) ||
871           ((test_id[j] != vlan_id[i]) && (retv == ARM_DRIVER_OK))) {
872         snprintf(str,sizeof(str),"[FAILED] VLAN tag %d",vlan_id[i]);
873         TEST_FAIL_MESSAGE(str);
874         break;
875       }
876       else TEST_PASS();
877     }
878   }
879
880   /* Power off and uninitialize */
881   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
882   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
883   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
884   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
885
886   /* Free buffers */
887   free(buffer_out);
888   free(buffer_in);
889 }
890
891 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
892 /**
893 \brief Function: ETH_MAC_SignalEvent
894 \details
895 The function \b ETH_MAC_SignalEvent verifies the Ethernet MAC interrupt operation with the sequence:
896   - Initialize
897   - Power on
898   - Configure receiver
899   - Configure transmitter
900   - Set output buffer pattern
901   - Send data and check receive interrupts
902   - Power off
903   - Uninitialize
904
905 \note
906 The internal Ethernet MAC loopback is used for the test.
907 */
908 void ETH_MAC_SignalEvent (void) {
909   uint32_t i,tick;
910
911   if (!capab.event_rx_frame) {
912     TEST_MESSAGE("[WARNING] Interrupt mode is not supported");
913     return;
914   }
915
916   /* Allocate buffer */
917   buffer_out = (uint8_t *)malloc(64);
918   TEST_ASSERT(buffer_out != NULL);
919   if (buffer_out == NULL) return;
920
921   /* Initialize, power on and configure MAC */
922   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
923   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
924   TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
925   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
926     ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
927   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
928   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
929   osDelay (100);
930   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
931   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
932   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
933   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
934
935   /* Set Ethernet header */
936   memcpy(&buffer_out[0], &mac_bcast, 6);
937   memcpy(&buffer_out[6], &mac_addr,  6);
938   buffer_out[12] = 0;
939   buffer_out[13] = 50;
940
941   for (i = 14; i < 64; i++) {
942     buffer_out[i] = i + 'A' - 14;
943   }
944
945   Event &= ~ARM_ETH_MAC_EVENT_RX_FRAME;
946   TEST_ASSERT(eth_mac->SendFrame(buffer_out, 64, 0) == ARM_DRIVER_OK);
947
948   /* Wait for RX interrupt event */
949   tick = GET_SYSTICK();
950   do {
951     if (Event & ARM_ETH_MAC_EVENT_RX_FRAME) {
952       break;
953     }
954   }
955   while ((GET_SYSTICK() - tick) < SYSTICK_MICROSEC(ETH_TRANSFER_TIMEOUT*1000));
956
957   if (!(Event & ARM_ETH_MAC_EVENT_RX_FRAME)) {
958     TEST_FAIL_MESSAGE("[FAILED] Interrupt mode not working");
959   } else TEST_PASS();
960
961   /* Power off and uninitialize */
962   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
963   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
964   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
965   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
966 }
967
968 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
969 /**
970 \brief Function: Function ETH_PHY_GetVersion
971 \details
972 The function \b ETH_PHY_GetVersion verifies the Ethernet PHY \b GetVersion function.
973 */
974 void ETH_PHY_GetVersion (void) {
975   ARM_DRIVER_VERSION ver;
976
977   ver = eth_phy->GetVersion();
978
979   TEST_ASSERT((ver.api >= ARM_DRIVER_VERSION_MAJOR_MINOR(1UL,0UL)) && (ver.drv >= ARM_DRIVER_VERSION_MAJOR_MINOR(1UL,0UL)));
980
981   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));
982   TEST_MESSAGE(str);
983 }
984
985 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
986 /**
987 \brief Function: ETH_PHY_Initialization
988 \details
989 The function \b ETH_PHY_Initialization verifies the Ethernet PHY functions in the following order:
990   - \b Initialize with read and write functions
991 */
992 void ETH_PHY_Initialization (void) {
993
994   /* MAC Initialize and power on */
995   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
996   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
997
998   /* Initialize */
999   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1000
1001   /* Uninitialize */
1002   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1003
1004   /* MAC Power off and uninitialize */
1005   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1006   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1007 }
1008
1009 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1010 /**
1011 \brief Function: ETH_PHY_CheckInvalidInit
1012 \details
1013 The function \b ETH_PHY_CheckInvalidInit verifies the driver behavior when receiving an invalid initialization sequence:
1014   - \b Uninitialize
1015   - \b PowerControl with Power off
1016   - \b PowerControl with Power on
1017   - \b SetInterface to configure the Ethernet PHY bus
1018   - \b SetMode to configure the Ethernet PHY bus
1019   - \b PowerControl with Power off
1020   - \b Uninitialize
1021 */
1022 void ETH_PHY_CheckInvalidInit (void) {
1023
1024   /* Uninitialize */
1025   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1026
1027   /* Power off */
1028   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) != ARM_DRIVER_OK);
1029
1030   /* Try to power on */
1031   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) != ARM_DRIVER_OK);
1032
1033   /* Try to configure ETH_PHY bus*/
1034   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) != ARM_DRIVER_OK);
1035   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) != ARM_DRIVER_OK);
1036
1037   /* Try to initialize without read and write functions */
1038   TEST_ASSERT(eth_phy->Initialize(NULL, NULL) != ARM_DRIVER_OK);
1039
1040   /* Power off */
1041   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) != ARM_DRIVER_OK);
1042
1043   /* Uninitialize */
1044   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1045 }
1046
1047 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1048 /**
1049 \brief Function: ETH_PHY_PowerControl
1050 \details
1051 The function \b ETH_PHY_PowerControl verifies the Ethernet PHY \b PowerControl function with the sequence:
1052   - Initialize
1053   - Power on
1054   - Power low
1055   - Power off
1056   - Check RMII lockup
1057   - Uninitialize
1058
1059 \note
1060 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
1061 and therefore not generating a reference clock.
1062 */
1063 void ETH_PHY_PowerControl (void) {
1064   int32_t retv;
1065
1066   /* MAC Initialize and power on */
1067   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1068   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1069
1070   /* Initialize */
1071   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1072
1073   /* Power on */
1074   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1075
1076   /* Power low */
1077   retv = eth_phy->PowerControl(ARM_POWER_LOW);
1078   if (retv == ARM_DRIVER_ERROR_UNSUPPORTED) { TEST_MESSAGE("[WARNING] Low power is not supported"); }
1079   else { TEST_ASSERT(retv == ARM_DRIVER_OK); }
1080
1081   /* Power off */
1082   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1083
1084   /* Uninitialize */
1085   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1086
1087   /* Check RMII lockup */
1088   if ((capab.media_interface == ARM_ETH_INTERFACE_RMII) && (!mac_lockup)) {
1089     eth_mac->PowerControl(ARM_POWER_OFF);
1090     eth_mac->PowerControl(ARM_POWER_FULL);
1091     eth_phy->PowerControl(ARM_POWER_OFF);
1092     eth_phy->Uninitialize();
1093   }
1094   if (mac_lockup) {
1095     TEST_MESSAGE("[WARNING] MAC is locked when PHY power is off");
1096   }
1097
1098   /* MAC Power off and uninitialize */
1099   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1100   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1101 }
1102
1103 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1104 /**
1105 \brief  Function: ETH_PHY_Config
1106 \details
1107 The function \b ETH_PHY_Config verifies the PHY functions
1108   - Initialize
1109   - Power on
1110   - SetInterface
1111   - SetMode
1112   - Power off
1113   - Uninitialize
1114 */
1115 void ETH_PHY_Config (void) {
1116
1117   /* MAC Initialize and power on */
1118   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1119   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1120
1121   /* Initialize and power on */
1122   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1123   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1124
1125   /* Configure ETH_PHY bus */
1126   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
1127
1128   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
1129
1130   /* Power off and uninitialize */
1131   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1132   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1133
1134   /* MAC Power off and uninitialize */
1135   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1136   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1137 }
1138
1139 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1140 /**
1141 \brief  Function: ETH_Loopback_Transfer
1142 \details
1143 The function \b ETH_Loopback_Transfer verifies data transfer via Ethernet with the following sequence:
1144   - Buffer allocation
1145   - Initialize
1146   - Power on
1147   - Set output buffer pattern
1148   - Transfer data chunks
1149   - Set output buffer with random data
1150   - Transfer data chunks
1151   - Transfer data by sending in two fragments
1152   - Power off
1153   - Uninitialize
1154
1155 \note
1156 The internal Ethernet MAC loopback is used as a data loopback, so there is no need to use an external loopback cable.
1157 */
1158 void ETH_Loopback_Transfer (void) {
1159   const uint16_t test_len[] = {
1160     28,36,40,44,45,46,47,48,49,50,55,60,65,70,75,80,85,90,95,100,110,120,127,128,
1161     129,140,150,160,170,180,190,196,200,220,240,250,256,270,300,325,350,375,400,
1162     425,450,475,500,511,512,513,525,550,575,600,625,650,700,750,800,850,900,950,
1163     1000,1024,1050,1100,1150,1200,1250,1300,1320,1420,1480,1490,1491,1492,1493,
1164     1494,1495,1496,1497,1498,1499,1500};
1165   const uint32_t test_num = ARRAY_SIZE(test_len);
1166   uint32_t i,cnt,tick;
1167
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; }
1175
1176   /* Initialize, power on and configure MAC */
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_ETH_MAC_LOOPBACK) == 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);
1184   osDelay (100);
1185   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
1186   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
1187   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
1188   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
1189
1190   /* Set output buffer pattern */
1191   for (i = 0; i < ETH_MTU; i+=2) {
1192     buffer_out[14+i] = 0x55;
1193     buffer_out[15+i] = 0xAA;
1194   }
1195
1196   /* Set Ethernet header */
1197   memcpy(&buffer_out[0], &mac_bcast, 6);
1198   memcpy(&buffer_out[6], &mac_addr,  6);
1199
1200   /* Transfer data chunks */
1201   for (cnt = 0; cnt < test_num; cnt++) {
1202     /* Clear input buffer */
1203     memset(buffer_in, 0, test_len[cnt]);
1204     /* Set Ethernet type/length */
1205     buffer_out[12] = test_len[cnt] >> 8;
1206     buffer_out[13] = test_len[cnt] & 0xFF;
1207     if (ETH_RunTransfer(buffer_out, buffer_in, 14+test_len[cnt], 0) != ARM_DRIVER_OK) {
1208       snprintf(str,sizeof(str),"[FAILED] Transfer block of %d bytes",test_len[cnt]);
1209       TEST_FAIL_MESSAGE(str);
1210     } else if (memcmp(buffer_in, buffer_out, 14+test_len[cnt]) != 0) {
1211       snprintf(str,sizeof(str),"[FAILED] Verify block of %d bytes",test_len[cnt]);
1212       TEST_FAIL_MESSAGE(str);
1213     } else TEST_PASS();
1214   }
1215
1216   /* Set output buffer with random data */
1217   srand(GET_SYSTICK());
1218   for (i = 0; i < ETH_MTU; i++) {
1219     buffer_out[14+cnt] = (uint8_t)rand();
1220   }
1221
1222   /* Transfer data chunks */
1223   for (cnt = 0; cnt < test_num; cnt++) {
1224     /* Clear input buffer */
1225     memset(buffer_in, 0, test_len[cnt]);
1226     /* Set Ethernet type/length */
1227     buffer_out[12] = test_len[cnt] >> 8;
1228     buffer_out[13] = test_len[cnt] & 0xFF;
1229     if (ETH_RunTransfer(buffer_out, buffer_in, 14+test_len[cnt], 0) != ARM_DRIVER_OK) {
1230       snprintf(str,sizeof(str),"[FAILED] Transfer block of %d bytes",test_len[cnt]);
1231       TEST_FAIL_MESSAGE(str);
1232     } else if (memcmp(buffer_in, buffer_out, 14+test_len[cnt]) != 0) {
1233       snprintf(str,sizeof(str),"[FAILED] Verify block of %d bytes",test_len[cnt]);
1234       TEST_FAIL_MESSAGE(str);
1235     } else TEST_PASS();
1236   }
1237
1238   /* Block transfer in two fragments: header and data */
1239   for (cnt = 0; cnt < test_num; cnt++) {
1240     /* Clear input buffer */
1241     memset(buffer_in, 0, test_len[cnt]);
1242     /* Set Ethernet type/length */
1243     buffer_out[12] = test_len[cnt] >> 8;
1244     buffer_out[13] = test_len[cnt] & 0xFF;
1245     if (ETH_RunTransfer(buffer_out, buffer_in, 14+test_len[cnt], 0) != ARM_DRIVER_OK) {
1246       snprintf(str,sizeof(str),"[FAILED] Fragmented block transfer of %d bytes",test_len[cnt]);
1247       TEST_FAIL_MESSAGE(str);
1248     } else if (memcmp(buffer_in, buffer_out, 14+test_len[cnt]) != 0) {
1249       snprintf(str,sizeof(str),"[FAILED] Fragmented block check of %d bytes",test_len[cnt]);
1250       TEST_FAIL_MESSAGE(str);
1251     } else TEST_PASS();
1252   }
1253
1254   /* Power off and uninitialize */
1255   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1256   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1257   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1258   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1259
1260   /* Free buffers */
1261   free(buffer_out);
1262   free(buffer_in);
1263 }
1264
1265 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1266 /**
1267 \brief  Function: ETH_Loopback_External
1268 \details
1269 The function \b ETH_Loopback_External verifies data transfer via Ethernet with the following sequence:
1270   - Buffer allocation
1271   - Initialize
1272   - Power on
1273   - Set output buffer pattern
1274   - Transfer data on PHY internal loopback
1275   - Ethernet connection
1276   - Transfer data on external cable loopback
1277   - Power off
1278   - Uninitialize
1279
1280 \note
1281 An external loopback cable is required for this test.
1282 */
1283 void ETH_Loopback_External (void) {
1284   ARM_ETH_LINK_INFO info;
1285   uint32_t i,cnt,tick;
1286
1287   /* Allocate buffers, add space for Ethernet header */
1288   buffer_out = (uint8_t *)malloc(14+ETH_MTU);
1289   TEST_ASSERT(buffer_out != NULL);
1290   if (buffer_out == NULL) return;
1291   buffer_in = (uint8_t *)malloc(14+ETH_MTU);
1292   TEST_ASSERT(buffer_in != NULL);
1293   if (buffer_in == NULL) { free(buffer_out); return; }
1294
1295   /* Initialize, power on and configure MAC and PHY */
1296   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1297   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1298   TEST_ASSERT(eth_mac->SetMacAddress(&mac_addr) == ARM_DRIVER_OK);
1299   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
1300     ARM_ETH_MAC_ADDRESS_BROADCAST) == ARM_DRIVER_OK);
1301   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1302   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1303   osDelay (100);
1304   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
1305   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_SPEED_100M |
1306    ARM_ETH_PHY_DUPLEX_FULL | ARM_ETH_PHY_LOOPBACK) == ARM_DRIVER_OK);
1307   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
1308   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
1309
1310   /* Fill output buffer */
1311   for (cnt = 0; cnt < ETH_MTU; cnt++) {
1312     buffer_out[14+cnt] = (cnt ^ 0x20) & 0x7F;
1313   }
1314
1315   /* Set Ethernet header */
1316   memcpy(&buffer_out[0], &mac_bcast, 6);
1317   memcpy(&buffer_out[6], &mac_addr,  6);
1318
1319   /* Set Ethernet type/length */
1320   buffer_out[12] = (ETH_MTU >> 8) & 0xFF;
1321   buffer_out[13] =  ETH_MTU       & 0xFF;
1322
1323   /* Check PHY internal loopback */
1324   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_SPEED_100M |
1325     ARM_ETH_PHY_DUPLEX_FULL | ARM_ETH_PHY_LOOPBACK) == ARM_DRIVER_OK);
1326   osDelay(200);
1327
1328   /* Clear input buffer*/
1329   memset(buffer_in, 0, 14+ETH_MTU);
1330   if (ETH_RunTransfer(buffer_out, buffer_in, 14+ETH_MTU, 0) != ARM_DRIVER_OK) {
1331     TEST_MESSAGE("[WARNING] PHY internal loopback is not active");
1332   } else if (memcmp(buffer_in, buffer_out, 14+ETH_MTU) != 0) {
1333     TEST_FAIL_MESSAGE("[FAILED] Verify received data");
1334   } else TEST_PASS();
1335
1336   /* Check external cable loopback */
1337   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
1338
1339   /* Check Ethernet link */
1340   tick = GET_SYSTICK();
1341   while (eth_phy->GetLinkState() != ARM_ETH_LINK_UP) {
1342     if ((GET_SYSTICK() - tick) >= SYSTICK_MICROSEC(ETH_LINK_TIMEOUT*1000)) {
1343       TEST_FAIL_MESSAGE("[FAILED] Link down, connect Ethernet cable");
1344       goto exit;
1345     }
1346   }
1347
1348   info = eth_phy->GetLinkInfo();
1349   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE,
1350     (uint32_t)info.speed  << ARM_ETH_MAC_SPEED_Pos  |
1351     (uint32_t)info.duplex << ARM_ETH_MAC_DUPLEX_Pos |
1352     ARM_ETH_MAC_ADDRESS_BROADCAST) == ARM_DRIVER_OK);
1353
1354   /* Clear input buffer */
1355   memset(buffer_in, 0, 14+ETH_MTU);
1356   if (ETH_RunTransfer(buffer_out, buffer_in, 14+ETH_MTU, 0) != ARM_DRIVER_OK) {
1357     TEST_FAIL_MESSAGE("[FAILED] Transfer external cable loopback");
1358   } else if (memcmp(buffer_in, buffer_out, 14+ETH_MTU) != 0) {
1359     TEST_FAIL_MESSAGE("[FAILED] Verify received data");
1360   } else TEST_PASS();
1361
1362   /* Power off and uninitialize */
1363 exit:
1364   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1365   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1366   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1367   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1368
1369   /* Free buffers */
1370   free(buffer_out);
1371   free(buffer_in);
1372 }
1373
1374 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1375 /**
1376 \brief Function: ETH_MAC_PTP_ControlTimer
1377 \details
1378 The function \b ETH_MAC_PTP_ControlTimer verifies the PTP \b ControlTimer function with the sequence:
1379   - Initialize
1380   - Power on
1381   - Set Time
1382   - Adjust Clock
1383   - Increment Time
1384   - Decrement Time
1385   - Set Alarm
1386   - Power off
1387   - Uninitialize
1388 */
1389 void ETH_MAC_PTP_ControlTimer (void) {
1390   ARM_ETH_MAC_TIME time1,time2;
1391   int64_t t,t1ns,t2ns,overhead;
1392   double rate;
1393
1394   /* Get capabilities */
1395   if (!capab.precision_timer) {
1396     TEST_MESSAGE("[WARNING] Precision Time Protocol is not supported");
1397     return;
1398   }
1399
1400   /* Initialize, power on and configure MAC */
1401   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1402   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1403
1404   /* Set Time -------------------------------------------------------------------------------- */
1405   time1.sec = 0U;
1406   time1.ns  = 0U;
1407   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_TIME, &time1) == ARM_DRIVER_OK);
1408
1409   /* Check System Time */
1410   osDelay(1U);
1411   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1412   osDelay(PTP_TIME_REF);
1413   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1414
1415   /* Get timestamps in nanoseconds */
1416   t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1417   t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1418   t    = t2ns - t1ns - PTP_TIME_REF_NS;
1419
1420   /* Check timestamps difference */
1421   if (llabs(t) > ETH_PTP_TOLERANCE) {
1422     snprintf(str,sizeof(str),"[WARNING] PTP measured time is %lldns from expected", t);
1423     TEST_MESSAGE(str);
1424   } else TEST_PASS();
1425
1426   /* Adjust clock - Set correction factor ---------------------------------------------------- */
1427   /* Calculate rate and convert it to q31 format */
1428   rate     = (double)PTP_TIME_REF_NS / (t2ns-t1ns);
1429   time1.ns = (uint32_t)(0x80000000U*rate);
1430   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_ADJUST_CLOCK, &time1) == ARM_DRIVER_OK);
1431
1432   /* Check System Time after adjusting clock */
1433   osDelay(1U);
1434   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1435   osDelay(PTP_TIME_REF);
1436   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1437
1438   /* Get timestamps in nanoseconds */
1439   t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1440   t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1441   t    = t2ns - t1ns - PTP_TIME_REF_NS;
1442
1443   /* Check timestamps difference */
1444   if (llabs(t) > ETH_PTP_TOLERANCE) {
1445     snprintf(str,sizeof(str),"[WARNING] PTP measured time with adj clk is %lldns from expected", t);
1446     TEST_MESSAGE(str);
1447   } else TEST_PASS();
1448
1449   /* Measure time overhead for increment/decrement calls ------------------------------------- */
1450   time2.sec = 0;
1451   time2.ns  = 0;
1452   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1453   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_INC_TIME, &time2) == ARM_DRIVER_OK);
1454   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1455   t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1456   t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1457   overhead = t2ns - t1ns;
1458
1459   /* Increment time -------------------------------------------------------------------------- */
1460   time2.sec = PTP_TIME_REF/1000U;
1461   time2.ns  = (PTP_TIME_REF-time2.sec*1000U)*1000000U;
1462   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1463   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_INC_TIME, &time2) == ARM_DRIVER_OK);
1464   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1465
1466   /* Get timestamps in nanoseconds */
1467   t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1468   t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1469   t    = t2ns - t1ns - PTP_TIME_REF_NS - overhead;
1470
1471   /* Check timestamps difference */
1472   if (llabs(t) > ETH_PTP_TOLERANCE) {
1473     snprintf(str,sizeof(str),"[WARNING] PTP incremented time is %lldns from expected", t);
1474     TEST_MESSAGE(str);
1475   } else TEST_PASS();
1476
1477   /* Decrement time -------------------------------------------------------------------------- */
1478   time2.sec =  PTP_TIME_REF/1000U;
1479   time2.ns  = (PTP_TIME_REF-time2.sec*1000U)*1000000U;
1480   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1481   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_DEC_TIME, &time2) == ARM_DRIVER_OK);
1482   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1483
1484   /* Get timestamps in nanoseconds */
1485   t1ns = (int64_t)time1.sec*PTP_S_NS + time1.ns;
1486   t2ns = (int64_t)time2.sec*PTP_S_NS + time2.ns;
1487   t    = t2ns - t1ns + PTP_TIME_REF_NS - overhead;
1488
1489   /* Check timestamps difference */
1490   if (llabs(t) > ETH_PTP_TOLERANCE) {
1491     snprintf(str,sizeof(str),"[WARNING] PTP decremented time is %lldns from expected", t);
1492     TEST_MESSAGE(str);
1493   } else TEST_PASS();
1494
1495   /* Set Alarm (1s) -------------------------------------------------------------------------- */
1496   Event &= ~ARM_ETH_MAC_EVENT_TIMER_ALARM;
1497   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1498   time1.sec += 1U;
1499   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_ALARM, &time1) == ARM_DRIVER_OK);
1500
1501   /* Check alarm event after 999ms */
1502   osDelay(999U);
1503   if ((Event & ARM_ETH_MAC_EVENT_TIMER_ALARM) != 0)  {
1504     TEST_FAIL_MESSAGE("[FAILED] PTP Alarm event triggered too early");
1505   } else TEST_PASS();
1506
1507   /* Check alarm event after 1001ms */
1508   osDelay(2U);
1509   if ((Event & ARM_ETH_MAC_EVENT_TIMER_ALARM) == 0)  {
1510     TEST_FAIL_MESSAGE("[FAILED] PTP Alarm event timeout");
1511   } else TEST_PASS();
1512
1513   /* Power off and uninitialize */
1514   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1515   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1516 }
1517
1518 /*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
1519 /**
1520 \brief Function: ETH_Loopback_PTP
1521 \details
1522 The function \b ETH_Loopback_PTP verifies the Precision Time Protocol functions \b ControlTimer, \b GetRxFrameTime and
1523 \b GetTxFrameTime with the sequence:
1524   - Initialize
1525   - Power on
1526   - Set Control Timer
1527   - Transfer a frame
1528   - Get TX frame time
1529   - Get RX frame time
1530   - Power off
1531   - Uninitialize
1532
1533 \note
1534 The internal Ethernet MAC loopback is used as the data loopback.
1535 */
1536 void ETH_Loopback_PTP (void) {
1537   ARM_ETH_MAC_TIME time1,time2;
1538   uint32_t tick;
1539
1540   // PTP over Ethernet IPv4 sample frame
1541   const uint8_t PTP_frame[] = {
1542     0x01,0x00,0x5e,0x00,0x01,0x81,0x02,0x30,0x05,0x1d,0x1e,0x27,0x08,0x00,0x45,0x00,
1543     0x00,0x98,0x00,0x5d,0x40,0x00,0x01,0x11,0x29,0x68,0x0a,0x0a,0x64,0x05,0xe0,0x00,
1544     0x01,0x81,0x01,0x3f,0x01,0x3f,0x00,0x84,0xc0,0x7b,0x00,0x01,0x00,0x01,0x5f,0x44,
1545     0x46,0x4c,0x54,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,
1546     0x00,0x30,0x05,0x1d,0x1e,0x27,0x00,0x01,0x00,0x5e,0x00,0x00,0x00,0x08,0x00,0x00,
1547     0x00,0x00,0x45,0x5b,0x0a,0x38,0x0e,0xb9,0x26,0x58,0x00,0x00,0x00,0x00,0x00,0x01,
1548     0x00,0x30,0x05,0x1d,0x1e,0x27,0x00,0x00,0x00,0x5e,0x00,0x00,0x00,0x04,0x44,0x46,
1549     0x4c,0x54,0x00,0x00,0xf0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
1550     0xf0,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x44,0x46,0x4c,0x54,0x00,0x01,
1551     0x00,0x30,0x05,0x1d,0x1e,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1552     0x00,0x00,0x00,0x00,0x00,0x00
1553   };
1554   const uint32_t PTP_frame_len = sizeof(PTP_frame);
1555
1556   /* Get capabilities */
1557   if (!capab.precision_timer) {
1558     TEST_MESSAGE("[WARNING] Precision Time Protocol is not supported");
1559     return;
1560   }
1561
1562   /* Allocate buffer */
1563   buffer_in = (uint8_t *)malloc(PTP_frame_len);
1564   TEST_ASSERT(buffer_in != NULL);
1565   if (buffer_in == NULL) return;
1566
1567   /* Initialize, power on and configure MAC and PHY */
1568   TEST_ASSERT(eth_mac->Initialize(cb_event) == ARM_DRIVER_OK);
1569   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1570   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONFIGURE, ARM_ETH_MAC_SPEED_100M | ARM_ETH_MAC_DUPLEX_FULL |
1571     ARM_ETH_MAC_ADDRESS_BROADCAST | ARM_ETH_MAC_ADDRESS_ALL | ARM_ETH_MAC_LOOPBACK) == ARM_DRIVER_OK);
1572   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_RX, 1) == ARM_DRIVER_OK);
1573   TEST_ASSERT(eth_mac->Control(ARM_ETH_MAC_CONTROL_TX, 1) == ARM_DRIVER_OK);
1574   TEST_ASSERT(eth_phy->Initialize(eth_mac->PHY_Read, eth_mac->PHY_Write) == ARM_DRIVER_OK);
1575   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK);
1576   osDelay (100);
1577   TEST_ASSERT(eth_phy->SetInterface(capab.media_interface) == ARM_DRIVER_OK);
1578   TEST_ASSERT(eth_phy->SetMode(ARM_ETH_PHY_AUTO_NEGOTIATE) == ARM_DRIVER_OK);
1579
1580   /* Set Time */
1581   time1.sec = 0U;
1582   time1.ns  = 0U;
1583   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_SET_TIME, &time1) == ARM_DRIVER_OK);
1584
1585   /* Check timestamps - verify if control timer is running */
1586   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time1) == ARM_DRIVER_OK);
1587   TEST_ASSERT(eth_mac->ControlTimer(ARM_ETH_MAC_TIMER_GET_TIME, &time2) == ARM_DRIVER_OK);
1588   TEST_ASSERT((time2.sec==time1.sec)?(time2.ns>time1.ns):(time2.sec>time1.sec));
1589
1590   /* Transfer frame */
1591   TEST_ASSERT(eth_mac->SendFrame(PTP_frame, PTP_frame_len, ARM_ETH_MAC_TX_FRAME_TIMESTAMP) == ARM_DRIVER_OK);
1592   tick = GET_SYSTICK();
1593   while (eth_mac->GetRxFrameSize() == 0) {
1594     if ((GET_SYSTICK() - tick) >= SYSTICK_MICROSEC(ETH_TRANSFER_TIMEOUT*1000)) {
1595       TEST_FAIL_MESSAGE("[FAILED] Transfer timeout");
1596       break;
1597     }
1598   }
1599
1600   /* Get TX Frame Time */
1601   TEST_ASSERT(eth_mac->GetTxFrameTime(&time1) == ARM_DRIVER_OK);
1602
1603   /* Get RX Frame Time */
1604   TEST_ASSERT(eth_mac->GetRxFrameTime(&time2) == ARM_DRIVER_OK);
1605
1606   /* Check timestamps */
1607   TEST_ASSERT((time2.sec==time1.sec) ? (time2.ns>time1.ns) : (time2.sec>time1.sec));
1608
1609   /* Check frame */
1610   eth_mac->ReadFrame(buffer_in, PTP_frame_len);
1611   TEST_ASSERT(memcmp(buffer_in, PTP_frame, PTP_frame_len) == 0);
1612
1613   /* Power off and uninitialize */
1614   TEST_ASSERT(eth_phy->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1615   TEST_ASSERT(eth_phy->Uninitialize() == ARM_DRIVER_OK);
1616   TEST_ASSERT(eth_mac->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK);
1617   TEST_ASSERT(eth_mac->Uninitialize() == ARM_DRIVER_OK);
1618
1619   /* Free buffer */
1620   free(buffer_in);
1621 }
1622
1623
1624 /**
1625 @}
1626 */
1627 // end of group dv_eth