1 /********************
\r
2 * Original work (C) COPYRIGHT 2006 STMicroelectronics **************************
\r
3 * Modifications (C) CopyRight 2006 Richard barry
\r
4 * File Name : 91x_enet.c
\r
5 * Author : MCD Application Team
\r
6 * Date First Issued : May 2006
\r
7 * Description : ENET library functions
\r
8 ********************************************************************************
\r
11 ********************************************************************************
\r
12 * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
\r
13 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
\r
14 * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
\r
15 * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
\r
16 * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
\r
17 * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
\r
18 *******************************************************************************/
\r
21 /* Includes ------------------------------------------------------------------*/
\r
22 #include "FreeRTOS.h"
\r
24 #include "91x_lib.h"
\r
25 #include "string.h" //include when using memcpy function
\r
27 /* Include of other module interface headers ---------------------------------*/
\r
28 /* Local includes ------------------------------------------------------------*/
\r
29 /* Private typedef -----------------------------------------------------------*/
\r
30 /* Private define ------------------------------------------------------------*/
\r
34 /* Function return values */
\r
36 #define ENET_NOK (0)
\r
38 /* PHY interface constants. */
\r
39 #define STE100P_STATUS_REG 0x01
\r
40 #define STE100P_CONTROL_REG 0x00
\r
41 #define STE100P_LINK_ABILITY 0x05
\r
42 #define STE100P_STATUS_LINKED 0x0004
\r
43 #define STE100P_AUTO_NEGOTIATE_ABILITY 0x1000
\r
44 #define STE100P_AUTO_NEGOTIATE_COMPLETE 0x20
\r
45 #define STE100P_10HALF 0x0020
\r
46 #define STE100P_10FULL 0x0040
\r
47 #define STE100P_100HALF 0x0080
\r
48 #define STE100P_100FULL 0x0100
\r
49 #define STE100P_CTRL_FULL 0x0100
\r
52 /* Private macro -------------------------------------------------------------*/
\r
53 /* Private variables ---------------------------------------------------------*/
\r
54 #define ENET_NUM_RX_BUFFERS 8
\r
56 static ENET_DMADSCRBase dmaTxDscrBase, dmaRxDscrBase[ ENET_NUM_RX_BUFFERS ];
\r
57 static u8 RxBuff[ ENET_NUM_RX_BUFFERS ][ENET_BUFFER_SIZE];
\r
58 u8 TxBuff[ENET_BUFFER_SIZE];
\r
60 /* Private function prototypes -----------------------------------------------*/
\r
61 extern MEMCOPY_L2S_BY4();
\r
63 /* Interface functions -------------------------------------------------------*/
\r
64 /* Private functions ---------------------------------------------------------*/
\r
66 /*******************************************************************************
\r
67 * Function Name : ENET_SetMACConfig(ENET_MACConfig * MAC_Config)
\r
68 * Description : MAC Control Register Configuration
\r
69 * Input : MAC_Config structure
\r
72 *******************************************************************************/
\r
73 void ENET_MACControlConfig(ENET_MACConfig *MAC_Config)
\r
75 /* ReceiveALL bit */
\r
76 if (MAC_Config->ReceiveALL==ENABLE) ENET_MAC->MCR |= MAC_MCR_RA;
\r
77 else ENET_MAC->MCR &=~MAC_MCR_RA;
\r
80 ENET_MAC->MCR &=~(0x3<<24);
\r
81 if ((MAC_Config->MIIPrescaler) == MIIPrescaler_2)
\r
82 ENET_MAC->MCR |=0x1<<24;
\r
85 if (MAC_Config->LoopbackMode==ENABLE)
\r
87 ENET_MAC->MCR &=~MAC_MCR_LM;
\r
88 ENET_MAC->MCR |=0x1<<21;
\r
89 ENET_MAC->MCR &=~MAC_MCR_DRO; /*enable frame reception during transmission*/
\r
92 /* Address filtering mode */
\r
93 ENET_MAC->MCR &=~MAC_MCR_AFM;
\r
94 ENET_MAC->MCR |= MAC_Config->AddressFilteringMode;
\r
96 /* VLAN Filtering Mode */
\r
97 ENET_MAC->MCR |= (MAC_Config->VLANFilteringMode)<<15;
\r
99 /*Wrong Frame Pass */
\r
100 if (MAC_Config->PassWrongFrame == ENABLE) ENET_MAC->MCR |=MAC_MCR_PWF;
\r
101 else ENET_MAC->MCR &=~MAC_MCR_PWF;
\r
103 /* Late Collision Retransmission*/
\r
104 if (MAC_Config->LateCollision == ENABLE) ENET_MAC->MCR |=MAC_MCR_ELC;
\r
105 else ENET_MAC->MCR &=~MAC_MCR_ELC;
\r
107 /* Broadcast Frame Reception */
\r
108 if (MAC_Config->BroadcastFrameReception == ENABLE) ENET_MAC->MCR &=~MAC_MCR_DBF;
\r
109 else ENET_MAC->MCR |=MAC_MCR_DBF;
\r
112 if (MAC_Config->PacketRetry == ENABLE) ENET_MAC->MCR &=~MAC_MCR_DPR;
\r
113 else ENET_MAC->MCR |=MAC_MCR_DPR;
\r
115 /* RxFrameFiltering */
\r
116 if (MAC_Config->RxFrameFiltering == ENABLE) ENET_MAC->MCR |=MAC_MCR_RVFF;
\r
117 else ENET_MAC->MCR &=~MAC_MCR_RVFF;
\r
119 /* AutomaticPadRemoval */
\r
120 if (MAC_Config->AutomaticPadRemoval == ENABLE) ENET_MAC->MCR |=MAC_MCR_APR;
\r
121 else ENET_MAC->MCR &=~MAC_MCR_APR;
\r
123 /* DefferalCheck */
\r
124 if (MAC_Config->DeferralCheck == ENABLE) ENET_MAC->MCR |=MAC_MCR_DCE;
\r
125 else ENET_MAC->MCR &=~MAC_MCR_DCE;
\r
131 /*******************************************************************************
\r
132 * Function Name : ENET_SetOperatingMode
\r
133 * Description : Sets the Operating mode
\r
134 * Input : ENET_OperatingMode:(see ENET_OperatingMode in 91x_enet.h)
\r
137 *******************************************************************************/
\r
138 portBASE_TYPE ENET_SetOperatingMode( void )
\r
140 unsigned long ulStatusReg, ulControlReg, ulLinkAbilityReg;
\r
142 /* Link status is latched, so read twice to get current value */
\r
143 ulStatusReg = ENET_MIIReadReg(0, STE100P_STATUS_REG);
\r
144 ulStatusReg = ENET_MIIReadReg(0, STE100P_STATUS_REG);
\r
146 if( !( ulStatusReg & STE100P_STATUS_LINKED ) )
\r
152 ulControlReg = ENET_MIIReadReg(0, STE100P_CONTROL_REG);
\r
153 if (ulControlReg & STE100P_AUTO_NEGOTIATE_ABILITY)
\r
155 /* AutoNegotiation is enabled. */
\r
156 if (!(ulStatusReg & STE100P_AUTO_NEGOTIATE_COMPLETE))
\r
158 /* Auto-negotiation in progress. */
\r
162 ulLinkAbilityReg = ENET_MIIReadReg(0, STE100P_LINK_ABILITY);
\r
163 if( ( ulLinkAbilityReg & STE100P_100FULL ) || ( ulLinkAbilityReg & STE100P_10FULL ) )
\r
165 ENET_MAC->MCR |=MAC_MCR_FDM; /* full duplex mode */
\r
166 ENET_MAC->MCR &=~MAC_MCR_DRO; /* enable frame reception during transmission */
\r
170 ENET_MAC->MCR &=~MAC_MCR_FDM; /* half duplex mode */
\r
171 ENET_MAC->MCR |=MAC_MCR_DRO; /* disable frame reception during transmission */
\r
176 if( ulStatusReg & STE100P_CTRL_FULL )
\r
178 ENET_MAC->MCR |=MAC_MCR_FDM; /* full duplex mode */
\r
179 ENET_MAC->MCR &=~MAC_MCR_DRO; /* enable frame reception during transmission */
\r
183 ENET_MAC->MCR &=~MAC_MCR_FDM; /* half duplex mode */
\r
184 ENET_MAC->MCR |=MAC_MCR_DRO; /* disable frame reception during transmission */
\r
191 /*******************************************************************************
\r
192 * Function Name : ENET_MIIWriteReg
\r
193 * Description : Writes a value on the PHY registers
\r
194 * Input : phyDev PHY device address
\r
195 : phyReg PHY register to be written
\r
196 * : phyVal PHY register value
\r
199 *******************************************************************************/
\r
200 void ENET_MIIWriteReg (u8 phyDev, u8 phyReg, u32 phyVal)
\r
204 volatile u32 res; /* temporary result for address register status */
\r
205 volatile u32 timeout;
\r
207 /* Prepare the MII register address */
\r
209 addr |= ((phyDev<<11) & MAC_MII_ADDR_PHY_ADDR); /* set the PHY address */
\r
210 addr |= ((phyReg<<6) & MAC_MII_ADDR_MII_REG); /* select the corresponding register */
\r
211 addr |= MAC_MII_ADDR_MII_WRITE; /* in write mode */
\r
212 addr |= MAC_MII_ADDR_MII_BUSY;
\r
214 /* Check for the Busy flag */
\r
219 res = ENET_MAC->MIIA;
\r
220 } while ((res & MAC_MII_ADDR_MII_BUSY) && (timeout < (u32 )MII_WRITE_TO));
\r
222 /* Give the value to the MII data register */
\r
223 ENET_MAC->MIID = (phyVal & 0xFFFF);
\r
225 /* write the result value into the MII Address register */
\r
226 ENET_MAC->MIIA =addr;
\r
228 /* Check for the Busy flag */
\r
233 res = ENET_MAC->MIIA;
\r
234 } while ((res & MAC_MII_ADDR_MII_BUSY) && (timeout < (u32 )MII_WRITE_TO));
\r
238 /*******************************************************************************
\r
239 * Function Name : ENET_MIIReadReg
\r
240 * Description : Writes a value on the PHY
\r
241 * Input : phyDev PHY device address
\r
242 * : phyReg PHY register to be read
\r
244 * Return : The read value (16 bits)
\r
245 *******************************************************************************/
\r
246 u32 ENET_MIIReadReg (u8 phyDev, u32 phyReg )
\r
251 u32 res; /* temporary result for address register status */
\r
252 u32 timeout; /* timeout value for read process */
\r
254 /* prepare the MII register address */
\r
256 addr |= ((phyDev<<11) & MAC_MII_ADDR_PHY_ADDR); /* set the PHY address */
\r
257 addr |= ((phyReg<<6) & MAC_MII_ADDR_MII_REG); /* select the corresponding register */
\r
258 addr &= ~(MAC_MII_ADDR_MII_WRITE); /* ... in read mode */
\r
259 addr |= MAC_MII_ADDR_MII_BUSY;
\r
261 /* Check for the Busy flag */
\r
267 res = ENET_MAC->MIIA;
\r
268 } while ((res & MAC_MII_ADDR_MII_BUSY) && (timeout < (u32 )MII_READ_TO));
\r
270 /* write the result value into the MII Address register */
\r
271 ENET_MAC->MIIA = addr;
\r
273 /* Check for the Busy flag */
\r
279 res = ENET_MAC->MIIA;
\r
280 } while ((res & MAC_MII_ADDR_MII_BUSY) && (timeout < (u32 )MII_READ_TO));
\r
282 /* read the result value from data register*/
\r
283 rValue = ENET_MAC->MIID;
\r
285 return (rValue & 0x0000FFFF);
\r
288 /*******************************************************************************
\r
289 * Function Name : ENET_RxDscrInit
\r
290 * Description : Initializes the Rx ENET descriptor chain. Single Descriptor
\r
294 *******************************************************************************/
\r
296 void ENET_RxDscrInit(void)
\r
300 for( i = 0; i < ENET_NUM_RX_BUFFERS; i++ )
\r
302 /* Assign temp Rx array to the ENET buffer */
\r
303 dmaRxDscrBase[ i ].dmaAddr = (u32)&(RxBuff[ i ][ 0 ]);
\r
305 /* Initialize RX ENET Status and control */
\r
306 dmaRxDscrBase[ i ].dmaStatCntl = 0x4000;
\r
308 /* Initialize the next descriptor- In our case its single descriptor */
\r
309 dmaRxDscrBase[ i ].dmaNext = (u32)&(dmaRxDscrBase[i+1]) | 0x01;
\r
311 /* Set the max packet size */
\r
312 dmaRxDscrBase[ i ].dmaStatCntl = ENET_MAX_PACKET_SIZE | ENET_NEXT_ENABLE;
\r
314 /* Setting the VALID bit */
\r
315 dmaRxDscrBase[ i ].dmaPackStatus = DMA_DSCR_RX_STATUS_VALID_MSK;
\r
318 dmaRxDscrBase[ ENET_NUM_RX_BUFFERS - 1 ].dmaNext = (u32)&(dmaRxDscrBase[ 0 ]);
\r
320 /* Setting the RX NEXT Descriptor Register inside the ENET */
\r
321 ENET_DMA->RXNDAR = (u32)&(dmaRxDscrBase) | 0x01;
\r
324 /*******************************************************************************
\r
325 * Function Name : ENET_TxDscrInit
\r
326 * Description : Initializes the Tx ENET descriptor chain with single descriptor
\r
330 *******************************************************************************/
\r
332 void ENET_TxDscrInit(void)
\r
335 /* ENET Start Address */
\r
336 dmaTxDscrBase.dmaAddr = (u32)TxBuff;
\r
338 /* Next Descriptor Address */
\r
339 dmaTxDscrBase.dmaNext = (u32)&(dmaTxDscrBase);
\r
341 /* Initialize ENET status and control */
\r
342 dmaTxDscrBase.dmaStatCntl = 0;
\r
344 /* Tx next set to Tx decriptor base */
\r
345 ENET_DMA->TXNDAR = (u32)&(dmaTxDscrBase);
\r
347 /* Enable next enable */
\r
348 ENET_DMA->TXNDAR |= DMA_DSCR_NXT_NPOL_EN;
\r
352 /*******************************************************************************
\r
353 * Function Name : ENET_Init
\r
354 * Description : ENET MAC, PHY and DMA initializations
\r
358 *******************************************************************************/
\r
363 ENET_MACConfig *MAC_Config;
\r
364 ENET_MACConfig config;
\r
366 /* De-assert the SRESET bit of ENET + MAC devices */
\r
367 ENET_DMA->SCR &=~DMA_SCR_SRESET;
\r
368 MAC_Config =&config;
\r
369 /* Initialize MAC control register with common values */
\r
370 MAC_Config->ReceiveALL = DISABLE;
\r
371 if (SCU_GetHCLKFreqValue() > 50000)
\r
372 MAC_Config->MIIPrescaler = MIIPrescaler_2;
\r
373 MAC_Config->LoopbackMode = DISABLE;
\r
374 MAC_Config->AddressFilteringMode = MAC_Perfect_Multicast_Perfect;
\r
375 MAC_Config->VLANFilteringMode = VLANfilter_VLTAG;
\r
376 MAC_Config->PassWrongFrame = DISABLE;
\r
377 MAC_Config->LateCollision = DISABLE;
\r
378 MAC_Config->BroadcastFrameReception = ENABLE;
\r
379 MAC_Config->PacketRetry = ENABLE;
\r
380 MAC_Config->RxFrameFiltering = ENABLE;
\r
381 MAC_Config->AutomaticPadRemoval = ENABLE;
\r
382 MAC_Config->DeferralCheck = ENABLE;
\r
384 /* Configure MAC control register */
\r
385 ENET_MACControlConfig(MAC_Config);
\r
387 /* DMA initialization */
\r
388 /* Read the ENET DMA Status and Control Register */
\r
389 regValue = ENET_DMA->SCR;
\r
391 /* Setup Tx Max burst size */
\r
392 regValue &= ~(u32)DMA_SCR_TX_MAX_BURST_SZ;
\r
393 regValue |= (u32)DMA_SCR_TX_MAX_BURST_SZ_VAL;
\r
395 /* Setup Rx Max Burst size */
\r
396 regValue &= ~(u32)DMA_SCR_RX_MAX_BURST_SZ;
\r
397 regValue |= (u32)DMA_SCR_RX_MAX_BURST_SZ_VAL;
\r
399 /* Write Tx & Rx burst size to the ENET status and control register */
\r
400 ENET_DMA->SCR = regValue;
\r
402 /* Put the PHY in reset mode */
\r
403 ENET_MIIWriteReg(0x0,MAC_MII_REG_XCR, 0x8000);
\r
405 /* Delay to assure PHY reset */
\r
406 vTaskDelay( 3000 / portTICK_RATE_MS );
\r
408 /* initialize the opearting mode */
\r
409 while( ENET_SetOperatingMode() == pdFAIL )
\r
411 vTaskDelay( 3000 / portTICK_RATE_MS );
\r
414 /*set MAC physical*/
\r
415 //ENET_MAC->MAH = (MAC_ADDR5<<8) + MAC_ADDR4;
\r
416 //ENET_MAC->MAL = (MAC_ADDR3<<24) + (MAC_ADDR2<<16) + (MAC_ADDR1<<8) + MAC_ADDR0;
\r
418 /* Initialize Rx and Tx descriptors in memory */
\r
422 // What's happening ???
\r
424 //int pippo = 1; // Do NOT remove!!!
\r
428 /********************************************************************************
\r
429 * Function Name : ENET_HandleRxPkt
\r
430 * Description : receive a packet and copy it to memory pointed by ppkt.
\r
431 * Input : ppkt: pointer on application receive buffer.
\r
433 * Return : ENET_NOK - If there is no packet
\r
434 * : ENET_OK - If there is a packet
\r
435 *******************************************************************************/
\r
436 u32 ENET_HandleRxPkt ( void *ppkt)
\r
438 ENET_DMADSCRBase *pDescr;
\r
440 static int iNextRx = 0;
\r
442 if( dmaRxDscrBase[ iNextRx ].dmaPackStatus & DMA_DSCR_RX_STATUS_VALID_MSK )
\r
447 pDescr = &dmaRxDscrBase[ iNextRx ];
\r
449 /*Get the size of the packet*/
\r
450 size = ((pDescr->dmaPackStatus & 0x7ff) - 4);
\r
452 //MEMCOPY_L2S_BY4((u8*)ppkt, RxBuff, size); /*optimized memcopy function*/
\r
453 memcpy(ppkt, RxBuff[iNextRx], size); //string.h library*/
\r
455 /* Give the buffer back to ENET */
\r
456 pDescr->dmaPackStatus = DMA_DSCR_RX_STATUS_VALID_MSK;
\r
460 if( iNextRx >= ENET_NUM_RX_BUFFERS )
\r
465 /* Return no error */
\r
469 /*******************************************************************************
\r
470 * Function Name : ENET_TxPkt
\r
471 * Description : Transmit a packet
\r
472 * Input : ppkt: pointer to application packet Buffer
\r
473 * : size: Tx Packet size
\r
476 *******************************************************************************/
\r
478 u8 *pcGetNextBuffer( void )
\r
480 if( dmaTxDscrBase.dmaPackStatus & DMA_DSCR_TX_STATUS_VALID_MSK )
\r
486 return ( unsigned char * ) TxBuff;
\r
490 void ENET_TxPkt(void *ppkt, u16 size)
\r
492 /* Setting the Frame Length*/
\r
493 dmaTxDscrBase.dmaStatCntl = (size&0xFFF);
\r
495 /* Start the ENET by setting the VALID bit in dmaPackStatus of current descr*/
\r
496 dmaTxDscrBase.dmaPackStatus = DMA_DSCR_TX_STATUS_VALID_MSK;
\r
498 /* Start the transmit operation */
\r
499 ENET_DMA->TXSTR|= DMA_TX_START_FETCH;
\r
502 /*******************************************************************************
\r
503 * Function Name : ENET_Start
\r
504 * Description : Enables ENET MAC reception / transmission & starts DMA fetch
\r
508 *******************************************************************************/
\r
510 void ENET_Start ( void)
\r
514 /* Force a ENET abort by software for the receive block */
\r
515 ENET_DMA->RXSTR &=~ DMA_RX_START_DMA_EN;
\r
517 /* Force a ENET abort by software for the transmit block */
\r
518 ENET_DMA->TXSTR &=~DMA_TX_START_DMA_EN;
\r
520 /* Reset all interrupts */
\r
521 ENET_DMA->ISR = 0xFFFFFFFF;
\r
523 /* Setup Descriptor Fetch ENET_PhyDelay for Receive Block */
\r
524 value = ENET_DMA->RXSTR;
\r
525 value &= ~( DMA_RX_START_DFETCH_DLY );
\r
526 value |= DMA_RX_START_DFETCH_DEFAULT;
\r
527 ENET_DMA->RXSTR= value;
\r
529 /* Setup Descriptor Fetch ENET_PhyDelay for Transmit Block */
\r
530 value = ENET_DMA->TXSTR;
\r
531 value &= ~( DMA_TX_START_DFETCH_DLY );
\r
532 value |= DMA_TX_START_DFETCH_DEFAULT;
\r
533 ENET_DMA->TXSTR= value;
\r
535 /* Set Tx underrun bit */
\r
536 value &= ~( DMA_TX_START_URUN );
\r
537 value |= DMA_TX_START_URUN;
\r
538 ENET_DMA->TXSTR = value;
\r
540 /* Clear the interrupts */
\r
541 ENET_DMA->IER = 0x0;
\r
543 /* MAC TX enable */
\r
544 ENET_MAC->MCR|= MAC_MCR_TE;
\r
546 /* MAC RX enable */
\r
547 ENET_MAC->MCR|= MAC_MCR_RE;
\r
549 /* Start the DMA Fetch */
\r
550 ENET_DMA->RXSTR|= DMA_RX_START_FETCH;
\r
554 /*******************************************************************************
\r
555 * Function Name : ENET_InitClocksGPIO
\r
556 * Description : Reset, clocks & GPIO Ethernet Pin initializations
\r
560 *******************************************************************************/
\r
561 void ENET_InitClocksGPIO(void)
\r
564 GPIO_InitTypeDef GPIO_Struct;
\r
566 SCU_AHBPeriphClockConfig(__ENET, ENABLE);
\r
567 SCU_AHBPeriphReset(__ENET,DISABLE);
\r
568 SCU_PHYCLKConfig(ENABLE);
\r
570 GPIO_DeInit(GPIO1);
\r
571 GPIO_Struct.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 |GPIO_Pin_3 |GPIO_Pin_4 |GPIO_Pin_7 ;
\r
572 GPIO_Struct.GPIO_Type = GPIO_Type_PushPull;
\r
573 GPIO_Struct.GPIO_Direction = GPIO_PinOutput;
\r
574 GPIO_Struct.GPIO_IPConnected = GPIO_IPConnected_Disable;
\r
575 GPIO_Struct.GPIO_Alternate=GPIO_OutputAlt2;
\r
576 GPIO_Init(GPIO1, &GPIO_Struct);
\r
579 GPIO_DeInit(GPIO5);
\r
580 GPIO_Struct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
\r
581 GPIO_Struct.GPIO_Type = GPIO_Type_PushPull;
\r
582 GPIO_Struct.GPIO_Direction = GPIO_PinOutput;
\r
583 GPIO_Struct.GPIO_IPConnected = GPIO_IPConnected_Disable;
\r
584 GPIO_Struct.GPIO_Alternate=GPIO_OutputAlt2;
\r
585 GPIO_Init(GPIO5, &GPIO_Struct);
\r
589 /******************** (C) COPYRIGHT 2006 STMicroelectronics *******************/
\r