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

📄 emac.c

📁 Hello I Send som Source Code Aboat LPC2000
💻 C
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
 *   emac.c:  Ethernet module file for NXP LPC230x Family Microprocessors
 *
 *   Copyright(C) 2006, NXP Semiconductor
 *   All rights reserved.
 *
 *   History
 *   2006.09.01  ver 1.00    Prelimnary version, first Release
 *
******************************************************************************/
#include "LPC23xx.h"                        /* LPC21xx definitions */
#include "type.h"
#include "target.h"
#include "irq.h"
#include "emac.h"

volatile DWORD Duplex;
volatile DWORD Speed;

volatile DWORD RXOverrunCount = 0;
volatile DWORD RXErrorCount = 0;

volatile DWORD TXUnderrunCount = 0;
volatile DWORD TXErrorCount = 0;
volatile DWORD RxFinishedCount = 0;
volatile DWORD TxFinishedCount = 0;
volatile DWORD TxDoneCount = 0;
volatile DWORD RxDoneCount = 0;

volatile DWORD CurrentRxPtr = EMAC_RX_BUFFER_ADDR;
volatile DWORD ReceiveLength = 0;
volatile DWORD PacketReceived = FALSE;

#if ENABLE_WOL
volatile DWORD WOLCount = 0;
volatile DWORD WOLArrived = FALSE;
#endif


/******************************************************************************
** Function name:		EMAC_TxEnable/EMAC_TxDisable
**
** Descriptions:		EMAC TX API modules
**
** parameters:			None
** Returned value:		None
** 
******************************************************************************/
void EMAC_TxEnable( void )
{
  MAC_COMMAND |= 0x02;
  return;
}

void EMAC_TxDisable( void )
{
  MAC_COMMAND &= ~0x02;
  return;
}

/******************************************************************************
** Function name:		EMAC_RxEnable/EMAC_RxDisable
**
** Descriptions:		EMAC RX API modules
**
** parameters:			None
** Returned value:		None
** 
******************************************************************************/
void EMAC_RxEnable( void )
{
  MAC_COMMAND |= 0x01;
  MAC_MAC1 |= 0x01;
  return;    
}

void EMAC_RxDisable( void )
{
  MAC_COMMAND &= ~0x01;
  MAC_MAC1 &= ~0x01;
  return;
}

/******************************************************************************
** Function name:		EMACHandler
**
** Descriptions:		EMAC interrupt handler
**
** parameters:			None
** Returned value:		None
** 
******************************************************************************/
void EMACHandler (void) __irq 
{
  volatile DWORD IntStatus;
  DWORD *rxptr;

  IENABLE;				/* handles nested interrupt */

  IntStatus = MAC_INTSTATUS;    
  if ( IntStatus != 0 )	/* At least one interrupt */
  {
#if ENABLE_WOL
	if ( IntStatus & EMAC_INT_WOL )
	{
	  MAC_INTCLEAR = EMAC_INT_WOL;
	  WOLCount++;
	  WOLArrived = TRUE;
	  /* the packet will be lost, no need to anything else, bail out */
	  IDISABLE;
	  VICVectAddr = 0;		/* Acknowledge Interrupt */
	  return;
	}
#endif
	if ( IntStatus & EMAC_INT_RXOVERRUN )
	{
	  MAC_INTCLEAR = EMAC_INT_RXOVERRUN;
	  RXOverrunCount++;
	  IDISABLE;
	  VICVectAddr = 0;		/* Acknowledge Interrupt */
	  return;
	}

	if ( IntStatus & EMAC_INT_RXERROR )
	{
	  MAC_INTCLEAR = EMAC_INT_RXERROR;
	  RXErrorCount++;
	  IDISABLE;
	  VICVectAddr = 0;		/* Acknowledge Interrupt */
	  return;
	}
	
	if ( IntStatus & EMAC_INT_RXFINISHED )
	{
	  MAC_INTCLEAR = EMAC_INT_RXFINISHED;
	  RxFinishedCount++;
	  /* Below should never happen or RX is seriously wrong */
	  while ( MAC_RXPRODUCEINDEX != (MAC_RXCONSUMEINDEX - 1) );
	}

	if ( IntStatus & EMAC_INT_RXDONE )
	{
	  MAC_INTCLEAR = EMAC_INT_RXDONE;
	  ReceiveLength = EMACReceive( rxptr );
	  PacketReceived = TRUE;
	  RxDoneCount++;
	}

	if ( IntStatus & EMAC_INT_TXUNDERRUN )
	{
	  MAC_INTCLEAR = EMAC_INT_TXUNDERRUN;
	  TXUnderrunCount++;
	  IDISABLE;
	  VICVectAddr = 0;		/* Acknowledge Interrupt */
	  return;
	}
	
	if ( IntStatus & EMAC_INT_TXERROR )
	{
	  MAC_INTCLEAR = EMAC_INT_TXERROR;
	  TXErrorCount++;
	  IDISABLE;
	  VICVectAddr = 0;		/* Acknowledge Interrupt */
	  return;
	}

	if ( IntStatus & EMAC_INT_TXFINISHED )
	{
	  MAC_INTCLEAR = EMAC_INT_TXFINISHED;
	  TxFinishedCount++;
	}

	if ( IntStatus & EMAC_INT_TXDONE )
	{
	  MAC_INTCLEAR = EMAC_INT_TXDONE;
	  TxDoneCount++;
	}
  }   
  IDISABLE;
  VICVectAddr = 0;		/* Acknowledge Interrupt */
  return;
}

/*****************************************************************************
** Function name:		WritePHY
**
** Descriptions:		Write Data to the PHY port
**
** parameters:			PHY register, write data
** Returned value:		None
** 
*****************************************************************************/
void WritePHY( DWORD PHYReg, DWORD PHYData )
{
  MAC_MCMD = 0x0000;			/* write command */
  MAC_MADR = PHY_ADDR | PHYReg;	/* [12:8] == PHY addr, [4:0]=register addr */
  MAC_MWTD = PHYData;
  while ( MAC_MIND != 0 );
  return;
}

/*****************************************************************************
** Function name:		ReadPHY
**
** Descriptions:		Read data from the PHY port
**
** parameters:			PHY register
** Returned value:		PHY data
** 
*****************************************************************************/
DWORD ReadPHY( DWORD PHYReg )
{
  MAC_MCMD = 0x0001;			/* read command */
  MAC_MADR = PHY_ADDR | PHYReg;	/* [12:8] == PHY addr, [4:0]= register addr */
  while ( (MAC_MIND & 0x05) != 0 );
  MAC_MCMD = 0x0000;
  return( MAC_MRDD );
}

/*****************************************************************************
** Function name:		PHYInit
**
** Descriptions:		initialize PHY port
**
** parameters:			PHYType
** Returned value:		None
** 
*****************************************************************************/
DWORD PHYInit( DWORD PHYType )
{
  DWORD i, regValue;
  DWORD timeout;

  /* MII configuration, I may just need to do either RMII or MII configuration, not both. */
  MAC_MCFG = 0x8018;	/* host clock divided by 20, no suppress preamble, no scan increment */
  for ( i = 0; i < 0x40; i++ );
  MAC_MCFG = 0x0018;	/* Apply a reset */
  MAC_MCMD = 0;	
#if RMII 
  /* RMII configuration */
  MAC_COMMAND |= 0x0200;
  /* PHY support: [8]=0 ->10 Mbps mode, =1 -> 100 Mbps mode */ 
  MAC_SUPP = 0x0100;	/* RMII setting, at power-on, default set to 100. */
#else
  MAC_COMMAND &= ~0x0200;
  MAC_SUPP = 0x0000;
#endif

  for ( i = 0; i < 0x100; i++ );	/* short delay */

  WritePHY( PHY_BMCR, BMCR_RESET );
  for ( i = 0; i < 0x20; i++ );	/* short delay */

  timeout = MII_BMSR_TIMEOUT * 4;
  while ( timeout != 0 )
  {
	regValue = ReadPHY( PHY_BMCR );
	if ( (regValue & BMCR_RESET) == 0x0000 )	
	{
	  break;		/* Reset self cleaned once the reset process is complete */	
	}
	timeout--;	
  }
  if ( timeout == 0 )
  {
	return ( FALSE );
  }

  if ( PHYType == NATIONAL_PHY )
  {
	/* check PHY IDs to make sure the reset takes place and PHY
	is in its default state. See National PHY DP83848 Users Manual 
	for more details */
	regValue = ReadPHY( PHY_PHYIDR1 );
	if ( (regValue & 0x2000) != 0x2000 )
	{
	  return ( FALSE );
	}

	regValue = ReadPHY( PHY_PHYIDR2 );
	if ( (regValue & 0x5C90) != 0x5C90 )
	{
	  return ( FALSE );
	}
  }
  else if ( PHYType == MICREL_PHY )
  {
	regValue = ReadPHY( PHY_PHYIDR1 );
	if ( (regValue & 0x00FF) != 0x0022 )
	{
	  return ( FALSE );
	}

	regValue = ReadPHY( PHY_PHYIDR2 );
	if ( (regValue & 0x1610) != 0x1610 )
	{
	  return ( FALSE );
	}
  }

  WritePHY( PHY_BMCR, BMCR_AN | BMCR_RE_AN ); /* auto negotiation, restart AN */
  /* RE_AN should be self cleared */
//	while ( ((regValue = ReadPHY( PHY_BMCR )) & BMCR_RE_AN) );

  if ( PHYType == NATIONAL_PHY )
  { 
	timeout = MII_BMSR_TIMEOUT;
	while ( timeout != 0 )
	{
	  regValue = ReadPHY( NSM_PHY_PHYSTS );
	  if ( (regValue & 0x0011) == 0x0011 )	
	  {
		break;		/* link established if bit 0 is set */
	  }
	  timeout--;
	}

	if ( timeout == 0 )
	{
	  return ( FALSE );
	}

	/* Link established from here on */
	if ( regValue & 0x04 )
	  Duplex = FULL_DUPLEX;
	else
	  Duplex = HALF_DUPLEX;

	if ( regValue & 0x02 )
	  Speed = SPEED_10;
	else
	  Speed = SPEED_100;
  }

  else if ( PHYType == MICREL_PHY )
  { 
	timeout = MII_BMSR_TIMEOUT;
	while ( timeout != 0 )
	{
	  regValue = ReadPHY( PHY_BMSR );
	  if ( (regValue & (BMSR_AUTO_DONE|BMSR_LINK_ESTABLISHED)) 
			== (BMSR_AUTO_DONE|BMSR_LINK_ESTABLISHED) )	
	  {
		break;		/* auto nego complete and link established if bit 2 
					and 5 are set */
	  }
	  timeout--;
	}
    if ( timeout == 0 )
	{
	  return ( FALSE );
	}

	regValue = ReadPHY( MIC_PHY_100BASE_PHY_CTRL );
	/* successful negotiations; update link info */
	regValue &= 0x001C;
	switch ( regValue )
	{
	  case 0x0004:
		Speed = SPEED_10;
		Duplex = HALF_DUPLEX;
	  break;
	  case 0x0008:
		Speed = SPEED_100;
		Duplex = HALF_DUPLEX;
	  break;
	  case 0x0014:
		Speed = SPEED_10;
		Duplex = FULL_DUPLEX;
	  break;
	  case 0x0018:
		Speed = SPEED_100;
		Duplex = FULL_DUPLEX;
	  break;
	  default:	// Should not come here, force to set default, 100 FULL_DUPLEX
		Speed = SPEED_100;
		Duplex = FULL_DUPLEX;
		break;
	}
  }
  return ( TRUE );
}

/*****************************************************************************
** Function name:		EMACTxDesciptorInit
**
** Descriptions:		initialize EMAC TX descriptor table
**
** parameters:			None
** Returned value:		None
** 
*****************************************************************************/
void EMACTxDescriptorInit( void )
{
  DWORD i;
  DWORD *tx_desc_addr, *tx_status_addr;
   
  /*-----------------------------------------------------------------------------      
   * setup the Tx status,descriptor registers -- 
   * Note, the actual tx packet data is loaded into the ahb2_sram16k memory as part
   * of the simulation
   *----------------------------------------------------------------------------*/ 
  MAC_TXDESCRIPTOR = TX_DESCRIPTOR_ADDR;	/* Base addr of tx descriptor array */
  MAC_TXSTATUS = TX_STATUS_ADDR;		/* Base addr of tx status */
  MAC_TXDESCRIPTORNUM = EMAC_TX_DESCRIPTOR_COUNT - 1;	/* number of tx descriptors, 16 */

  for ( i = 0; i < EMAC_TX_DESCRIPTOR_COUNT; i++ )
  {
	tx_desc_addr = (DWORD *)(TX_DESCRIPTOR_ADDR + i * 8);	/* two words at a time, packet and control */
	*tx_desc_addr = (DWORD)(EMAC_TX_BUFFER_ADDR + i * EMAC_BLOCK_SIZE);
	*(tx_desc_addr+1) = (DWORD)(EMAC_TX_DESC_INT | (EMAC_BLOCK_SIZE - 1));	/* set size only */
  }
    
  for ( i = 0; i < EMAC_TX_DESCRIPTOR_COUNT; i++ )
  {
	tx_status_addr = (DWORD *)(TX_STATUS_ADDR + i * 4);	/* TX status, one word only, status info. */
	*tx_status_addr = (DWORD)0;		/* initially, set status info to 0 */
  }
  MAC_TXPRODUCEINDEX = 0x0;	/* TX descriptors point to zero */
  return;

⌨️ 快捷键说明

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