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

📄 lpc17xx_emac.c

📁 uCOSII_lwip_lpc1768
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********************************************************************
* $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 + -