⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethernet_lpc23xx.c

📁 This program contains program realization EMAC for LPC23xx
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
 ********************************************************************
 * Project:     ethernet driver for LPC23xx/24xx
 * File:    	ethernet_lpc23xx.c
 *
 * System:   	ARM7TDMI-S 32 Bit
 * Compiler:  	GCC 4.0.3
 *
 * Date:      	2006-08-31
 * Author:    	Wenz
 *
 * Rights:    	Hitex Development Tools GmbH
 *            	Greschbachstr. 12
 *            	D-76229 Karlsruhe
 ********************************************************************
 * Description:
 *	
 * ethernet driver for LPC23xx controller ethernet module.
 * The iplementation is tested on a MCB2300 board with 
 * LPC2378 Controller 
 * DP8348C external PHY
 * 
 ********************************************************************
 * History:
 *
 *  Revision 1.0    2006/09/27      We
 *     Initial revision 
 ********************************************************************
 * This software is provided by the author 'AS IS' without any 
 * warranties. Hitex Development Tools GmbH shall not be held 
 * liable for any direct, indirect or consequential damages with
 * respect to any claims arising from the content of such software.
 ********************************************************************/



#include "peripherals_lpc23xx.h"        /* LPC23xx definitions               */
#include "ethernet_lpc23xx.h"
#include "peripherals_config.h"


/* extern declarations */

/* global function prototypes */

bool		eEthInit(void);
uint32_t	ulReadFrame(uint8_t* aFrameBuffer);
bool		eEthSendFrame(uint32_t frameLength, uint8_t* aFrameBuffer);
void		vEthSetStationAddress( uint8_t*	pAddress);
linkstatus	eGetLinkStatus(uint32_t	aPHYDevice);
void    	vEthIntHandler(void);
void        vEthIntService(void) __attribute__((naked)) ;



/* Local variables */

static const uint32_t	PHYREADCOMMAND = 0x01;
static const uint32_t	PHYWRITECOMMAND = 0x02;

static const uint32_t	MII_COMMAND_TIMEOUT = 0x5000;
static const uint32_t	MII_AUTONEG_TIMEOUT = 0x50000;
static const uint32_t	MII_LINKSTAT_TIMEOUT = 0x50000;

static const uint32_t	PHY_RESET_TIMEOUT = 0x10000;


/*
 *********************************************************************
 *	data for the DMA engine; descriptors
 *  location in ethernet RAM
 *********************************************************************/

 static eth_data*	const pxEthernetData = (eth_data*)ETHDATA_STARTADDRESS;

	
/* data exchange to application or stack 
 * only the length, pointer to data, and status is stored 
 * the data is left inside receive DMA engine				*/

static fragment	uxRxFrame[NUMBER_REC_FRAGMENTS];

static uint32_t	readIndex;
static uint32_t	writeIndex;		


/* error counters	*/

static	uint32_t	ulRxOverrunErrorCounter;
static	uint32_t	ulRxError;
static	uint32_t	ulTxUnderrunErrorCounter;
static	uint32_t	ulTxError;




/* local function prototypes */

static void		prvInitAPI(void);
static void		prvInitDMAEngine(void);

static uint16_t prvConfigurePHY(uint32_t	aPHYDevice);
static uint16_t prvReadPhyRegister( uint32_t aPhyRegisterAdr );
static uint16_t prvWritePhyRegister( uint32_t aPhyRegisterAdr, uint16_t aRegisterValue );
static void		prvConfigureRxFilters(void);

static void		prvReceiveFragment(void);
static void     prvSetupInt(uint32_t aIntSource, uint32_t aIntServiceAdr, uint32_t aPriority ); 


				

/* macros incrementing the index taking wrap around mechannism into account */
 
#define incRxIndex(Index)	if( (++Index) == NUMBER_REC_FRAGMENTS )			\
								Index = 0x00
#define incTxIndex(Index)	if( (++Index) == NUMBER_TX_FRAGMENTS )			\
								Index = 0x00


/****************************************************************************
* Name:			prvInitAPI
*                  	
* Description:	initialize the data which  should 
*				be interfaced to upper layers.
*						
* Parameters:	none
*					
* Return value:	none
*
****************************************************************************
*/
static void prvInitAPI(void)
{
	int		i;

	readIndex	= 0x00;
	writeIndex	= 0x00;

	ulRxOverrunErrorCounter = 0x00;
	ulRxError = 0x00;
	ulTxUnderrunErrorCounter = 0x00;
	ulTxError = 0x00;

	for( i = 0x00; i < NUMBER_REC_FRAGMENTS; i++ )
	{
		uxRxFrame[i].Length = 0x00;
		uxRxFrame[i].pReceived = 0x00;
		uxRxFrame[i].status = 0x00;
	}
}

/****************************************************************************
* Name:			prvInitDMAEngine
*                  	
* Description:	initialize the DMA registers 
*				note: the data to transfer via Ethernet
*				is located in 16K SRAM connected to AHB 1
*				at address 0x7FE00000 	
*				
*						
* Parameters:	none
*					
* Return value:	none
*
****************************************************************************
*/
static void prvInitDMAEngine(void)
{
	uint32_t i;

	// initialize receive DMA
	for( i=0; i < NUMBER_REC_FRAGMENTS; i++ )
	{
		pxEthernetData->xRxDescr[i].packet	 = (uint8_t*)(&pxEthernetData->ucRxBuffer[i][0]);
		pxEthernetData->xRxDescr[i].control  = MAXLENGTH_REC_FRAGMENT;
		pxEthernetData->xRxDescr[i].control |= RX_CONTROL_INT;
		pxEthernetData->xRxStat[i].info = 0x00;
		pxEthernetData->xRxStat[i].hashCRC = 0x00;
	}

	// configure receive descriptor register
	ETH_RXDESC	= (volatile uint32_t)&pxEthernetData->xRxDescr[0];					// start of rec data descr. table
	ETH_RXSTAT	= (volatile uint32_t)&pxEthernetData->xRxStat[0];					// start of rec status info table
	ETH_RXDESCRNO = NUMBER_REC_FRAGMENTS -1;	// number of descriptors -1	

	ETH_RXCONSIX = 0x00;						// consumer index	

	// initialize transmit DMA
	for( i=0; i < NUMBER_TX_FRAGMENTS; i++ )
	{
		pxEthernetData->xTxDescr[i].packet	 = &pxEthernetData->ucTxBuffer[i][0];
		pxEthernetData->xTxDescr[i].control  = 0x00;
		pxEthernetData->xTxStat[i].status	 = 0x00;
	}

	// configure transmit descriptor register
	ETH_TXDESC = (volatile uint32_t)&pxEthernetData->xTxDescr[0];					// start of transmit data table 
	ETH_TXSTAT = (volatile uint32_t)&pxEthernetData->xTxStat[0];					// start of transmit status table
	ETH_TXDESCRNO = NUMBER_TX_FRAGMENTS -1;	// number of descriptors -1	

	ETH_TXPRODIX = 0x00;						// producer index
}

/****************************************************************************
* Name:			prvReadPhyRegister
*                  	
* Description:	read a given register from phy ethernet  	
*				
*						
* Parameters:	aPhyRegisterAdr
*					address of the PHY register which is concatenated 
*					of device + register offset 
*					
* Return value:	register value (32 Bits) or 0xFFFF if access fails
*
****************************************************************************
*/
static uint16_t prvReadPhyRegister( uint32_t aPhyRegisterAdr )
{
	uint32_t	aTimeout;
	uint32_t 	aMII_Indicator;
	uint16_t	aRegisterValue = 0xFFFF;
	
   	ETH_MIIADR = aPhyRegisterAdr;
   	ETH_MIICMD = PHYREADCOMMAND;

	/* Wait until operation completed */

   	for (aTimeout = 0; aTimeout < MII_COMMAND_TIMEOUT; aTimeout++)
   	{
   		aMII_Indicator = ETH_MIIIND;
   		
      	if((aMII_Indicator & (0x01 << MII_IND_BUSY)) == 0)
      	{
      		aRegisterValue = (uint16_t)ETH_MIIRDD; 
        	break;
        }
   	}
   	ETH_MIICMD = 0x00;
   	return (aRegisterValue);
}

/****************************************************************************
* Name:			prvWritePhyRegister
*                  	
* Description:	write valuie to a given register of ethernet-phy  	
*				
*						
* Parameters:	aPhyRegisterAdr
*					address of the PHY register which is concatenated 
*					of device + register offset 
*				aRegisterValue
*					data to write
*					
* Return value:	0x00 	--> ok
*				0xFFFF 	--> fail
*
****************************************************************************
*/
static uint16_t prvWritePhyRegister( uint32_t aPhyRegisterAdr, uint16_t aRegisterValue )
{
	uint32_t	aTimeout;
	uint32_t 	aMII_Indicator;
	uint16_t	ret = 0xFFFF;
	
   	ETH_MIIADR = aPhyRegisterAdr;
    ETH_MIIWTD = aRegisterValue;


	/* Wait until operation completed */

   	for (aTimeout = 0; aTimeout < MII_COMMAND_TIMEOUT; aTimeout++)
   	{
   		aMII_Indicator = ETH_MIIIND;
   		
      	if((aMII_Indicator & ( 0x01 << MII_IND_BUSY)) == 0)
      	{
      		ret = 0x00;
        	break;
        }
   	}
   	return (ret);
}

/****************************************************************************
* Name:			prvConfigurePHY
*                  	
* Description:	configures the PHY registers according to 	
*				settings in config.h  
*				
*						
* Parameters:	aPHYDevice
*					address of the phy device in ETH
*					
* Return value:	extended Status register of DP83848C PHY
*				indicates link status among others
*
****************************************************************************
*/

static uint16_t  prvConfigurePHY(uint32_t	aPHYDevice)
{
	uint32_t	phyAddress = aPHYDevice << 8;
	uint32_t 	phyId = 0x00;
	uint32_t	aTimeout;
	uint16_t	basicModeStatus, extendedStatus, basicModeControl;


   /* Put the DP83848C in reset mode */
   prvWritePhyRegister (phyAddress | PHY_BMCR, 0x8000);

   /* Wait for hardware reset to end. */
   for (aTimeout = 0; aTimeout < PHY_RESET_TIMEOUT; aTimeout++)
   {
      basicModeControl = prvReadPhyRegister (phyAddress | PHY_BMCR);
      if (!(basicModeControl & PHY_RESET))
	  {
         /* Reset complete */
         break;
      }
   }

	// first of all check for the ethernet phy device
	
	phyId = prvReadPhyRegister( phyAddress | PHY_IDR1 );
	phyId <<= 16;
	phyId |= prvReadPhyRegister( phyAddress | PHY_IDR2 );

	// actually supports only DP83848C Phyter 
	switch( phyId)
	{
	case DP83848C_ID:

		if( LOOPBACK)
			prvWritePhyRegister( phyAddress | PHY_BMCR, PHY_FULLD_100M | PHY_LOOPBACK);

		else
		{
			switch( PHYSPEED )
			{
			case AUTONEGOTIATION:

				/* configure autonegotiation  */
				prvWritePhyRegister( phyAddress | PHY_BMCR, PHY_AUTO_NEG | PHY_RESTART_AUTON);

				/* Wait to complete Auto_Negotiation. */
   				for (aTimeout = 0; aTimeout < MII_AUTONEG_TIMEOUT; aTimeout++)
				{
					basicModeStatus = prvReadPhyRegister (phyAddress | PHY_BMSR);
					if (basicModeStatus & PHY_AUTO_DONE)				// autonegotiation complete
						break;
				}
				break;
		
			case FDX_100:
				prvWritePhyRegister( phyAddress | PHY_BMCR, PHY_FULLD_100M );
				break;

			case FDX_10:
				prvWritePhyRegister( phyAddress | PHY_BMCR, PHY_FULLD_10M );
				break;

			case HDX_100:
				prvWritePhyRegister( phyAddress | PHY_BMCR, PHY_HALFD_100M );
				break;

			case HDX_10:
				prvWritePhyRegister( phyAddress | PHY_BMCR, PHY_HALFD_10M );
				break;

			default: 
				prvWritePhyRegister( phyAddress | PHY_BMCR, PHY_AUTO_NEG | PHY_RESTART_AUTON);
				break;

			}
		}
		/* Check the link status. */
		for (aTimeout = 0; aTimeout < MII_LINKSTAT_TIMEOUT; aTimeout++)
		{
			extendedStatus = prvReadPhyRegister (phyAddress | PHY_STS);
			if (extendedStatus & PHY_EXST_LINK_ESTABLISHED)			// link status 
				break;
		}
 		break;
	default :
		break;
	}
	return( extendedStatus);
}
/****************************************************************************
* Name:			prvConfigureRxFilters
*                  	
* Description:	configure receive filtering  
*				
*						
* Parameters:	none
*					
* Return value:	none
*  
****************************************************************************
*/

