📄 bsp_lpc32xx_eth.c
字号:
//*********************************************************************
//* Software that is described herein is for illustrative purposes only
//* which provides customers with programming information regarding the
//* products. This software is supplied "AS IS" without any warranties.
//* NXP Semiconductors assumes no responsibility or liability for the
//* use of the software, conveys no license or title under any patent,
//* copyright, or mask work right to the product. NXP Semiconductors
//* reserves the right to make changes in the software without
//* notification. NXP Semiconductors also make no representation or
//* warranty that such application will be suitable for the specified
//* use without further testing or modification.
//*
//* Copyright NXP Semiconductors
//*********************************************************************
//
// bsp_lpc32xx_eth.h
//
// Ethernet support functions for KITL and EBOOT download
//
#include <windows.h>
#include <halether.h>
#include <oal.h>
#include "image_cfg.h"
#include "bsp_phyc32xx_phy.h"
#include "lpc32xx_mac.h"
#include "lpc32xx_clkpwr.h"
#include "phy3250_board.h"
// Driver data
static ETHERNET_REGS_T *pEregs;
static CLKPWR_REGS_T *pClkpwr;
static BOOL init;
static UINT32 smac [3];
static UINT32 g_dmabase;
static UINT32 gdma_size;
static TXRX_DESC_T *pTXDesc;
static UINT32 *pTXStatus;
static UINT32 pTXVBuffs [ENET_MAX_TX_PACKETS];
static TXRX_DESC_T *pRXDesc;
static RX_STATUS_T *pRXStatus;
static UINT32 pRXVBuffs [ENET_MAX_RX_PACKETS];
// External PHYTEC hardware structure with MAC address
extern PHY_HW_T phyhwdesc;
// Returns the ethernet DMA buffer address and size
extern void OEMGetEthBuffers(UINT32 *dmabase, UINT32 *dmasize);
UINT16 LPC32XX_Eth_SendFrame(UINT8 *pbData, UINT32 length);
//------------------------------------------------------------------------------
//
// msDelay
//
// Delay a number of milliSeconds
//
VOID msDelay(UINT32 ms)
{
UINT32 mswval = OALGetTickCount() + ms;
while (mswval > OALGetTickCount());
}
//------------------------------------------------------------------------------
//
// RMII_Write
//
// Write a value to a RMII PHY register
//
static BOOL RMII_Write (UINT32 PhyReg, UINT32 Value)
{
UINT32 mst = 250;
BOOL sts = FALSE;
// Write value at PHY address and register
pEregs->madr = (PHYDEF_PHYADDR << 5) | PhyReg;
pEregs->mwtd = Value;
// Wait for unbusy status
while (mst > 0)
{
if ((pEregs->mind & MIND_BUSY) == 0)
{
mst = 0;
sts = TRUE;
}
else
{
mst--;
msDelay(1);
}
}
if (sts == FALSE)
{
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"RMII_Write:PHY register %d write timed out = 0x%08x\r\n", PhyReg));
}
return sts;
}
//------------------------------------------------------------------------------
//
// RMII_Read
//
// Read a value from a RMII PHY register
//
BOOL RMII_Read(UINT32 PhyReg, UINT32 *data)
{
UINT32 mst = 250;
BOOL sts = FALSE;
// Read value at PHY address and register
pEregs->madr = (PHYDEF_PHYADDR << 5) | PhyReg;
pEregs->mcmd = MCMD_READ;
// Wait for unbusy status
while (mst > 0)
{
if ((pEregs->mind & MIND_BUSY) == 0)
{
mst = 0;
*data = pEregs->mrdd;
sts = TRUE;
}
else
{
mst--;
msDelay(1);
}
}
pEregs->mcmd = 0;
if (sts == FALSE)
{
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"RMII_Read:PHY register %d read timed out = 0x%08x\r\n", PhyReg));
}
return sts;
}
//------------------------------------------------------------------------------
//
// HYPHYReset
//
// Reset the PHY
//
BOOL HYPHYReset(VOID)
{
BOOL goodacc;
UINT32 tmp1, mst;
// Reset the PHY and wait for reset to complete
goodacc = RMII_Write(PHY_REG_BMCR, PHY_BMCR_RESET_BIT);
if (goodacc == FALSE)
{
return FALSE;
}
mst = 400;
goodacc = FALSE;
while (mst > 0)
{
RMII_Read(PHY_REG_BMCR, &tmp1);
if ((tmp1 & PHY_BMCR_RESET_BIT) == 0)
{
mst = 0;
goodacc = TRUE;
}
else
{
mst--;
msDelay(1);
}
}
return goodacc;
}
//------------------------------------------------------------------------------
//
// txrx_setup
//
// Setup transmit and receive descriptors
//
BOOL txrx_setup(VOID)
{
INT32 idx;
UINT32 *pTXStatusL, pbase1, pbase2, pbase3;
TXRX_DESC_T *pTXRXDesc;
RX_STATUS_T *pRXStatusL;
// Get physical address and size of DMA buffers
OEMGetEthBuffers(&g_dmabase, &gdma_size);
// Setup base pointers
pbase1 = g_dmabase; // Start of descriptors
pbase2 = pbase1 + 256; // Start of statuses
pbase3 = pbase1 + 1024; // Start of buffers
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"+txrx_setup buffer physical address at 0x%x with size %d\r\n",
g_dmabase, gdma_size));
// Setup pointers to TX structures
pEregs->txdescriptor = pbase1;
pEregs->txstatus = pbase2;
pEregs->txdescriptornumber = (ENET_MAX_TX_PACKETS - 1);
// Save base address of TX descriptor table and TX status
pTXRXDesc = (TXRX_DESC_T *) OALPAtoVA(pbase1, FALSE);
pTXStatusL = (UINT32 *) OALPAtoVA(pbase2, FALSE);
pTXDesc = pTXRXDesc;
pTXStatus = pTXStatusL;
// Build TX descriptors
for (idx = 0; idx < ENET_MAX_TX_PACKETS; idx++)
{
pTXRXDesc->packet = pbase3;
pTXRXDesc->control = 0;
*pTXStatusL = 0;
// Save virtual address of buffer
pTXVBuffs [idx] = (UINT32) OALPAtoVA(pbase3, FALSE);
// Next descriptor and status
pTXRXDesc++;
pTXStatusL++;
pbase1 += sizeof (TXRX_DESC_T);
pbase2 += sizeof (UINT32);
pbase3 += ENET_MAXF_SIZE;
}
// Setup pointers to RX structures
pEregs->rxdescriptor = pbase1;
pEregs->rxstatus = pbase2;
pEregs->rxdescriptornumber = (ENET_MAX_RX_PACKETS - 1);
// Save base address of RX descriptor table and RX status
pRXDesc = pTXRXDesc;
pRXStatus = pRXStatusL = (RX_STATUS_T *) pTXStatusL;
// Build RX descriptors
for (idx = 0; idx < ENET_MAX_TX_PACKETS; idx++)
{
pTXRXDesc->packet = pbase3;
pTXRXDesc->control = 0x80000000 | (ENET_MAXF_SIZE - 1);
pRXStatusL->statusinfo = 0;
pRXStatusL->statushashcrc = 0;
// Save virtual address of buffer
pRXVBuffs [idx] = (UINT32) OALPAtoVA(pbase3, FALSE);
// Next descriptor and status
pTXRXDesc++;
pRXStatusL++;
pbase1 += sizeof (TXRX_DESC_T);
pbase2 += sizeof (UINT32);
pbase3 += ENET_MAXF_SIZE;
}
return TRUE;
}
//------------------------------------------------------------------------------
//
// HWInit
//
// Initialize ethernet and PHY hardware
//
BOOL HWInit(VOID)
{
BOOL btemp, goodacc;
UINT32 tmp1, tmp2, mst = 250;
if (init == TRUE)
{
// Previously initialized, do nothing
return TRUE;
}
init = TRUE;
// Enable MAC interface
pClkpwr->clkpwr_macclk_ctrl = (CLKPWR_MACCTRL_HRCCLK_EN |
CLKPWR_MACCTRL_MMIOCLK_EN | CLKPWR_MACCTRL_DMACLK_EN |
#ifdef USE_PHY_RMII
CLKPWR_MACCTRL_USE_RMII_PINS);
#else
CLKPWR_MACCTRL_USE_MII_PINS);
#endif
// Set RMII management clock rate. This clock should be slower
// than 12.5MHz (for NXP PHYs only). For a divider of 28, the
// clock rate when HCLK is 150MHz will be 5.4MHz
pEregs->mcfg = MCFG_CLOCK_SELECT(MCFG_CLOCK_HOST_DIV_28);
// Reset all MAC logic
pEregs->mac1 = (MAC1_SOFT_RESET | MAC1_SIMULATION_RESET |
MAC1_RESET_MCS_TX | MAC1_RESET_TX | MAC1_RESET_MCS_RX |
MAC1_RESET_RX);
pEregs->command = (COMMAND_REG_RESET | COMMAND_TXRESET |
COMMAND_RXRESET);
msDelay(10);
// Initial MAC initialization
pEregs->mac1 = MAC1_PASS_ALL_RX_FRAMES;
pEregs->mac2 = (MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE);
pEregs->maxf = ENET_MAXF_SIZE;
// Maximum number of retries, 0x37 collision window, gap */
pEregs->clrt = (CLRT_LOAD_RETRY_MAX(0xF) |
CLRT_LOAD_COLLISION_WINDOW(0x37));
pEregs->ipgr = IPGR_LOAD_PART2(0x12);
#ifdef USE_PHY_RMII
// RMII setup
pEregs->command = (COMMAND_RMII | COMMAND_PASSRUNTFRAME);
pEregs->supp = SUPP_RESET_RMII;
msDelay(10);
#else
// MII setup
pEregs->command = COMMAND_PASSRUNTFRAME;
#endif
// Reset PHY
goodacc = HYPHYReset();
if (goodacc == FALSE)
{
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"ENET:Reset of PHY timed out\r\n"));
return FALSE;
}
// Get PHY ID
RMII_Read(PHY_REG_IDR1, &tmp1);
RMII_Read(PHY_REG_IDR2, &tmp2);
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"ENET:PHY ID 1 register = 0x%08x\r\n", tmp1));
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"ENET:PHY ID 2 register = 0x%08x\r\n", tmp2));
// Enable rate auto-negotiation for the link
if (RMII_Write(PHY_REG_BMCR,
(PHY_BMCR_SPEED_BIT | PHY_BMCR_AUTON_BIT)) == FALSE)
{
return FALSE;
}
// Wait up to 5 seconds for auto-negotiation to finish
mst = 5000;
goodacc = TRUE;
btemp = FALSE;
while (mst > 0)
{
goodacc &= RMII_Read(PHY_REG_BMSR, &tmp1);
if ((tmp1 & PHY_BMSR_AUTON_COMPLETE) != 0)
{
mst = 0;
btemp = TRUE;
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"ENET:auto-negotiation complete\r\n"));
}
else
{
mst--;
msDelay(1);
}
}
if ((goodacc == FALSE) || (btemp == FALSE))
{
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"ENET:auto-negotiation failed\r\n"));
return FALSE;
}
// Check link status
mst = 1000;
goodacc = TRUE;
btemp = FALSE;
while (mst > 0)
{
goodacc &= RMII_Read(PHY_REG_BMSR, &tmp1);
if ((tmp1 & PHY_BMSR_LINKUP_STATUS) != 0)
{
mst = 0;
btemp = TRUE;
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"ENET:Link status up\r\n"));
}
else
{
mst--;
msDelay(1);
}
}
if ((goodacc == FALSE) || (btemp == FALSE))
{
OALMSGS((OAL_ETHER && OAL_FUNC),
(L"ENET:Link status failure\r\n"));
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -