2 FreeRTOS V7.0.1 - Copyright (C) 2011 Real Time Engineers Ltd.
\r
5 ***************************************************************************
\r
7 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
8 * Complete, revised, and edited pdf reference manuals are also *
\r
11 * Purchasing FreeRTOS documentation will not only help you, by *
\r
12 * ensuring you get running as quickly as possible and with an *
\r
13 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
14 * the FreeRTOS project to continue with its mission of providing *
\r
15 * professional grade, cross platform, de facto standard solutions *
\r
16 * for microcontrollers - completely free of charge! *
\r
18 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
20 * Thank you for using FreeRTOS, and thank you for your support! *
\r
22 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\r
27 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
28 the terms of the GNU General Public License (version 2) as published by the
\r
29 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
30 >>>NOTE<<< The modification to the GPL is included to allow you to
\r
31 distribute a combined work that includes FreeRTOS without being obliged to
\r
32 provide the source code for proprietary components outside of the FreeRTOS
\r
33 kernel. FreeRTOS is distributed in the hope that it will be useful, but
\r
34 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
35 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
36 more details. You should have received a copy of the GNU General Public
\r
37 License and the FreeRTOS license exception along with FreeRTOS; if not it
\r
38 can be viewed here: http://www.freertos.org/a00114.html and also obtained
\r
39 by writing to Richard Barry, contact details for whom are available on the
\r
44 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
47 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
50 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
51 licensing and training services.
\r
54 /* Freescale includes. */
\r
56 #include "eth_phy.h"
\r
60 /* FreeRTOS includes. */
\r
61 #include "FreeRTOS.h"
\r
66 #include "net/uip.h"
\r
68 /* The time to wait between attempts to obtain a free buffer. */
\r
69 #define emacBUFFER_WAIT_DELAY_ms ( 3 / portTICK_RATE_MS )
\r
71 /* The number of times emacBUFFER_WAIT_DELAY_ms should be waited before giving
\r
72 up on attempting to obtain a free buffer all together. */
\r
73 #define emacBUFFER_WAIT_ATTEMPTS ( 30 )
\r
75 /* The number of Rx descriptors. */
\r
76 #define emacNUM_RX_DESCRIPTORS 8
\r
78 /* The number of Tx descriptors. When using uIP there is not point in having
\r
80 #define emacNUM_TX_BUFFERS 2
\r
82 /* The total number of EMAC buffers to allocate. */
\r
83 #define emacNUM_BUFFERS ( emacNUM_RX_DESCRIPTORS + emacNUM_TX_BUFFERS )
\r
85 /* The time to wait for the Tx descriptor to become free. */
\r
86 #define emacTX_WAIT_DELAY_ms ( 10 / portTICK_RATE_MS )
\r
88 /* The total number of times to wait emacTX_WAIT_DELAY_ms for the Tx descriptor to
\r
90 #define emacTX_WAIT_ATTEMPTS ( 50 )
\r
92 #define emacTX_INTERRUPT_NO ( 76 )
\r
93 #define emacRX_INTERRUPT_NO ( 77 )
\r
94 #define emacERROR_INTERRUPT_NO ( 78 )
\r
95 #define emacLINK_DELAY ( 500 / portTICK_RATE_MS )
\r
96 #define emacPHY_STATUS ( 0x1F )
\r
97 #define emacPHY_DUPLEX_STATUS ( 4 << 2 )
\r
98 #define emacPHY_SPEED_STATUS ( 1 << 2 )
\r
100 /*-----------------------------------------------------------*/
\r
103 * Initialise both the Rx and Tx descriptors.
\r
105 static void prvInitialiseDescriptors( void );
\r
108 * Return a pointer to a free buffer within xEthernetBuffers.
\r
110 static unsigned char *prvGetNextBuffer( void );
\r
113 * Return a buffer to the list of free buffers.
\r
115 static void prvReturnBuffer( unsigned char *pucBuffer );
\r
118 * Examine the status of the next Rx descriptor to see if it contains new data.
\r
120 static unsigned short prvCheckRxStatus( void );
\r
123 * Something has gone wrong with the descriptor usage. Reset all the buffers
\r
126 static void prvResetEverything( void );
\r
128 /*-----------------------------------------------------------*/
\r
130 /* The buffers and descriptors themselves. */
\r
131 #pragma data_alignment=16
\r
132 volatile NBUF xRxDescriptors[ emacNUM_RX_DESCRIPTORS ];
\r
134 #pragma data_alignment=16
\r
135 volatile NBUF xTxDescriptors[ emacNUM_TX_BUFFERS ];
\r
137 #pragma data_alignment=16
\r
138 char xEthernetBuffers[ emacNUM_BUFFERS ][ UIP_BUFSIZE ];
\r
140 /* Used to indicate which buffers are free and which are in use. If an index
\r
141 contains 0 then the corresponding buffer in xEthernetBuffers is free, otherwise
\r
142 the buffer is in use or about to be used. */
\r
143 static unsigned char ucBufferInUse[ emacNUM_BUFFERS ];
\r
145 /* Points to the Rx descriptor currently in use. */
\r
146 static volatile NBUF *pxCurrentRxDesc = NULL;
\r
148 /* pxCurrentRxDesc points to descriptor within the xRxDescriptors array that
\r
149 has an index defined by ulRxDescriptorIndex. */
\r
150 static unsigned long ulRxDescriptorIndex = 0UL;
\r
152 /* The buffer used by the uIP stack to both receive and send. This points to
\r
153 one of the Ethernet buffers when its actually in use. */
\r
154 unsigned char *uip_buf = NULL;
\r
156 /*-----------------------------------------------------------*/
\r
157 #define ENET_HARDWARE_CHECKSUM 0 //_RB_ for test only
\r
158 void vEMACInit( void )
\r
161 extern int periph_clk_khz;
\r
162 const unsigned portCHAR ucMACAddress[] =
\r
164 configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5
\r
167 /* Enable the ENET clock. */
\r
168 SIM_SCGC2 |= SIM_SCGC2_ENET_MASK;
\r
170 /* Allow concurrent access to MPU controller to avoid bus errors. */
\r
173 prvInitialiseDescriptors();
\r
175 /* Reset and enable. */
\r
176 ENET_ECR = ENET_ECR_RESET_MASK;
\r
178 /* Wait at least 8 clock cycles */
\r
181 /* Start the MII interface*/
\r
182 mii_init( 0, periph_clk_khz / 1000L );
\r
184 /* Configure the transmit interrupt. */
\r
185 set_irq_priority( emacTX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
\r
186 enable_irq( emacTX_INTERRUPT_NO );
\r
188 /* Configure the receive interrupt. */
\r
189 set_irq_priority( emacRX_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
\r
190 enable_irq( emacRX_INTERRUPT_NO );
\r
192 /* Configure the error interrupt. */
\r
193 set_irq_priority( emacERROR_INTERRUPT_NO, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY );
\r
194 enable_irq( emacERROR_INTERRUPT_NO );
\r
196 /* Configure the pins to the PHY - RMII mode used. */
\r
197 PORTB_PCR0 = PORT_PCR_MUX( 4 ); /* RMII0_MDIO / MII0_MDIO. */
\r
198 PORTB_PCR1 = PORT_PCR_MUX( 4 ); /* RMII0_MDC / MII0_MDC */
\r
199 PORTA_PCR14 = PORT_PCR_MUX( 4 ); /* RMII0_CRS_DV / MII0_RXDV */
\r
200 PORTA_PCR12 = PORT_PCR_MUX( 4 ); /* RMII0_RXD1 / MII0_RXD1 */
\r
201 PORTA_PCR13 = PORT_PCR_MUX( 4 ); /* RMII0_RXD0/MII0_RXD0 */
\r
202 PORTA_PCR15 = PORT_PCR_MUX( 4 ); /* RMII0_TXEN/MII0_TXEN */
\r
203 PORTA_PCR16 = PORT_PCR_MUX( 4 ); /* RMII0_TXD0/MII0_TXD0 */
\r
204 PORTA_PCR17 = PORT_PCR_MUX( 4 ); /* RMII0_TXD1/MII0_TXD1 */
\r
206 /* Is there communication with the PHY? */
\r
209 vTaskDelay( emacLINK_DELAY );
\r
211 mii_read( 0, configPHY_ADDRESS, PHY_PHYIDR1, &iData );
\r
213 } while( iData == 0xFFFF );
\r
215 /* Start to auto negotiate. */
\r
216 mii_write( 0, configPHY_ADDRESS, PHY_BMCR, ( PHY_BMCR_AN_RESTART | PHY_BMCR_AN_ENABLE ) );
\r
218 /* Wait for auto negotiate to complete. */
\r
221 vTaskDelay( emacLINK_DELAY );
\r
222 mii_read( 0, configPHY_ADDRESS, PHY_BMSR, &iData );
\r
224 } while( !( iData & PHY_BMSR_AN_COMPLETE ) );
\r
226 /* A link has been established. What was negotiated? */
\r
228 mii_read( 0, configPHY_ADDRESS, emacPHY_STATUS, &iData );
\r
230 /* Clear the Individual and Group Address Hash registers */
\r
236 /* Set the Physical Address for the selected ENET */
\r
237 enet_set_address( 0, ucMACAddress );
\r
239 ENET_RCR = ENET_RCR_MAX_FL( UIP_BUFSIZE ) | ENET_RCR_MII_MODE_MASK | ENET_RCR_CRCFWD_MASK | ENET_RCR_RMII_MODE_MASK;
\r
241 /* Clear the control registers. */
\r
244 if( iData & emacPHY_DUPLEX_STATUS )
\r
247 ENET_RCR &= ( unsigned long )~ENET_RCR_DRT_MASK;
\r
248 ENET_TCR |= ENET_TCR_FDEN_MASK;
\r
253 ENET_RCR |= ENET_RCR_DRT_MASK;
\r
254 ENET_TCR &= (unsigned portLONG)~ENET_TCR_FDEN_MASK;
\r
257 if( iData & emacPHY_SPEED_STATUS )
\r
260 ENET_RCR |= ENET_RCR_RMII_10T_MASK;
\r
263 ENET_ECR = ENET_ECR_EN1588_MASK;
\r
267 // Enable Ethernet header alignment for rx
\r
269 | ENET_RACC_SHIFT16_MASK
\r
272 // Enable Ethernet header alignment for tx
\r
274 | ENET_TACC_SHIFT16_MASK
\r
278 /* Store and forward checksum. */
\r
279 ENET_TFWR = ENET_TFWR_STRFWD_MASK;
\r
281 /* Set Rx Buffer Size */
\r
282 ENET_MRBR = ( unsigned short ) UIP_BUFSIZE;
\r
284 /* Point to the start of the circular Rx buffer descriptor queue */
\r
285 ENET_RDSR = ( unsigned long ) &( xRxDescriptors[ 0 ] );
\r
287 /* Point to the start of the circular Tx buffer descriptor queue */
\r
288 ENET_TDSR = ( unsigned long ) &( xTxDescriptors[ 0 ] );
\r
290 /* Clear all ENET interrupt events */
\r
291 ENET_EIR = ( unsigned long ) -1;
\r
293 /* Enable interrupts. */
\r
296 | ENET_EIMR_RXF_MASK/*FSL: only for complete frame, not partial buffer descriptor | ENET_EIMR_RXB_MASK*/
\r
298 | ENET_EIMR_TXF_MASK/*FSL: only for complete frame, not partial buffer descriptor | ENET_EIMR_TXB_MASK*/
\r
300 | ENET_EIMR_UN_MASK | ENET_EIMR_RL_MASK | ENET_EIMR_LC_MASK | ENET_EIMR_BABT_MASK | ENET_EIMR_BABR_MASK | ENET_EIMR_EBERR_MASK
\r
303 /* Enable the MAC itself. */
\r
304 ENET_ECR |= ENET_ECR_ETHEREN_MASK;
\r
306 /* Indicate that there have been empty receive buffers produced */
\r
307 ENET_RDAR = ENET_RDAR_RDAR_MASK;
\r
309 /*-----------------------------------------------------------*/
\r
311 static void prvInitialiseDescriptors( void )
\r
313 volatile NBUF *pxDescriptor;
\r
316 for( x = 0; x < emacNUM_BUFFERS; x++ )
\r
318 /* Ensure none of the buffers are shown as in use at the start. */
\r
319 ucBufferInUse[ x ] = pdFALSE;
\r
322 /* Initialise the Rx descriptors. */
\r
323 for( x = 0; x < emacNUM_RX_DESCRIPTORS; x++ )
\r
325 pxDescriptor = &( xRxDescriptors[ x ] );
\r
326 pxDescriptor->data = ( uint8_t* ) &( xEthernetBuffers[ x ][ 0 ] );
\r
327 pxDescriptor->data = ( uint8_t* ) __REV( ( unsigned long ) pxDescriptor->data );
\r
328 pxDescriptor->length = 0;
\r
329 pxDescriptor->status = RX_BD_E;
\r
330 pxDescriptor->bdu = 0;
\r
331 pxDescriptor->ebd_status = RX_BD_INT;
\r
333 /* Mark this buffer as in use. */
\r
334 ucBufferInUse[ x ] = pdTRUE;
\r
337 /* The last descriptor points back to the start. */
\r
338 pxDescriptor->status |= RX_BD_W;
\r
340 /* Initialise the Tx descriptors. */
\r
341 for( x = 0; x < emacNUM_TX_BUFFERS; x++ )
\r
343 pxDescriptor = &( xTxDescriptors[ x ] );
\r
345 /* A buffer is not allocated to the Tx descriptor until a send is
\r
346 actually required. */
\r
347 pxDescriptor->data = NULL;
\r
348 pxDescriptor->length = 0;
\r
349 pxDescriptor->status = TX_BD_TC;
\r
350 pxDescriptor->ebd_status = TX_BD_INT;
\r
353 /* The last descriptor points back to the start. */
\r
354 pxDescriptor->status |= TX_BD_W;
\r
356 /* Use the first Rx descriptor to start with. */
\r
357 ulRxDescriptorIndex = 0UL;
\r
358 pxCurrentRxDesc = &( xRxDescriptors[ 0 ] );
\r
360 /*-----------------------------------------------------------*/
\r
362 void vEMACWrite( void )
\r
366 /* Wait until the second transmission of the last packet has completed. */
\r
367 for( x = 0; x < emacTX_WAIT_ATTEMPTS; x++ )
\r
369 if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )
\r
371 /* Descriptor is still active. */
\r
372 vTaskDelay( emacTX_WAIT_DELAY_ms );
\r
380 /* Is the descriptor free after waiting for it? */
\r
381 if( ( xTxDescriptors[ 1 ].status & TX_BD_R ) != 0 )
\r
383 /* Something has gone wrong. */
\r
384 prvResetEverything();
\r
387 /* Setup both descriptors to transmit the frame. */
\r
388 xTxDescriptors[ 0 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );
\r
389 xTxDescriptors[ 0 ].length = __REVSH( uip_len );
\r
390 xTxDescriptors[ 1 ].data = ( uint8_t * ) __REV( ( unsigned long ) uip_buf );
\r
391 xTxDescriptors[ 1 ].length = __REVSH( uip_len );
\r
393 /* uip_buf is being sent by the Tx descriptor. Allocate a new buffer
\r
394 for use by the stack. */
\r
395 uip_buf = prvGetNextBuffer();
\r
397 /* Clear previous settings and go. */
\r
398 xTxDescriptors[ 0 ].status |= ( TX_BD_R | TX_BD_L );
\r
399 xTxDescriptors[ 1 ].status |= ( TX_BD_R | TX_BD_L );
\r
401 /* Start the Tx. */
\r
402 ENET_TDAR = ENET_TDAR_TDAR_MASK;
\r
404 /*-----------------------------------------------------------*/
\r
406 static unsigned char *prvGetNextBuffer( void )
\r
409 unsigned char *pucReturn = NULL;
\r
410 unsigned long ulAttempts = 0;
\r
412 while( pucReturn == NULL )
\r
414 /* Look through the buffers to find one that is not in use by
\r
416 for( x = 0; x < emacNUM_BUFFERS; x++ )
\r
418 if( ucBufferInUse[ x ] == pdFALSE )
\r
420 ucBufferInUse[ x ] = pdTRUE;
\r
421 pucReturn = ( unsigned char * ) &( xEthernetBuffers[ x ][ 0 ] );
\r
426 /* Was a buffer found? */
\r
427 if( pucReturn == NULL )
\r
431 if( ulAttempts >= emacBUFFER_WAIT_ATTEMPTS )
\r
436 /* Wait then look again. */
\r
437 vTaskDelay( emacBUFFER_WAIT_DELAY_ms );
\r
443 /*-----------------------------------------------------------*/
\r
445 static void prvResetEverything( void )
\r
447 /* Temporary code just to see if this gets called. This function has not
\r
448 been implemented. */
\r
449 portDISABLE_INTERRUPTS();
\r
452 /*-----------------------------------------------------------*/
\r
454 unsigned short usEMACRead( void )
\r
456 unsigned short usBytesReceived;
\r
458 usBytesReceived = prvCheckRxStatus();
\r
459 usBytesReceived = __REVSH( usBytesReceived );
\r
461 if( usBytesReceived > 0 )
\r
463 /* Mark the pxDescriptor buffer as free as uip_buf is going to be set to
\r
464 the buffer that contains the received data. */
\r
465 prvReturnBuffer( uip_buf );
\r
467 /* Point uip_buf to the data about to be processed. */
\r
468 uip_buf = ( void * ) pxCurrentRxDesc->data;
\r
469 uip_buf = ( void * ) __REV( ( unsigned long ) uip_buf );
\r
471 /* Allocate a new buffer to the descriptor, as uip_buf is now using it's
\r
473 pxCurrentRxDesc->data = ( uint8_t * ) prvGetNextBuffer();
\r
474 pxCurrentRxDesc->data = ( uint8_t* ) __REV( ( unsigned long ) pxCurrentRxDesc->data );
\r
476 /* Prepare the descriptor to go again. */
\r
477 pxCurrentRxDesc->status |= RX_BD_E;
\r
479 /* Move onto the next buffer in the ring. */
\r
480 ulRxDescriptorIndex++;
\r
481 if( ulRxDescriptorIndex >= emacNUM_RX_DESCRIPTORS )
\r
483 ulRxDescriptorIndex = 0UL;
\r
485 pxCurrentRxDesc = &( xRxDescriptors[ ulRxDescriptorIndex ] );
\r
487 /* Restart Ethernet if it has stopped */
\r
488 ENET_RDAR = ENET_RDAR_RDAR_MASK;
\r
491 return usBytesReceived;
\r
493 /*-----------------------------------------------------------*/
\r
495 static void prvReturnBuffer( unsigned char *pucBuffer )
\r
499 /* Return a buffer to the pool of free buffers. */
\r
500 for( ul = 0; ul < emacNUM_BUFFERS; ul++ )
\r
502 if( &( xEthernetBuffers[ ul ][ 0 ] ) == ( void * ) pucBuffer )
\r
504 ucBufferInUse[ ul ] = pdFALSE;
\r
509 /*-----------------------------------------------------------*/
\r
511 static unsigned short prvCheckRxStatus( void )
\r
513 unsigned long usReturn = 0;
\r
515 if( ( pxCurrentRxDesc->status & RX_BD_E ) != 0 )
\r
517 /* Current descriptor is still active. */
\r
521 /* The descriptor contains a frame. Because of the size of the buffers
\r
522 the frame should always be complete. */
\r
523 usReturn = pxCurrentRxDesc->length;
\r
528 /*-----------------------------------------------------------*/
\r
530 void vEMAC_TxISRHandler( void )
\r
532 /* Check the buffers have not already been freed in the first of the
\r
533 two Tx interrupts - which could potentially happen if the second Tx completed
\r
534 during the interrupt for the first Tx. */
\r
535 if( xTxDescriptors[ 0 ].data != NULL )
\r
537 if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) )
\r
539 configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data );
\r
541 xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data );
\r
542 prvReturnBuffer( xTxDescriptors[ 0 ].data );
\r
544 /* Just to mark the fact that the buffer has already been released. */
\r
545 xTxDescriptors[ 0 ].data = NULL;
\r
549 /*-----------------------------------------------------------*/
\r
551 void vEMAC_RxISRHandler( void )
\r
553 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
\r
554 long lHigherPriorityTaskWoken = pdFALSE;
\r
555 extern xQueueHandle xEMACEventQueue;
\r
557 /* An Ethernet Rx event has occurred. */
\r
558 xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );
\r
559 portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
\r
561 /*-----------------------------------------------------------*/
\r
563 void vEMAC_ErrorISRHandler( void )
\r
565 portDISABLE_INTERRUPTS();
\r
568 /*-----------------------------------------------------------*/
\r
570 volatile unsigned long ulEvent, ulMask;
\r
571 void vEMAC_ISRHandler( void )
\r
573 //unsigned long ulEvent;
\r
574 long lHigherPriorityTaskWoken = pdFALSE;
\r
575 const unsigned long ulRxEvent = uipETHERNET_RX_EVENT;
\r
576 extern xQueueHandle xEMACEventQueue;
\r
578 /* What caused the interrupt? */
\r
579 ulMask = ENET_EIMR;
\r
580 ulEvent = ENET_EIR;
\r
583 ENET_EIR = ulEvent;
\r
585 if( ( ulEvent & ENET_EIR_TXF_MASK ) != 0UL )
\r
587 /* Transmit complete.
\r
588 Check the buffers have not already been freed in the first of the
\r
589 two Tx interrupts - which could potentially happen if the second Tx completed
\r
590 during the interrupt for the first Tx. */
\r
591 if( xTxDescriptors[ 0 ].data != NULL )
\r
593 if( ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) && ( ( xTxDescriptors[ 0 ].status & TX_BD_R ) == 0 ) )
\r
595 configASSERT( xTxDescriptors[ 0 ].data == xTxDescriptors[ 1 ].data );
\r
597 xTxDescriptors[ 0 ].data = ( uint8_t* ) __REV( ( unsigned long ) xTxDescriptors[ 0 ].data );
\r
598 prvReturnBuffer( xTxDescriptors[ 0 ].data );
\r
600 /* Just to mark the fact that the buffer has already been released. */
\r
601 xTxDescriptors[ 0 ].data = NULL;
\r
606 if( ( ulEvent & ENET_EIR_RXF_MASK ) != 0UL )
\r
609 xQueueSendFromISR( xEMACEventQueue, &ulRxEvent, &lHigherPriorityTaskWoken );
\r
610 portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );
\r
613 if( ulEvent & ( ENET_EIR_UN_MASK | ENET_EIR_RL_MASK | ENET_EIR_LC_MASK | ENET_EIR_EBERR_MASK | ENET_EIR_BABT_MASK | ENET_EIR_BABR_MASK | ENET_EIR_EBERR_MASK ) )
\r
616 prvInitialiseDescriptors();
\r
617 ENET_RDAR = ENET_RDAR_RDAR_MASK;
\r