static void prvConfigureRxFilters(void)
{
	if(ACCEPTUNICAST)
		ETH_RXFILTERCTL  = RFC_UCAST_EN;		/* Accept Unicast Frames Enable      */

	if(ACCEPTBROADCAST)
		ETH_RXFILTERCTL |= RFC_BCAST_EN;		/* Accept Broadcast Frames Enable    */

	if(ACCEPTMULTICAST)
		ETH_RXFILTERCTL |= RFC_MCAST_EN;		/* Accept Multicast frames Enable    */

	if(ACCEPTPERFECT)
		ETH_RXFILTERCTL |= RFC_PERFECT_EN;		/* Accept Perfect Match Enable       */
}

/****************************************************************************
* Name:			vSetStationAddress
*                  	
* Description:	set the MAC address  
*				
*						
* Parameters:	pointer to byte array containing 6 bytes station address
*					
* Return value:	none
*  
****************************************************************************
*/
void vEthSetStationAddress( uint8_t*	pAddress)
{
	ETH_SA0 = ( (uint32_t)pAddress[0] <<8) | (uint32_t)pAddress[1];
	ETH_SA1 = ( (uint32_t)pAddress[2] <<8) | (uint32_t)pAddress[3];
	ETH_SA2 = ( (uint32_t)pAddress[4] <<8) | (uint32_t)pAddress[5];
}

/****************************************************************************
* Name:			vEthInit
*                  	
* Description:	Initialize  
*				
*						
* Parameters:	none
*					
* Return value:	TRUE -->  driver successfully initialized, link established
*				FALSE --> driver not initialized.
*
****************************************************************************
*/
bool eEthInit(void)
{
	uint16_t	aPhyStatus = 0x00;
	uint8_t		aMACAddress[6];
	uint32_t	Timeout;

	/* initialize data to application (stack) */
	prvInitAPI();

   	/* Power Up the ethernet MAC controller. */
   	PCONP |= PCON_ENET;

   	/* Ethernet port is GPIO_1 P1.0 up to P1.17  			
   	   enable ethernet by switching to Pinfunction 2 = 01    */

#ifdef RMII_INTERFACE  	
    /* P1.6, ETHERNET-TX_CLK, has to be set for ethernet module to address a BUG in 
		the engineering 
		version, even if this pin is not used for RMII interface. This bug has been fixed,
		and this port pin can be used as GPIO pin in the future release.  
		Unfortunately, this MCB2300 board still has the old eng. version LPC23xx chip
		on it. */
    PINSEL2 = 0x50151105;	/* selects P1[0,1,4,8,9,10,14,15] */
    PINSEL3 = 0x00000005;	/* selects P1[17:16] */

#elif 
	PINSEL2 = 0x55555555;							/* selects P1[15:0] */
   	PINSEL3 = (PINSEL3 & ~0x0000000F) | 0x00000005;	/* selects P1[17:16] */
#endif

	/* Reset all MAC internal modules. */
	ETH_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |
               MAC1_SIM_RES | MAC1_SOFT_RES;

	/* reset all datapaths and the host registers */
	ETH_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES;
 
	/* A short delay after reset. */
	for (Timeout = 200; Timeout; Timeout--);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -