📄 lpc177x_8x_emac.c
字号:
**********************************************************************
* $Id$ lpc177x_8x_emac.c 2011-06-02
*//**
* @file lpc177x_8x_emac.c
* @brief Contains all functions support for Ethernet MAC firmware
* library on LPC177x_8x
* @version 1.0
* @date 02. June. 2011
* @author NXP MCU SW Application Team
*
* Copyright(C) 2011, NXP Semiconductor
* All rights reserved.
*
***********************************************************************
* 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.
* Permission to use, copy, modify, and distribute this software and its
* documentation is hereby granted, under NXP Semiconductors'
* relevant copyright in the software, without fee, provided that it
* is used in conjunction with NXP Semiconductors microcontrollers. This
* copyright, permission, and disclaimer notice must appear in all copies of
* this code.
**********************************************************************/
#ifdef __BUILD_WITH_EXAMPLE__
#include "lpc177x_8x_libcfg.h"
#else
#include "lpc177x_8x_libcfg_default.h"
#endif /* __BUILD_WITH_EXAMPLE__ */
#ifdef _EMAC
#include "lpc177x_8x_emac.h"
#include "lpc177x_8x_clkpwr.h"
#include "lpc177x_8x_pinsel.h"
/* Peripheral group ----------------------------------------------------------- */
/** @addtogroup EMAC
* @{
*/
/************************** PRIVATE VARIABLES *************************/
/* MII Mgmt Configuration register - Clock divider setting */
const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28, 36, 40, 44, 48, 52, 56, 60, 64 };
/* EMAC Config data */
static EMAC_CFG_Type EMAC_Configs;
/* EMAC local DMA Descriptors */
#ifdef __IAR_SYSTEMS_ICC__
/* Global Tx Buffer data */
#pragma data_alignment=4
static uint16_t saFrameBuffers[EMAC_MAX_FRAME_NUM][EMAC_MAX_FRAME_SIZE];
#else
/* Global Rx Buffer data */
static uint16_t __attribute__ ((aligned (4))) saFrameBuffers[EMAC_MAX_FRAME_NUM][EMAC_MAX_FRAME_SIZE];
#endif
static uint32_t sulCurrFrameSz = 0;
static uint8_t sbCurrFrameID = 0;
/***************************** PRIVATE FUNCTION *****************************/
static void EMAC_UpdateRxConsumeIndex(void);
static void EMAC_UpdateTxProduceIndex(void);
static uint32_t EMAC_AllocTxBuff(uint16_t nFrameSize, uint8_t bLastFrame);
static uint32_t EMAC_GetRxFrameSize(void);
/*********************************************************************//**
* @brief
* @param[in]
* @return
**********************************************************************/
void rx_descr_init (void)
{
unsigned int i;
for (i = 0; i < EMAC_NUM_RX_FRAG; i++)
{
RX_DESC_PACKET(i) = RX_BUF(i);
RX_DESC_CTRL(i) = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN-1);
RX_STAT_INFO(i) = 0;
RX_STAT_HASHCRC(i) = 0;
}
/* Set EMAC Receive Descriptor Registers. */
LPC_EMAC->RxDescriptor = RX_DESC_BASE;
LPC_EMAC->RxStatus = RX_STAT_BASE;
LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG-1;
/* Rx Descriptors Point to 0 */
LPC_EMAC->RxConsumeIndex = 0;
}
/*********************************************************************//**
* @brief
* @param[in]
* @return
**********************************************************************/
void tx_descr_init (void)
{
unsigned int i;
for (i = 0; i < EMAC_NUM_TX_FRAG; i++)
{
TX_DESC_PACKET(i) = TX_BUF(i);
TX_DESC_CTRL(i) = 0;
TX_STAT_INFO(i) = 0;
}
/* Set EMAC Transmit Descriptor Registers. */
LPC_EMAC->TxDescriptor = TX_DESC_BASE;
LPC_EMAC->TxStatus = TX_STAT_BASE;
LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG-1;
/* Tx Descriptors Point to 0 */
LPC_EMAC->TxProduceIndex = 0;
}
/*********************************************************************//**
* @brief Set Station MAC address for EMAC module
* @param[in] abStationAddr Pointer to Station address that contains 6-bytes
* of MAC address.
* @return None
**********************************************************************/
void setEmacAddr(uint8_t abStationAddr[])
{
/* Set the Ethernet MAC Address registers */
LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4];
LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2];
LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0];
}
/************************** GLOBAL/PUBLIC FUNCTIONS *************************/
/** @defgroup EMAC_Public_Functions
* @{
*/
/*********************************************************************//**
* @brief Write data to PHY
* @param[in] PhyReg PHY register address
* @param[in] Value Register Value
* @return None
**********************************************************************/
void EMAC_Write_PHY (uint8_t PhyReg, uint16_t Value)
{
unsigned int tout;
LPC_EMAC->MADR = ((EMAC_Configs.bPhyAddr & 0x1F) << 8 )| (PhyReg & 0x1F);
LPC_EMAC->MWTD = Value;
/* Wait utill operation completed */
tout = 0;
for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++)
{
if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0)
{
break;
}
}
}
/*********************************************************************//**
* @brief Read data from PHY register
* @param[in] PhyReg PHY register address
* @return Register value
**********************************************************************/
uint16_t EMAC_Read_PHY (uint8_t PhyReg)
{
unsigned int tout;
LPC_EMAC->MADR = ((EMAC_Configs.bPhyAddr & 0x1F) << 8 )| (PhyReg & 0x1F);
LPC_EMAC->MCMD = EMAC_MCMD_READ;
/* Wait until operation completed */
tout = 0;
for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++)
{
if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0)
{
break;
}
}
LPC_EMAC->MCMD = 0;
return (LPC_EMAC->MRDD);
}
/*********************************************************************//**
* @brief Set Full/Half Duplex Mode
* @param[in] full_duplex 0: Half-duplex, 1: Full-duplex
* @return None
**********************************************************************/
void EMAC_SetFullDuplexMode(uint8_t full_duplex)
{
if(full_duplex)
{
LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP;
LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP;
}
else
{
LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
}
}
/*********************************************************************//**
* @brief Set PHY Speed
* @param[in] mode_100Mbps 0: 10Mbps, 1: 100Mbps
* @return None
**********************************************************************/
void EMAC_SetPHYSpeed(uint8_t mode_100Mbps)
{
if(mode_100Mbps)
{
LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
}
else
{
LPC_EMAC->SUPP = 0;
}
}
/*********************************************************************//**
* @brief Initializes the EMAC peripheral according to the specified
* parameters in the EMAC_ConfigStruct.
* @param[in] EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure
* that contains the configuration information for the
* specified EMAC peripheral.
* @return None
*
* Note: This function will initialize EMAC module according to procedure below:
* - Remove the soft reset condition from the MAC
* - Configure the PHY via the MIIM interface of the MAC
* - Select RMII mode
* - Configure the transmit and receive DMA engines, including the descriptor arrays
* - Configure the host registers (MAC1,MAC2 etc.) in the MAC
* - Enable the receive and transmit data paths
* In default state after initializing, Rx Done and Tx Done interrupt are enabled,
* nad all interrupts are also enabled
* (Ref. from LPC17xx UM)
**********************************************************************/
int32_t EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
{
/* Initialize the EMAC Ethernet controller. */
int32_t tout, tmp;
EMAC_Configs = *EMAC_ConfigStruct;
/* Set up power for Ethernet module */
CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);
/* Enable P1 Ethernet Pins. */
/* Reset all EMAC internal modules */
LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;
LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM;
/* A short delay after reset. */
for (tout = 100; tout; tout--);
/* Initialize MAC control registers. */
LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN;
LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
/*
* Find the clock that close to desired target clock
*/
tmp = CLKPWR_GetCLK(CLKPWR_CLKTYPE_CPU)/ EMAC_MCFG_MII_MAXCLK;
for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++)
{
if (EMAC_clkdiv[tout] >= tmp)
break;
}
if(tout >= sizeof (EMAC_clkdiv))
return ERROR;
tout++;
// Set Frame size
LPC_EMAC->MAXF = EMAC_ConfigStruct->nMaxFrameSize;
// Write to MAC configuration register and reset
LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;
// release reset
LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
LPC_EMAC->CLRT = EMAC_CLRT_DEF;
LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;
/* Enable Reduced MII interface. */
LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;
// Initilialize PHY
if(EMAC_ConfigStruct->pfnPHYInit != NULL)
{
if(EMAC_ConfigStruct->pfnPHYInit(&EMAC_ConfigStruct->PhyCfg) != SUCCESS)
{
return ERROR;
}
}
// Set EMAC address
setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr);
/* Initialize Tx and Rx DMA Descriptors */
rx_descr_init ();
tx_descr_init ();
// Set Receive Filter register: enable broadcast and multicast
LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;
/* Enable Rx Done and Tx Done interrupt for EMAC */
EMAC_IntCmd((EMAC_INT_RX_OVERRUN | EMAC_INT_RX_ERR | EMAC_INT_RX_FIN \
| EMAC_INT_RX_DONE | EMAC_INT_TX_UNDERRUN | EMAC_INT_TX_ERR \
| EMAC_INT_TX_FIN | EMAC_INT_TX_DONE), ENABLE);
/* Reset all interrupts */
LPC_EMAC->IntClear = 0xFFFF;
/* Enable receive and transmit mode of MAC Ethernet core */
EMAC_TxEnable();
EMAC_RxEnable();
NVIC_EnableIRQ(ENET_IRQn);
return SUCCESS;
}
/*********************************************************************//**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -