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

📄 bsp_lpc32xx_eth.c

📁 NXP LPC3000系列 wince BSP包
💻 C
📖 第 1 页 / 共 2 页
字号:
//*********************************************************************
//* 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 + -