📄 lpc17xx_emac.c.svn-base
字号:
/**********************************************************************
* $Id$ lpc17xx_dac.c 2010-05-21
*//**
* @file lpc17xx_dac.c
* @brief Contains all functions support for Ethernet MAC firmware
* library on LPC17xx
* @version 2.0
* @date 21. May. 2010
* @author NXP MCU SW Application Team
*
* Copyright(C) 2010, 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.
**********************************************************************/
/* Peripheral group ----------------------------------------------------------- */
/** @addtogroup EMAC
* @{
*/
/* Includes ------------------------------------------------------------------- */
#include "lpc17xx_emac.h"
#include "lpc17xx_clkpwr.h"
/* If this source file built with example, the LPC17xx FW library configuration
* file in each example directory ("lpc17xx_libcfg.h") must be included,
* otherwise the default FW library configuration file must be included instead
*/
#ifdef __BUILD_WITH_EXAMPLE__
#include "lpc17xx_libcfg.h"
#else
#include "lpc17xx_libcfg_default.h"
#endif /* __BUILD_WITH_EXAMPLE__ */
#ifdef _EMAC
/* Private Variables ---------------------------------------------------------- */
/** @defgroup EMAC_Private_Variables EMAC Private Variables
* @{
*/
/* MII Mgmt Configuration register - Clock divider setting */
const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 };
/* EMAC local DMA Descriptors */
/** Rx Descriptor data array */
static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG];
/** Rx Status data array - Must be 8-Byte aligned */
#if defined ( __CC_ARM )
static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
#elif defined ( __ICCARM__ )
#pragma data_alignment=8
static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
#elif defined ( __GNUC__ )
static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
#endif
/** Tx Descriptor data array */
static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG];
/** Tx Status data array */
static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG];
/* EMAC local DMA buffers */
/** Rx buffer data */
static uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2];
/** Tx buffer data */
static uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2];
/**
* @}
*/
/* Private Functions ---------------------------------------------------------- */
static void rx_descr_init (void);
static void tx_descr_init (void);
static int32_t write_PHY (uint32_t PhyReg, uint16_t Value);
static int32_t read_PHY (uint32_t PhyReg);
static void setEmacAddr(uint8_t abStationAddr[]);
static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len);
/*--------------------------- rx_descr_init ---------------------------------*/
/*********************************************************************//**
* @brief Initializes RX Descriptor
* @param[in] None
* @return None
***********************************************************************/
static void rx_descr_init (void)
{
/* Initialize Receive Descriptor and Status array. */
uint32_t i;
for (i = 0; i < EMAC_NUM_RX_FRAG; i++) {
Rx_Desc[i].Packet = (uint32_t)&rx_buf[i];
Rx_Desc[i].Ctrl = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1);
Rx_Stat[i].Info = 0;
Rx_Stat[i].HashCRC = 0;
}
/* Set EMAC Receive Descriptor Registers. */
LPC_EMAC->RxDescriptor = (uint32_t)&Rx_Desc[0];
LPC_EMAC->RxStatus = (uint32_t)&Rx_Stat[0];
LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1;
/* Rx Descriptors Point to 0 */
LPC_EMAC->RxConsumeIndex = 0;
}
/*--------------------------- tx_descr_init ---- ----------------------------*/
/*********************************************************************//**
* @brief Initializes TX Descriptor
* @param[in] None
* @return None
***********************************************************************/
static void tx_descr_init (void) {
/* Initialize Transmit Descriptor and Status array. */
uint32_t i;
for (i = 0; i < EMAC_NUM_TX_FRAG; i++) {
Tx_Desc[i].Packet = (uint32_t)&tx_buf[i];
Tx_Desc[i].Ctrl = 0;
Tx_Stat[i].Info = 0;
}
/* Set EMAC Transmit Descriptor Registers. */
LPC_EMAC->TxDescriptor = (uint32_t)&Tx_Desc[0];
LPC_EMAC->TxStatus = (uint32_t)&Tx_Stat[0];
LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1;
/* Tx Descriptors Point to 0 */
LPC_EMAC->TxProduceIndex = 0;
}
/*--------------------------- write_PHY -------------------------------------*/
/*********************************************************************//**
* @brief Write value to PHY device
* @param[in] PhyReg: PHY Register address
* @param[in] Value: Value to write
* @return 0 - if success
* 1 - if fail
***********************************************************************/
static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
{
/* Write a data 'Value' to PHY register 'PhyReg'. */
uint32_t tout;
LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
LPC_EMAC->MWTD = Value;
/* Wait until operation completed */
tout = 0;
for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) {
if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
return (0);
}
}
// Time out!
return (-1);
}
/*--------------------------- read_PHY --------------------------------------*/
/*********************************************************************//**
* @brief Read value from PHY device
* @param[in] PhyReg: PHY Register address
* @return 0 - if success
* 1 - if fail
***********************************************************************/
static int32_t read_PHY (uint32_t PhyReg)
{
/* Read a PHY register 'PhyReg'. */
uint32_t tout;
LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
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) {
LPC_EMAC->MCMD = 0;
return (LPC_EMAC->MRDD);
}
}
// Time out!
return (-1);
}
/*********************************************************************//**
* @brief Set Station MAC address for EMAC module
* @param[in] abStationAddr Pointer to Station address that contains 6-bytes
* of MAC address (should be in order from MAC Address 1 to MAC Address 6)
* @return None
**********************************************************************/
static 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];
}
/*********************************************************************//**
* @brief Calculates CRC code for number of bytes in the frame
* @param[in] frame_no_fcs Pointer to the first byte of the frame
* @param[in] frame_len length of the frame without the FCS
* @return the CRC as a 32 bit integer
**********************************************************************/
static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len)
{
int i; // iterator
int j; // another iterator
char byte; // current byte
int crc; // CRC result
int q0, q1, q2, q3; // temporary variables
crc = 0xFFFFFFFF;
for (i = 0; i < frame_len; i++) {
byte = *frame_no_fcs++;
for (j = 0; j < 2; j++) {
if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) {
q3 = 0x04C11DB7;
} else {
q3 = 0x00000000;
}
if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) {
q2 = 0x09823B6E;
} else {
q2 = 0x00000000;
}
if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) {
q1 = 0x130476DC;
} else {
q1 = 0x00000000;
}
if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) {
q0 = 0x2608EDB8;
} else {
q0 = 0x00000000;
}
crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
byte >>= 4;
}
}
return crc;
}
/* End of Private Functions --------------------------------------------------- */
/* Public Functions ----------------------------------------------------------- */
/** @addtogroup EMAC_Public_Functions
* @{
*/
/*********************************************************************//**
* @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, only Rx Done and Tx Done interrupt are enabled,
* all remain interrupts are disabled
* (Ref. from LPC17xx UM)
**********************************************************************/
Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
{
/* Initialize the EMAC Ethernet controller. */
int32_t regv,tout, tmp;
/* Set up clock and power for Ethernet module */
CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);
/* 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 = SystemCoreClock / EMAC_MCFG_MII_MAXCLK;
for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){
if (EMAC_clkdiv[tout] >= tmp) break;
}
tout++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -