📄 emac.c
字号:
/*****************************************************************************
* 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 <string.h>
#include "LPC23xx.H" /* LPC21xx definitions */
#include "type.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]=0x00(BMCR) 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]=0x00(BMCR) register addr */
while ( MAC_MIND != 0 );
MAC_MCMD = 0x0000;
return( MAC_MRDD );
}
/*****************************************************************************
** Function name: PHYInit
**
** Descriptions: initialize PHY port
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
DWORD PHYInit( void )
{
DWORD i, regValue;
DWORD timeout;
/* MII configuration, I may just need to do either RMII or MII configuration, not both. */
MAC_MCFG = 0x0018; /* host clock divided by 20, no suppress preamble, no scan increment */
#if RMII
/* RMII configuration */
MAC_COMMAND |= 0x0200;
MAC_SUPP = 0x0900; /* RMII setting, PHY support: [8]=0 ->10 Mbps mode, =1 -> 100 Mbps mode */
/* (note bit 4 was set in original test, although spec says its unused) */
for ( i = 0; i < 0x20; i++ ); /* short delay */
MAC_SUPP = 0x0100;
#else
MAC_COMMAND &= ~0x0200;
MAC_SUPP = 0x0000;
#endif
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 );
}
/* 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 );
}
WritePHY( PHY_BMCR, BMCR_AN | BMCR_RE_AN ); /* auto negotiation, restart AN */
timeout = MII_BMSR_TIMEOUT;
while ( timeout != 0 )
{
regValue = ReadPHY( 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;
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;
}
/*****************************************************************************
** Function name: EMACRxDesciptorInit
**
** Descriptions: initialize EMAC RX descriptor table
**
** parameters: None
** Returned value: None
**
*****************************************************************************/
void EMACRxDescriptorInit( void )
{
DWORD i;
DWORD *rx_desc_addr, *rx_status_addr;
/*-----------------------------------------------------------------------------
* setup the Rx status,descriptor registers --
* Note, the actual rx packet data is loaded into the ahb2_sram16k memory as part
* of the simulation
*----------------------------------------------------------------------------*/
MAC_RXDESCRIPTOR = RX_DESCRIPTOR_ADDR; /* Base addr of rx descriptor array */
MAC_RXSTATUS = RX_STATUS_ADDR; /* Base addr of rx status */
MAC_RXDESCRIPTORNUM = EMAC_RX_DESCRIPTOR_COUNT - 1; /* number of rx descriptors, 16 */
for ( i = 0; i < EMAC_RX_DESCRIPTOR_COUNT; i++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -