]> git.sur5r.net Git - freertos/blob
5162f4d752d2c87ed2da3cabd6aa108e8fb2e89a
[freertos] /
1 /**********************************************************************\r
2 * Copyright(C) 2011, NXP Semiconductor\r
3 * All rights reserved.\r
4 * Heavily modified by Real Time Engineers ltd.\r
5 ***********************************************************************\r
6 * Software that is described herein is for illustrative purposes only\r
7 * which provides customers with programming information regarding the\r
8 * products. This software is supplied "AS IS" without any warranties.\r
9 * NXP Semiconductors assumes no responsibility or liability for the\r
10 * use of the software, conveys no license or title under any patent,\r
11 * copyright, or mask work right to the product. NXP Semiconductors\r
12 * reserves the right to make changes in the software without\r
13 * notification. NXP Semiconductors also make no representation or\r
14 * warranty that such application will be suitable for the specified\r
15 * use without further testing or modification.\r
16 **********************************************************************/\r
17 \r
18 /* FreeRTOS includes. */\r
19 #include "FreeRTOS.h"\r
20 #include "task.h"\r
21 \r
22 /* FreeRTOS+UDP includes. */\r
23 #include "FreeRTOS_UDP_IP.h"\r
24 #include "FreeRTOS_IP_Private.h"\r
25 #include "NetworkBufferManagement.h"\r
26 \r
27 /* Library includes. */\r
28 #include "lpc18xx_emac.h"\r
29 #include "lpc18xx_rgu.h"\r
30 #include "lpc18xx_scu.h"\r
31 #include "lpc18xx_gpio.h"\r
32 \r
33 \r
34 #define emacTIMEOUT_DELAY       ( 2 )\r
35 #define emacNEGOTIATE_DELAY     ( 10 / portTICK_RATE_MS )\r
36 \r
37 #define emacEXPECTED_RX_STATUS_MASK     ( RX_FIRST_SEGM | RX_LAST_SEGM )\r
38 \r
39 /* Rx descriptors and data array. */\r
40 static volatile RX_Desc Rx_Desc[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];\r
41 static unsigned int RxDescIndex = 0;\r
42 \r
43 /** Rx Status data array - Must be 8-Byte aligned */\r
44 #if defined ( __CC_ARM   )\r
45         static __align(8) RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];\r
46 #elif defined ( __ICCARM__ )\r
47         #pragma data_alignment=8\r
48         static RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];\r
49 #elif defined   (  __GNUC__  )\r
50         static volatile __attribute__ ((aligned (8))) RX_Stat Rx_Stat[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS ];\r
51 #endif\r
52 \r
53 /* Tx descriptors and status array. */\r
54 static volatile TX_Desc Tx_Desc[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS ];\r
55 static volatile TX_Stat Tx_Stat[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS ];\r
56 static unsigned int TxDescIndex = 0;\r
57 \r
58 /* Private Functions ---------------------------------------------------------- */\r
59 static void rx_descr_init( void );\r
60 static void tx_descr_init( void );\r
61 static int32_t write_PHY( uint32_t PhyReg, uint16_t Value );\r
62 static int32_t read_PHY( uint32_t PhyReg );\r
63 static void setEmacAddr( uint8_t abStationAddr[] );\r
64 \r
65 /*********************************************************************//**\r
66  * @brief               Initializes the EMAC peripheral according to the specified\r
67  *               parameters in the EMAC_ConfigStruct.\r
68  * @param[in]   EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure\r
69  *                    that contains the configuration information for the\r
70  *                    specified EMAC peripheral.\r
71  * @return              None\r
72  *\r
73  * Note: This function will initialize EMAC module according to procedure below:\r
74  *  - Remove the soft reset condition from the MAC\r
75  *  - Configure the PHY via the MIIM interface of the MAC\r
76  *  - Select RMII mode\r
77  *  - Configure the transmit and receive DMA engines, including the descriptor arrays\r
78  *  - Configure the host registers (MAC1,MAC2 etc.) in the MAC\r
79  *  - Enable the receive and transmit data paths\r
80  *  In default state after initializing, only Rx Done and Tx Done interrupt are enabled,\r
81  *  all remain interrupts are disabled\r
82  *  (Ref. from LPC17xx UM)\r
83  **********************************************************************/\r
84 portBASE_TYPE EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)\r
85 {\r
86 int32_t id1, id2, regv, phy = 0;\r
87 int32_t phy_linkstatus_reg, phy_linkstatus_mask;\r
88 uint32_t x;\r
89 const uint32_t ulMaxAttempts = 250UL;\r
90 portBASE_TYPE xReturn = pdPASS;\r
91 \r
92         /* Enable Ethernet Pins (NGX LPC1830 Xplorer. */\r
93         scu_pinmux(0x2 ,0 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC7);\r
94         scu_pinmux(0x1 ,17 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);\r
95         scu_pinmux(0x1 ,18 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);\r
96         scu_pinmux(0x1 ,20 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);\r
97         scu_pinmux(0x1 ,19 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC0);\r
98         scu_pinmux(0x0 ,1 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC6);\r
99         scu_pinmux(0x1 ,15 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);\r
100         scu_pinmux(0x0 ,0 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC2);\r
101         scu_pinmux(0x1 ,16 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);\r
102         scu_pinmux(0xC ,9 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC3);\r
103         scu_pinmux(0x1 ,16 , (MD_EHS | MD_PLN | MD_EZI | MD_ZI), FUNC7);\r
104 \r
105         /* Ethernet RESET Pins */\r
106         scu_pinmux(0x1 ,0 , MD_PUP, FUNC0);\r
107         GPIO_SetDir(0,(1<<4), 1);\r
108         GPIO_SetValue(0,(1<<4));\r
109 \r
110 \r
111         #if MII                           /*   Select MII interface       */                             // check MUXING for new Eagle...\r
112           scu_pinmux(0xC ,6 , (MD_PLN | MD_EZI | MD_ZI), FUNC3);        // ENET_RXD2: PC_6 -> FUNC3\r
113           scu_pinmux(0xC ,7 , (MD_PLN | MD_EZI | MD_ZI), FUNC3);        // ENET_RXD3: PC_7 -> FUNC3\r
114           scu_pinmux(0xC ,0 , (MD_PLN | MD_EZI | MD_ZI), FUNC3);        // ENET_RXLK: PC_0 -> FUNC3\r
115           scu_pinmux(0xC ,2 , (MD_PLN | MD_EZI | MD_ZI), FUNC3);        // ENET_TXD2: PC_2 -> FUNC3\r
116           scu_pinmux(0xC ,3 , (MD_PLN | MD_EZI | MD_ZI), FUNC3);        // ENET_TXD3: PC_3 -> FUNC3\r
117           scu_pinmux(0xC ,5 , (MD_PLN | MD_EZI | MD_ZI), FUNC3);        // ENET_TX_ER:  PC_5 -> FUNC3\r
118           scu_pinmux(0x0 ,1 , (MD_PLN | MD_EZI | MD_ZI), FUNC2);        // ENET_COL:  P0_1 -> FUNC2\r
119         #else                              /*   Select RMII interface     */\r
120           LPC_CREG->CREG6 |= RMII_SELECT;\r
121         #endif\r
122 \r
123 \r
124         RGU_SoftReset( RGU_SIG_ETHERNET );\r
125 \r
126         /* Wait for reset. */\r
127         while( !( LPC_RGU->RESET_ACTIVE_STATUS0 & ( 1 << ETHERNET_RST ) ) )\r
128         {\r
129                 vTaskDelay( emacTIMEOUT_DELAY );\r
130         }\r
131 \r
132         /* Reset all GMAC Subsystem internal registers and logic. */\r
133         LPC_ETHERNET->DMA_BUS_MODE |= DMA_SOFT_RESET;\r
134 \r
135         /* Wait for software reset completion. */\r
136         while( LPC_ETHERNET->DMA_BUS_MODE & DMA_SOFT_RESET )\r
137         {\r
138                 vTaskDelay( emacTIMEOUT_DELAY );\r
139         }\r
140 \r
141         /* Put the PHY in reset mode */\r
142         write_PHY( PHY_REG_BMCR, PHY_BMCR_RESET );\r
143 \r
144         /* Wait for hardware reset to end. */\r
145         for( x = 0; x < ulMaxAttempts; x++ )\r
146         {\r
147                 regv = read_PHY (PHY_REG_BMCR);\r
148                 if( !( regv & PHY_BMCR_RESET ) )\r
149                 {\r
150                         /* Reset complete */\r
151                         break;\r
152                 }\r
153                 else\r
154                 {\r
155                         vTaskDelay( emacTIMEOUT_DELAY );\r
156                 }\r
157         }\r
158 \r
159         if( x == ulMaxAttempts )\r
160         {\r
161                 xReturn = pdFAIL;\r
162         }\r
163 \r
164         /* Check if this is a DP83848C PHY. */\r
165         id1 = read_PHY( PHY_REG_IDR1 );\r
166         id2 = read_PHY( PHY_REG_IDR2 );\r
167         if( ( ( id1 << 16 ) | ( id2 & 0xFFF0 ) ) == DP83848C_ID )\r
168         {\r
169                 phy = DP83848C_ID;\r
170         }\r
171         else if( ( ( id1 << 16 ) | id2 ) == LAN8720_ID )\r
172         {\r
173                 phy = LAN8720_ID;\r
174         }\r
175 \r
176         if( phy != 0 )\r
177         {\r
178                 /* Use autonegotiation about the link speed. */\r
179                 write_PHY( PHY_REG_BMCR, PHY_AUTO_NEG );\r
180 \r
181                 /* Wait to complete Auto_Negotiation. */\r
182                 for( x = 0; x < ulMaxAttempts; x++ )\r
183                 {\r
184                         regv = read_PHY( PHY_REG_BMSR );\r
185 \r
186                         if( ( regv & PHY_AUTO_NEG_DONE ) != 0 )\r
187                         {\r
188                                 /* Auto negotiation Complete. */\r
189                                 break;\r
190                         }\r
191                         else\r
192                         {\r
193                                 vTaskDelay( emacNEGOTIATE_DELAY );\r
194                         }\r
195                 }\r
196 \r
197                 if( x == ulMaxAttempts )\r
198                 {\r
199                         xReturn = pdFAIL;\r
200                 }\r
201         }\r
202         else\r
203         {\r
204                 xReturn = pdFAIL;\r
205         }\r
206 \r
207 \r
208         if( xReturn == pdPASS )\r
209         {\r
210                 /* Default to DP83848C. */\r
211                 phy_linkstatus_reg = PHY_REG_STS;\r
212                 phy_linkstatus_mask = 0x0001;\r
213 \r
214                 if( phy == LAN8720_ID )\r
215                 {\r
216                         phy_linkstatus_reg = PHY_REG_BMSR;\r
217                         phy_linkstatus_mask = 0x0004;\r
218                 }\r
219 \r
220                 /* Check the link status. */\r
221                 for( x = 0; x < ulMaxAttempts; x++ )\r
222                 {\r
223                         regv = read_PHY( phy_linkstatus_reg );\r
224 \r
225                         if( ( regv & phy_linkstatus_mask ) != 0 )\r
226                         {\r
227                                 /* Link is on. */\r
228                                 break;\r
229                         }\r
230                         else\r
231                         {\r
232                                 vTaskDelay( emacNEGOTIATE_DELAY );\r
233                         }\r
234                 }\r
235 \r
236                 if( x == ulMaxAttempts )\r
237                 {\r
238                         xReturn = pdFAIL;\r
239                 }\r
240 \r
241                 regv = read_PHY( PHY_REG_SPCON );\r
242                 regv &= PHY_REG_HCDSPEED_MASK;\r
243 \r
244                 /* Configure 100MBit/10MBit mode and Full/Half Duplex mode. */\r
245                 switch( regv )\r
246                 {\r
247                         case PHY_REG_HCDSPEED_10MB_FULLD:\r
248                                 LPC_ETHERNET->MAC_CONFIG |= MAC_DUPMODE;\r
249                                 break;\r
250 \r
251                         case PHY_REG_HCDSPEED_100MB_HALFD:\r
252                                 LPC_ETHERNET->MAC_CONFIG |= MAC_100MPS;\r
253                                 break;\r
254 \r
255                         case PHY_REG_HCDSPEED_100MB_FULLD:\r
256                                 LPC_ETHERNET->MAC_CONFIG |= MAC_DUPMODE;\r
257                                 LPC_ETHERNET->MAC_CONFIG |= MAC_100MPS;\r
258                                 break;\r
259 \r
260                         default:\r
261                                 break;\r
262                 }\r
263 \r
264                 /* Set the Ethernet MAC Address registers */\r
265                 setEmacAddr( EMAC_ConfigStruct->pbEMAC_Addr );\r
266 \r
267                 /* Initialize Descriptor Lists    */\r
268                 rx_descr_init();\r
269                 tx_descr_init();\r
270 \r
271                 /* Configure Filter\r
272                 LPC_ETHERNET->MAC_FRAME_FILTER is left at its default value.\r
273                 MAC_PROMISCUOUS and MAC_RECEIVEALL can be set if required. */\r
274 \r
275                 /* Enable Receiver and Transmitter   */\r
276                 LPC_ETHERNET->MAC_CONFIG |= (MAC_TX_ENABLE | MAC_RX_ENABLE);\r
277 \r
278                 /* Enable interrupts    */\r
279                 LPC_ETHERNET->DMA_INT_EN =  DMA_INT_NOR_SUM | DMA_INT_RECEIVE ;\r
280 \r
281                 /* Start Transmission & Receive processes   */\r
282                 LPC_ETHERNET->DMA_OP_MODE |= (DMA_SS_TRANSMIT | DMA_SS_RECEIVE );\r
283         }\r
284 \r
285         return xReturn;\r
286 }\r
287 \r
288 /*********************************************************************//**\r
289  **********************************************************************/\r
290 portBASE_TYPE EMAC_CheckTransmitIndex( void )\r
291 {\r
292 portBASE_TYPE xReturn;\r
293 \r
294         if( ( Tx_Desc[ TxDescIndex ].Status & OWN_BIT ) == 0 )\r
295         {\r
296                 xReturn = pdPASS;\r
297         }\r
298         else\r
299         {\r
300                 xReturn = pdFAIL;\r
301         }\r
302 \r
303         return xReturn;\r
304 }\r
305 \r
306 /*********************************************************************//**\r
307  * @brief               EMAC_SetNextPacketToSend\r
308  * @param[in]   pucBuffer\r
309  * @return              None\r
310  ***********************************************************************/\r
311 void EMAC_SetNextPacketToSend( uint8_t * pucBuffer )\r
312 {\r
313         /* The old packet is now finished with and can be freed. */\r
314         vEthernetBufferRelease( ( void * ) Tx_Desc[ TxDescIndex ].Packet );\r
315 \r
316         /* Assign the new packet to the descriptor. */\r
317         Tx_Desc[ TxDescIndex ].Packet = ( uint32_t ) pucBuffer;\r
318 }\r
319 \r
320 void EMAC_StartTransmitNextBuffer( uint32_t ulLength )\r
321 {\r
322         Tx_Desc[ TxDescIndex ].Ctrl = ulLength;\r
323         Tx_Desc[ TxDescIndex ].Status |= OWN_BIT;\r
324 \r
325         /* Wake Up the DMA if it's in Suspended Mode. */\r
326         LPC_ETHERNET->DMA_TRANS_POLL_DEMAND = 1;\r
327         TxDescIndex++;\r
328 \r
329         if( TxDescIndex == configNUM_TX_ETHERNET_DMA_DESCRIPTORS )\r
330         {\r
331                 TxDescIndex = 0;\r
332         }\r
333 }\r
334 \r
335 /*********************************************************************//**\r
336  * @brief               Get size of current Received data in received buffer (due to\r
337  *                              RxConsumeIndex)\r
338  * @param[in]   None\r
339  * @return              Size of received data\r
340  **********************************************************************/\r
341 uint32_t EMAC_GetReceiveDataSize(void)\r
342 {\r
343 unsigned short RxLen = 0;\r
344 \r
345         RxLen = ( Rx_Desc[ RxDescIndex ].Status >> 16 ) & 0x03FFF;\r
346         return RxLen;\r
347 }\r
348 \r
349 /*********************************************************************//**\r
350  * @brief               Increase the RxConsumeIndex (after reading the Receive buffer\r
351  *                              to release the Receive buffer) and wrap-around the index if\r
352  *                              it reaches the maximum Receive Number\r
353  * @param[in]   None\r
354  * @return              None\r
355  **********************************************************************/\r
356 void EMAC_UpdateRxConsumeIndex( void )\r
357 {\r
358         Rx_Desc[ RxDescIndex ].Status = OWN_BIT;\r
359         RxDescIndex++;\r
360 \r
361         if( RxDescIndex == configNUM_RX_ETHERNET_DMA_DESCRIPTORS )\r
362         {\r
363                 RxDescIndex = 0;\r
364         }\r
365 }\r
366 \r
367 /*********************************************************************//**\r
368  * @brief               Check whether if the current RxConsumeIndex is not equal to the\r
369  *                              current RxProduceIndex.\r
370  * @param[in]   None\r
371  * @return              TRUE if they're not equal, otherwise return FALSE\r
372  *\r
373  * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,\r
374  * it means there're available data has been received. They should be read\r
375  * out and released the Receive Data Buffer by updating the RxConsumeIndex value.\r
376  **********************************************************************/\r
377 portBASE_TYPE EMAC_CheckReceiveIndex(void)\r
378 {\r
379 portBASE_TYPE xReturn;\r
380 \r
381         if( ( Rx_Desc[ RxDescIndex ].Status & OWN_BIT ) == 0 )\r
382         {\r
383                 xReturn = pdPASS;\r
384         }\r
385         else\r
386         {\r
387                 xReturn = pdFAIL;\r
388         }\r
389 \r
390         return xReturn;\r
391 }\r
392 \r
393 void EMAC_NextPacketToRead( xNetworkBufferDescriptor_t *pxNetworkBuffer )\r
394 {\r
395 uint8_t *pucTemp;\r
396 \r
397         /* Swap the buffer in the network buffer with the buffer used by the DMA.\r
398         This allows the data to be passed out without having to perform any copies. */\r
399         pucTemp = ( uint8_t * ) Rx_Desc[ RxDescIndex ].Packet;\r
400         Rx_Desc[ RxDescIndex ].Packet = ( uint32_t ) pxNetworkBuffer->pucEthernetBuffer;\r
401         pxNetworkBuffer->pucEthernetBuffer = pucTemp;\r
402 \r
403         /* Only supports frames coming in single buffers.  If this frame is split\r
404         across multiple buffers then reject it (and if the frame is needed increase\r
405         the ipconfigNETWORK_MTU setting). */\r
406         if( ( Rx_Desc[ RxDescIndex ].Status & emacEXPECTED_RX_STATUS_MASK ) != emacEXPECTED_RX_STATUS_MASK )\r
407         {\r
408                 pxNetworkBuffer->xDataLength = 0;\r
409         }\r
410         else\r
411         {\r
412                 pxNetworkBuffer->xDataLength = ( size_t ) EMAC_GetReceiveDataSize() - ( ipETHERNET_CRC_BYTES - 1U );;\r
413         }\r
414 }\r
415 \r
416 /*********************************************************************//**\r
417  * @brief               Initializes RX Descriptor\r
418  * @param[in]   None\r
419  * @return              None\r
420  ***********************************************************************/\r
421 static void rx_descr_init( void )\r
422 {\r
423 uint32_t x;\r
424 size_t xBufferSize = ipTOTAL_ETHERNET_FRAME_SIZE;\r
425 \r
426         for( x = 0; x < configNUM_RX_ETHERNET_DMA_DESCRIPTORS; x++ )\r
427         {\r
428                 /* Obtain the buffer first, as the size of the buffer might be changed\r
429                 within the pucEthernetBufferGet() call. */\r
430                 Rx_Desc[ x ].Packet  = ( uint32_t ) pucEthernetBufferGet( &xBufferSize );\r
431                 Rx_Desc[ x ].Status = OWN_BIT;\r
432                 Rx_Desc[ x ].Ctrl  = xBufferSize;\r
433                 Rx_Desc[ x ].NextDescripter = ( uint32_t ) &Rx_Desc[ x + 1 ];\r
434                 \r
435                 configASSERT( ( ( ( uint32_t ) Rx_Desc[x].Packet ) & 0x07 ) == 0 );\r
436         }\r
437 \r
438         /* Last Descriptor */\r
439         Rx_Desc[ configNUM_RX_ETHERNET_DMA_DESCRIPTORS - 1 ].Ctrl |= RX_END_RING;\r
440 \r
441         RxDescIndex = 0;\r
442 \r
443         /* Set Starting address of RX Descriptor list */\r
444         LPC_ETHERNET->DMA_REC_DES_ADDR = ( uint32_t ) Rx_Desc;\r
445 }\r
446 \r
447 /*********************************************************************//**\r
448  * @brief               Initializes TX Descriptor\r
449  * @param[in]   None\r
450  * @return              None\r
451  ***********************************************************************/\r
452 static void tx_descr_init( void )\r
453 {\r
454 /* Initialize Transmit Descriptor and Status array. */\r
455 uint32_t x;\r
456 \r
457         for( x = 0; x < configNUM_TX_ETHERNET_DMA_DESCRIPTORS; x++ )\r
458         {\r
459                 Tx_Desc[ x ].Status = TX_LAST_SEGM | TX_FIRST_SEGM;\r
460                 Tx_Desc[ x ].Ctrl  = 0;\r
461                 Tx_Desc[ x ].NextDescripter = ( uint32_t ) &Tx_Desc[ x + 1 ];\r
462 \r
463                 /* Packet is assigned when a Tx is initiated. */\r
464                 Tx_Desc[ x ].Packet   = ( uint32_t )NULL;\r
465         }\r
466 \r
467         /* Last Descriptor? */\r
468         Tx_Desc[ configNUM_TX_ETHERNET_DMA_DESCRIPTORS-1 ].Status |= TX_END_RING;\r
469 \r
470         /* Set Starting address of TX Descriptor list */\r
471         LPC_ETHERNET->DMA_TRANS_DES_ADDR = ( uint32_t ) Tx_Desc;\r
472 }\r
473 \r
474 \r
475 /*********************************************************************//**\r
476  * @brief               Write value to PHY device\r
477  * @param[in]   PhyReg: PHY Register address\r
478  * @param[in]   Value:  Value to write\r
479  * @return              0 - if success\r
480  *                              1 - if fail\r
481  ***********************************************************************/\r
482 static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)\r
483 {\r
484 uint32_t x;\r
485 const uint32_t ulMaxAttempts = 250UL;\r
486 int32_t lReturn = pdPASS;\r
487 \r
488         /* Write a data 'Value' to PHY register 'PhyReg'. */\r
489         x = 0;\r
490         while( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY )\r
491         {\r
492                 x++;\r
493 \r
494                 if( x >= ulMaxAttempts )\r
495                 {\r
496                         /* Time out. */\r
497                         lReturn = pdFAIL;\r
498                         break;\r
499                 }\r
500                 else\r
501                 {\r
502                         /* GMII is busy. */\r
503                         vTaskDelay( emacTIMEOUT_DELAY );\r
504                 }\r
505         }\r
506 \r
507         if( lReturn == pdPASS )\r
508         {\r
509                 LPC_ETHERNET->MAC_MII_ADDR = ( DP83848C_DEF_ADR << 11 ) | ( PhyReg << 6 ) | GMII_WRITE;\r
510                 LPC_ETHERNET->MAC_MII_DATA = Value;\r
511 \r
512                 /* Start PHY Write Cycle. */\r
513                 LPC_ETHERNET->MAC_MII_ADDR |= GMII_BUSY;\r
514 \r
515                 /* Wait untl operation completed. */\r
516                 for( x = 0; x < ulMaxAttempts; x++ )\r
517                 {\r
518                         if( ( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY ) == 0 )\r
519                         {\r
520                                 break;\r
521                         }\r
522                         else\r
523                         {\r
524                                 vTaskDelay( emacTIMEOUT_DELAY );\r
525                         }\r
526                 }\r
527 \r
528                 if( x == ulMaxAttempts )\r
529                 {\r
530                         /* Timeout. */\r
531                         lReturn = pdFAIL;\r
532                 }\r
533         }\r
534 \r
535         return lReturn;\r
536 }\r
537 \r
538 /*********************************************************************//**\r
539  * @brief               Read value from PHY device\r
540  * @param[in]   PhyReg: PHY Register address\r
541  * @return              0 - if success\r
542  *                              1 - if fail\r
543  ***********************************************************************/\r
544 static int32_t read_PHY( uint32_t PhyReg )\r
545 {\r
546 int32_t lValue = 0;\r
547 uint32_t x;\r
548 const uint32_t ulMaxAttempts = 250UL;\r
549 \r
550         /* Write a data 'Value' to PHY register 'PhyReg'. */\r
551         x = 0;\r
552         while( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY )\r
553         {\r
554                 x++;\r
555 \r
556                 if( x >= ulMaxAttempts )\r
557                 {\r
558                         /* Time out. */\r
559                         break;\r
560                 }\r
561                 else\r
562                 {\r
563                         /* GMII is busy. */\r
564                         vTaskDelay( emacTIMEOUT_DELAY );\r
565                 }\r
566         }\r
567 \r
568         if( x < ulMaxAttempts )\r
569         {\r
570                 /* Read a PHY register 'PhyReg'. */\r
571                 LPC_ETHERNET->MAC_MII_ADDR = ( DP83848C_DEF_ADR << 11 ) | ( PhyReg << 6 ) | GMII_READ;\r
572 \r
573                 /* Start PHY Read Cycle. */\r
574                 LPC_ETHERNET->MAC_MII_ADDR |= GMII_BUSY;\r
575 \r
576                 /* Wait until operation completed */\r
577                 for( x = 0; x < ulMaxAttempts; x++ )\r
578                 {\r
579                         if( ( LPC_ETHERNET->MAC_MII_ADDR & GMII_BUSY ) == 0 )\r
580                         {\r
581                                 break;\r
582                         }\r
583                         else\r
584                         {\r
585                                 vTaskDelay( emacTIMEOUT_DELAY );\r
586                         }\r
587                 }\r
588 \r
589                 configASSERT( x != ulMaxAttempts );\r
590                 lValue = LPC_ETHERNET->MAC_MII_DATA;\r
591         }\r
592 \r
593         return lValue;\r
594 }\r
595 \r
596 /*********************************************************************//**\r
597  * @brief               Set Station MAC address for EMAC module\r
598  * @param[in]   abStationAddr Pointer to Station address that contains 6-bytes\r
599  *                              of MAC address (should be in order from MAC Address 1 to MAC Address 6)\r
600  * @return              None\r
601  **********************************************************************/\r
602 static void setEmacAddr( uint8_t abStationAddr[] )\r
603 {\r
604         /* Set the Ethernet MAC Address registers */\r
605         LPC_ETHERNET->MAC_ADDR0_HIGH = (( uint32_t ) abStationAddr[ 5 ] << 8 ) | ( uint32_t )abStationAddr[ 4 ];\r
606         LPC_ETHERNET->MAC_ADDR0_LOW =   (( uint32_t )abStationAddr[ 3 ] << 24) | (( uint32_t )abStationAddr[ 2 ] << 16) | (( uint32_t )abStationAddr[ 1 ] << 8 ) | ( uint32_t )abStationAddr[ 0 ];\r
607 }\r
608 \r
609 \r
610 \r