lpc-field

Template project for programming NXP's LPC1768 MCUs
git clone git://git.mdnr.space/lpc-field
Log | Files | Refs | README | LICENSE

lpc17xx_emac.c (31839B)


      1 /**********************************************************************
      2 * $Id$		lpc17xx_emac.c				2010-05-21
      3 *//**
      4 * @file		lpc17xx_emac.c
      5 * @brief	Contains all functions support for Ethernet MAC firmware
      6 * 			library on LPC17xx
      7 * @version	2.0
      8 * @date		21. May. 2010
      9 * @author	NXP MCU SW Application Team
     10 *
     11 * Copyright(C) 2010, NXP Semiconductor
     12 * All rights reserved.
     13 *
     14 ***********************************************************************
     15 * Software that is described herein is for illustrative purposes only
     16 * which provides customers with programming information regarding the
     17 * products. This software is supplied "AS IS" without any warranties.
     18 * NXP Semiconductors assumes no responsibility or liability for the
     19 * use of the software, conveys no license or title under any patent,
     20 * copyright, or mask work right to the product. NXP Semiconductors
     21 * reserves the right to make changes in the software without
     22 * notification. NXP Semiconductors also make no representation or
     23 * warranty that such application will be suitable for the specified
     24 * use without further testing or modification.
     25 * Permission to use, copy, modify, and distribute this software and its
     26 * documentation is hereby granted, under NXP Semiconductors'
     27 * relevant copyright in the software, without fee, provided that it
     28 * is used in conjunction with NXP Semiconductors microcontrollers.  This
     29 * copyright, permission, and disclaimer notice must appear in all copies of
     30 * this code.
     31 **********************************************************************/
     32 
     33 /* Peripheral group ----------------------------------------------------------- */
     34 /** @addtogroup EMAC
     35  * @{
     36  */
     37 
     38 /* Includes ------------------------------------------------------------------- */
     39 #include "lpc17xx_emac.h"
     40 #include "lpc17xx_clkpwr.h"
     41 
     42 /* If this source file built with example, the LPC17xx FW library configuration
     43  * file in each example directory ("lpc17xx_libcfg.h") must be included,
     44  * otherwise the default FW library configuration file must be included instead
     45  */
     46 #ifdef __BUILD_WITH_EXAMPLE__
     47 #include "lpc17xx_libcfg.h"
     48 #else
     49 #include "lpc17xx_libcfg_default.h"
     50 #endif /* __BUILD_WITH_EXAMPLE__ */
     51 
     52 
     53 #ifdef _EMAC
     54 
     55 /* Private Variables ---------------------------------------------------------- */
     56 /** @defgroup EMAC_Private_Variables EMAC Private Variables
     57  * @{
     58  */
     59 
     60 /* MII Mgmt Configuration register - Clock divider setting */
     61 const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28, 36, 40, 44, 48, 52, 56, 60, 64};
     62 
     63 /* EMAC local DMA Descriptors */
     64 
     65 /** Rx Descriptor data array */
     66 static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG];
     67 
     68 /** Rx Status data array - Must be 8-Byte aligned */
     69 #if defined ( __CC_ARM   )
     70 static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
     71 #elif defined ( __ICCARM__ )
     72 #pragma data_alignment=8
     73 static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
     74 #elif defined   (  __GNUC__  )
     75 static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG];
     76 #endif
     77 
     78 /** Tx Descriptor data array */
     79 static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG];
     80 /** Tx Status data array */
     81 static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG];
     82 
     83 /* EMAC local DMA buffers */
     84 /** Rx buffer data */
     85 static uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2];
     86 /** Tx buffer data */
     87 static uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2];
     88 
     89 /**
     90  * @}
     91  */
     92 
     93 /* Private Functions ---------------------------------------------------------- */
     94 static void rx_descr_init (void);
     95 static void tx_descr_init (void);
     96 static int32_t write_PHY (uint32_t PhyReg, uint16_t Value);
     97 static int32_t  read_PHY (uint32_t PhyReg);
     98 
     99 static void setEmacAddr(uint8_t abStationAddr[]);
    100 static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len);
    101 
    102 
    103 /*--------------------------- rx_descr_init ---------------------------------*/
    104 /*********************************************************************//**
    105  * @brief 		Initializes RX Descriptor
    106  * @param[in] 	None
    107  * @return 		None
    108  ***********************************************************************/
    109 static void rx_descr_init (void)
    110 {
    111 	/* Initialize Receive Descriptor and Status array. */
    112 	uint32_t i;
    113 
    114 	for (i = 0; i < EMAC_NUM_RX_FRAG; i++) {
    115 		Rx_Desc[i].Packet  = (uint32_t)&rx_buf[i];
    116 		Rx_Desc[i].Ctrl    = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1);
    117 		Rx_Stat[i].Info    = 0;
    118 		Rx_Stat[i].HashCRC = 0;
    119 	}
    120 
    121 	/* Set EMAC Receive Descriptor Registers. */
    122 	LPC_EMAC->RxDescriptor       = (uint32_t)&Rx_Desc[0];
    123 	LPC_EMAC->RxStatus           = (uint32_t)&Rx_Stat[0];
    124 	LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1;
    125 
    126 	/* Rx Descriptors Point to 0 */
    127 	LPC_EMAC->RxConsumeIndex  = 0;
    128 }
    129 
    130 
    131 /*--------------------------- tx_descr_init ---- ----------------------------*/
    132 /*********************************************************************//**
    133  * @brief 		Initializes TX Descriptor
    134  * @param[in] 	None
    135  * @return 		None
    136  ***********************************************************************/
    137 static void tx_descr_init (void) {
    138 	/* Initialize Transmit Descriptor and Status array. */
    139 	uint32_t i;
    140 
    141 	for (i = 0; i < EMAC_NUM_TX_FRAG; i++) {
    142 		Tx_Desc[i].Packet = (uint32_t)&tx_buf[i];
    143 		Tx_Desc[i].Ctrl   = 0;
    144 		Tx_Stat[i].Info   = 0;
    145 	}
    146 
    147 	/* Set EMAC Transmit Descriptor Registers. */
    148 	LPC_EMAC->TxDescriptor       = (uint32_t)&Tx_Desc[0];
    149 	LPC_EMAC->TxStatus           = (uint32_t)&Tx_Stat[0];
    150 	LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1;
    151 
    152 	/* Tx Descriptors Point to 0 */
    153 	LPC_EMAC->TxProduceIndex  = 0;
    154 }
    155 
    156 
    157 /*--------------------------- write_PHY -------------------------------------*/
    158 /*********************************************************************//**
    159  * @brief 		Write value to PHY device
    160  * @param[in] 	PhyReg: PHY Register address
    161  * @param[in] 	Value:  Value to write
    162  * @return 		0 - if success
    163  * 				1 - if fail
    164  ***********************************************************************/
    165 static int32_t write_PHY (uint32_t PhyReg, uint16_t Value)
    166 {
    167 	/* Write a data 'Value' to PHY register 'PhyReg'. */
    168 	uint32_t tout;
    169 
    170 	LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
    171 	LPC_EMAC->MWTD = Value;
    172 
    173 	/* Wait until operation completed */
    174 	tout = 0;
    175 	for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) {
    176 		if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
    177 			return (0);
    178 		}
    179 	}
    180 	// Time out!
    181 	return (-1);
    182 }
    183 
    184 
    185 /*--------------------------- read_PHY --------------------------------------*/
    186 /*********************************************************************//**
    187  * @brief 		Read value from PHY device
    188  * @param[in] 	PhyReg: PHY Register address
    189  * @return 		0 - if success
    190  * 				1 - if fail
    191  ***********************************************************************/
    192 static int32_t read_PHY (uint32_t PhyReg)
    193 {
    194 	/* Read a PHY register 'PhyReg'. */
    195 	uint32_t tout;
    196 
    197 	LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg;
    198 	LPC_EMAC->MCMD = EMAC_MCMD_READ;
    199 
    200 	/* Wait until operation completed */
    201 	tout = 0;
    202 	for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) {
    203 		if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) {
    204 			LPC_EMAC->MCMD = 0;
    205 			return (LPC_EMAC->MRDD);
    206 		}
    207 	}
    208 	// Time out!
    209 	return (-1);
    210 }
    211 
    212 /*********************************************************************//**
    213  * @brief		Set Station MAC address for EMAC module
    214  * @param[in]	abStationAddr Pointer to Station address that contains 6-bytes
    215  * 				of MAC address (should be in order from MAC Address 1 to MAC Address 6)
    216  * @return		None
    217  **********************************************************************/
    218 static void setEmacAddr(uint8_t abStationAddr[])
    219 {
    220 	/* Set the Ethernet MAC Address registers */
    221 	LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4];
    222 	LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2];
    223 	LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0];
    224 }
    225 
    226 
    227 /*********************************************************************//**
    228  * @brief		Calculates CRC code for number of bytes in the frame
    229  * @param[in]	frame_no_fcs	Pointer to the first byte of the frame
    230  * @param[in]	frame_len		length of the frame without the FCS
    231  * @return		the CRC as a 32 bit integer
    232  **********************************************************************/
    233 static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len)
    234 {
    235 	int i; 		// iterator
    236 	int j; 		// another iterator
    237 	char byte; 	// current byte
    238 	int crc; 	// CRC result
    239 	int q0, q1, q2, q3; // temporary variables
    240 	crc = 0xFFFFFFFF;
    241 	for (i = 0; i < frame_len; i++) {
    242 		byte = *frame_no_fcs++;
    243 		for (j = 0; j < 2; j++) {
    244 			if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) {
    245 				q3 = 0x04C11DB7;
    246 			} else {
    247 				q3 = 0x00000000;
    248 			}
    249 			if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) {
    250 				q2 = 0x09823B6E;
    251 			} else {
    252 				q2 = 0x00000000;
    253 			}
    254 			if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) {
    255 				q1 = 0x130476DC;
    256 			} else {
    257 				q1 = 0x00000000;
    258 			}
    259 			if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) {
    260 				q0 = 0x2608EDB8;
    261 			} else {
    262 				q0 = 0x00000000;
    263 			}
    264 			crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0;
    265 			byte >>= 4;
    266 		}
    267 	}
    268 	return crc;
    269 }
    270 /* End of Private Functions --------------------------------------------------- */
    271 
    272 
    273 /* Public Functions ----------------------------------------------------------- */
    274 /** @addtogroup EMAC_Public_Functions
    275  * @{
    276  */
    277 
    278 
    279 /*********************************************************************//**
    280  * @brief		Initializes the EMAC peripheral according to the specified
    281 *               parameters in the EMAC_ConfigStruct.
    282  * @param[in]	EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure
    283 *                    that contains the configuration information for the
    284 *                    specified EMAC peripheral.
    285  * @return		None
    286  *
    287  * Note: This function will initialize EMAC module according to procedure below:
    288  *  - Remove the soft reset condition from the MAC
    289  *  - Configure the PHY via the MIIM interface of the MAC
    290  *  - Select RMII mode
    291  *  - Configure the transmit and receive DMA engines, including the descriptor arrays
    292  *  - Configure the host registers (MAC1,MAC2 etc.) in the MAC
    293  *  - Enable the receive and transmit data paths
    294  *  In default state after initializing, only Rx Done and Tx Done interrupt are enabled,
    295  *  all remain interrupts are disabled
    296  *  (Ref. from LPC17xx UM)
    297  **********************************************************************/
    298 Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct)
    299 {
    300 	/* Initialize the EMAC Ethernet controller. */
    301 	int32_t regv,tout, tmp;
    302 
    303 	/* Set up clock and power for Ethernet module */
    304 	CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE);
    305 
    306 	/* Reset all EMAC internal modules */
    307 	LPC_EMAC->MAC1    = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX |
    308 					EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES;
    309 
    310 	LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM;
    311 
    312 	/* A short delay after reset. */
    313 	for (tout = 100; tout; tout--);
    314 
    315 	/* Initialize MAC control registers. */
    316 	LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL;
    317 	LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN;
    318 	LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN;
    319 	/*
    320 	 * Find the clock that close to desired target clock
    321 	 */
    322 	tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK;
    323 	for (tout = 0; tout < (int32_t)sizeof (EMAC_clkdiv); tout++){
    324 		if (EMAC_clkdiv[tout] >= tmp) break;
    325 	}
    326 	tout++;
    327 	// Write to MAC configuration register and reset
    328 	LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII;
    329 	// release reset
    330 	LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII);
    331 	LPC_EMAC->CLRT = EMAC_CLRT_DEF;
    332 	LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF;
    333 
    334 	/* Enable Reduced MII interface. */
    335 	LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM;
    336 
    337 	/* Reset Reduced MII Logic. */
    338 //	LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII;
    339 
    340 	for (tout = 100; tout; tout--);
    341 	LPC_EMAC->SUPP = 0;
    342 
    343 	/* Put the DP83848C in reset mode */
    344 	write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET);
    345 
    346 	/* Wait for hardware reset to end. */
    347 	for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
    348 		regv = read_PHY (EMAC_PHY_REG_BMCR);
    349 		if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) {
    350 			/* Reset complete, device not Power Down. */
    351 			break;
    352 		}
    353 		if (tout == 0){
    354 			// Time out, return ERROR
    355 			return (ERROR);
    356 		}
    357 	}
    358 
    359 	// Set PHY mode
    360 	if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){
    361 		return (ERROR);
    362 	}
    363 
    364 	// Set EMAC address
    365 	setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr);
    366 
    367 	/* Initialize Tx and Rx DMA Descriptors */
    368 	rx_descr_init ();
    369 	tx_descr_init ();
    370 
    371 	// Set Receive Filter register: enable broadcast and multicast
    372 	LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN;
    373 
    374 	/* Enable Rx Done and Tx Done interrupt for EMAC */
    375 	LPC_EMAC->IntEnable = EMAC_INT_RX_DONE | EMAC_INT_TX_DONE;
    376 
    377 	/* Reset all interrupts */
    378 	LPC_EMAC->IntClear  = 0xFFFF;
    379 
    380 	/* Enable receive and transmit mode of MAC Ethernet core */
    381 	LPC_EMAC->Command  |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN);
    382 	LPC_EMAC->MAC1     |= EMAC_MAC1_REC_EN;
    383 
    384 	return SUCCESS;
    385 }
    386 
    387 
    388 /*********************************************************************//**
    389  * @brief		De-initializes the EMAC peripheral registers to their
    390 *                  default reset values.
    391  * @param[in]	None
    392  * @return 		None
    393  **********************************************************************/
    394 void EMAC_DeInit(void)
    395 {
    396 	// Disable all interrupt
    397 	LPC_EMAC->IntEnable = 0x00;
    398 	// Clear all pending interrupt
    399 	LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP);
    400 
    401 	/* TurnOff clock and power for Ethernet module */
    402 	CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE);
    403 }
    404 
    405 
    406 /*********************************************************************//**
    407  * @brief		Check specified PHY status in EMAC peripheral
    408  * @param[in]	ulPHYState	Specified PHY Status Type, should be:
    409  * 							- EMAC_PHY_STAT_LINK: Link Status
    410  * 							- EMAC_PHY_STAT_SPEED: Speed Status
    411  * 							- EMAC_PHY_STAT_DUP: Duplex Status
    412  * @return		Status of specified PHY status (0 or 1).
    413  * 				(-1) if error.
    414  *
    415  * Note:
    416  * For EMAC_PHY_STAT_LINK, return value:
    417  * - 0: Link Down
    418  * - 1: Link Up
    419  * For EMAC_PHY_STAT_SPEED, return value:
    420  * - 0: 10Mbps
    421  * - 1: 100Mbps
    422  * For EMAC_PHY_STAT_DUP, return value:
    423  * - 0: Half-Duplex
    424  * - 1: Full-Duplex
    425  **********************************************************************/
    426 int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState)
    427 {
    428 	int32_t regv, tmp;
    429 #ifdef MCB_LPC_1768
    430 	regv = read_PHY (EMAC_PHY_REG_STS);
    431 	switch(ulPHYState){
    432 	case EMAC_PHY_STAT_LINK:
    433 		tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0;
    434 		break;
    435 	case EMAC_PHY_STAT_SPEED:
    436 		tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1;
    437 		break;
    438 	case EMAC_PHY_STAT_DUP:
    439 		tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
    440 		break;
    441 #elif defined(IAR_LPC_1768)
    442 	/* Use IAR_LPC_1768 board:
    443 	 * FSZ8721BL doesn't have Status Register
    444 	 * so we read Basic Mode Status Register (0x01h) instead
    445 	 */
    446 	regv = read_PHY (EMAC_PHY_REG_BMSR);
    447 	switch(ulPHYState){
    448 	case EMAC_PHY_STAT_LINK:
    449 		tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0;
    450 		break;
    451 	case EMAC_PHY_STAT_SPEED:
    452 		tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0;
    453 		break;
    454 	case EMAC_PHY_STAT_DUP:
    455 		tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0;
    456 		break;
    457 #endif
    458 	default:
    459 		tmp = -1;
    460 		break;
    461 	}
    462 	return (tmp);
    463 }
    464 
    465 
    466 /*********************************************************************//**
    467  * @brief		Set specified PHY mode in EMAC peripheral
    468  * @param[in]	ulPHYMode	Specified PHY mode, should be:
    469  * 							- EMAC_MODE_AUTO
    470  * 							- EMAC_MODE_10M_FULL
    471  * 							- EMAC_MODE_10M_HALF
    472  * 							- EMAC_MODE_100M_FULL
    473  * 							- EMAC_MODE_100M_HALF
    474  * @return		Return (0) if no error, otherwise return (-1)
    475  **********************************************************************/
    476 int32_t EMAC_SetPHYMode(uint32_t ulPHYMode)
    477 {
    478 	int32_t id1, id2, tout;
    479 
    480 	/* Check if this is a DP83848C PHY. */
    481 	id1 = read_PHY (EMAC_PHY_REG_IDR1);
    482 	id2 = read_PHY (EMAC_PHY_REG_IDR2);
    483 
    484 #ifdef MCB_LPC_1768
    485 	if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) {
    486 		switch(ulPHYMode){
    487 		case EMAC_MODE_AUTO:
    488 			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
    489 #elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */
    490 	if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) {
    491 		/* Configure the PHY device */
    492 		switch(ulPHYMode){
    493 		case EMAC_MODE_AUTO:
    494 			/* Use auto-negotiation about the link speed. */
    495 			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG);
    496 //			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN);
    497 #endif
    498 			/* Wait to complete Auto_Negotiation */
    499 			for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
    500 				
    501 			}
    502 			break;
    503 		case EMAC_MODE_10M_FULL:
    504 			/* Connect at 10MBit full-duplex */
    505 			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M);
    506 			break;
    507 		case EMAC_MODE_10M_HALF:
    508 			/* Connect at 10MBit half-duplex */
    509 			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M);
    510 			break;
    511 		case EMAC_MODE_100M_FULL:
    512 			/* Connect at 100MBit full-duplex */
    513 			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M);
    514 			break;
    515 		case EMAC_MODE_100M_HALF:
    516 			/* Connect at 100MBit half-duplex */
    517 			write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M);
    518 			break;
    519 		default:
    520 			// un-supported
    521 			return (-1);
    522 		}
    523 	}
    524 	// It's not correct module ID
    525 	else {
    526 		return (-1);
    527 	}
    528 
    529 	// Update EMAC configuration with current PHY status
    530 	if (EMAC_UpdatePHYStatus() < 0){
    531 		return (-1);
    532 	}
    533 
    534 	// Complete
    535 	return (0);
    536 }
    537 
    538 
    539 /*********************************************************************//**
    540  * @brief		Auto-Configures value for the EMAC configuration register to
    541  * 				match with current PHY mode
    542  * @param[in]	None
    543  * @return		Return (0) if no error, otherwise return (-1)
    544  *
    545  * Note: The EMAC configuration will be auto-configured:
    546  * 		- Speed mode.
    547  * 		- Half/Full duplex mode
    548  **********************************************************************/
    549 int32_t EMAC_UpdatePHYStatus(void)
    550 {
    551 	int32_t regv, tout;
    552 
    553 	/* Check the link status. */
    554 #ifdef MCB_LPC_1768
    555 	for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
    556 		regv = read_PHY (EMAC_PHY_REG_STS);
    557 		if (regv & EMAC_PHY_SR_LINK) {
    558 			/* Link is on. */
    559 			break;
    560 		}
    561 		if (tout == 0){
    562 			// time out
    563 			return (-1);
    564 		}
    565 	}
    566 	/* Configure Full/Half Duplex mode. */
    567 	if (regv & EMAC_PHY_SR_DUP) {
    568 	/* Full duplex is enabled. */
    569 			LPC_EMAC->MAC2    |= EMAC_MAC2_FULL_DUP;
    570 			LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
    571 			LPC_EMAC->IPGT     = EMAC_IPGT_FULL_DUP;
    572 	} else {
    573 		/* Half duplex mode. */
    574 		LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
    575 	}
    576 	if (regv & EMAC_PHY_SR_SPEED) {
    577 	/* 10MBit mode. */
    578 		LPC_EMAC->SUPP = 0;
    579 	} else {
    580 		/* 100MBit mode. */
    581 		LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
    582 	}
    583 #elif defined(IAR_LPC_1768)
    584 	for (tout = EMAC_PHY_RESP_TOUT; tout>=0; tout--) {
    585 		regv = read_PHY (EMAC_PHY_REG_BMSR);
    586 		if (regv & EMAC_PHY_BMSR_LINK_STATUS) {
    587 			/* Link is on. */
    588 			break;
    589 		}
    590 		if (tout == 0){
    591 			// time out
    592 			return (-1);
    593 		}
    594 	}
    595 
    596 	/* Configure Full/Half Duplex mode. */
    597 	if (regv & EMAC_PHY_SR_FULL_DUP) {
    598 		/* Full duplex is enabled. */
    599 		LPC_EMAC->MAC2    |= EMAC_MAC2_FULL_DUP;
    600 		LPC_EMAC->Command |= EMAC_CR_FULL_DUP;
    601 		LPC_EMAC->IPGT     = EMAC_IPGT_FULL_DUP;
    602 	} else {
    603 		/* Half duplex mode. */
    604 		LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP;
    605 	}
    606 
    607 	/* Configure 100MBit/10MBit mode. */
    608 	if (!(regv & EMAC_PHY_SR_100_SPEED)) {
    609 		/* 10MBit mode. */
    610 		LPC_EMAC->SUPP = 0;
    611 	} else {
    612 		/* 100MBit mode. */
    613 		LPC_EMAC->SUPP = EMAC_SUPP_SPEED;
    614 	}
    615 #endif
    616 	// Complete
    617 	return (0);
    618 }
    619 
    620 
    621 /*********************************************************************//**
    622  * @brief		Enable/Disable hash filter functionality for specified destination
    623  * 				MAC address in EMAC module
    624  * @param[in]	dstMAC_addr		Pointer to the first MAC destination address, should
    625  * 								be 6-bytes length, in order LSB to the MSB
    626  * @param[in]	NewState		New State of this command, should be:
    627  *									- ENABLE.
    628  *									- DISABLE.
    629  * @return		None
    630  *
    631  * Note:
    632  * The standard Ethernet cyclic redundancy check (CRC) function is calculated from
    633  * the 6 byte destination address in the Ethernet frame (this CRC is calculated
    634  * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of
    635  * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access
    636  * the hash table: it is used as an index in the 64 bit HashFilter register that has been
    637  * programmed with accept values. If the selected accept value is 1, the frame is
    638  * accepted.
    639  **********************************************************************/
    640 void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState)
    641 {
    642 	uint32_t *pReg;
    643 	uint32_t tmp;
    644 	int32_t crc;
    645 
    646 	// Calculate the CRC from the destination MAC address
    647 	crc = emac_CRCCalc(dstMAC_addr, 6);
    648 	// Extract the value from CRC to get index value for hash filter table
    649 	crc = (crc >> 23) & 0x3F;
    650 
    651 	pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \
    652 								: ((uint32_t *)&LPC_EMAC->HashFilterL);
    653 	tmp = (crc > 31) ? (crc - 32) : crc;
    654 	if (NewState == ENABLE) {
    655 		(*pReg) |= (1UL << tmp);
    656 	} else {
    657 		(*pReg) &= ~(1UL << tmp);
    658 	}
    659 	// Enable Rx Filter
    660 	LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT;
    661 }
    662 
    663 /*********************************************************************//**
    664  * @brief		Enable/Disable Filter mode for each specified type EMAC peripheral
    665  * @param[in]	ulFilterMode	Filter mode, should be:
    666  * 								- EMAC_RFC_UCAST_EN: all frames of unicast types
    667  * 								will be accepted
    668  * 								- EMAC_RFC_BCAST_EN: broadcast frame will be
    669  * 								accepted
    670  * 								- EMAC_RFC_MCAST_EN: all frames of multicast
    671  * 								types will be accepted
    672  * 								- EMAC_RFC_UCAST_HASH_EN: The imperfect hash
    673  * 								filter will be applied to unicast addresses
    674  * 								- EMAC_RFC_MCAST_HASH_EN: The imperfect hash
    675  * 								filter will be applied to multicast addresses
    676  * 								- EMAC_RFC_PERFECT_EN: the destination address
    677  * 								will be compared with the 6 byte station address
    678  * 								programmed in the station address by the filter
    679  * 								- EMAC_RFC_MAGP_WOL_EN: the result of the magic
    680  * 								packet filter will generate a WoL interrupt when
    681  * 								there is a match
    682  * 								- EMAC_RFC_PFILT_WOL_EN: the result of the perfect address
    683  * 								matching filter and the imperfect hash filter will
    684  * 								generate a WoL interrupt when there is a match
    685  * @param[in]	NewState	New State of this command, should be:
    686  * 								- ENABLE
    687  * 								- DISABLE
    688  * @return		None
    689  **********************************************************************/
    690 void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState)
    691 {
    692 	if (NewState == ENABLE){
    693 		LPC_EMAC->RxFilterCtrl |= ulFilterMode;
    694 	} else {
    695 		LPC_EMAC->RxFilterCtrl &= ~ulFilterMode;
    696 	}
    697 }
    698 
    699 /*********************************************************************//**
    700  * @brief		Get status of Wake On LAN Filter for each specified
    701  * 				type in EMAC peripheral, clear this status if it is set
    702  * @param[in]	ulWoLMode	WoL Filter mode, should be:
    703  * 								- EMAC_WOL_UCAST: unicast frames caused WoL
    704  * 								- EMAC_WOL_UCAST: broadcast frame caused WoL
    705  * 								- EMAC_WOL_MCAST: multicast frame caused WoL
    706  * 								- EMAC_WOL_UCAST_HASH: unicast frame that passes the
    707  * 								imperfect hash filter caused WoL
    708  * 								- EMAC_WOL_MCAST_HASH: multicast frame that passes the
    709  * 								imperfect hash filter caused WoL
    710  * 								- EMAC_WOL_PERFECT:perfect address matching filter
    711  * 								caused WoL
    712  * 								- EMAC_WOL_RX_FILTER: the receive filter caused WoL
    713  * 								- EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL
    714  * @return		SET/RESET
    715  **********************************************************************/
    716 FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode)
    717 {
    718 	if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) {
    719 		LPC_EMAC->RxFilterWoLClear = ulWoLMode;
    720 		return SET;
    721 	} else {
    722 		return RESET;
    723 	}
    724 }
    725 
    726 
    727 /*********************************************************************//**
    728  * @brief		Write data to Tx packet data buffer at current index due to
    729  * 				TxProduceIndex
    730  * @param[in]	pDataStruct		Pointer to a EMAC_PACKETBUF_Type structure
    731  * 							data that contain specified information about
    732  * 							Packet data buffer.
    733  * @return		None
    734  **********************************************************************/
    735 void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
    736 {
    737 	uint32_t idx,len;
    738 	uint32_t *sp,*dp;
    739 
    740 	idx = LPC_EMAC->TxProduceIndex;
    741 	sp  = (uint32_t *)pDataStruct->pbDataBuf;
    742 	dp  = (uint32_t *)Tx_Desc[idx].Packet;
    743 	/* Copy frame data to EMAC packet buffers. */
    744 	for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
    745 		*dp++ = *sp++;
    746 	}
    747 	Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST);
    748 }
    749 
    750 /*********************************************************************//**
    751  * @brief		Read data from Rx packet data buffer at current index due
    752  * 				to RxConsumeIndex
    753  * @param[in]	pDataStruct		Pointer to a EMAC_PACKETBUF_Type structure
    754  * 							data that contain specified information about
    755  * 							Packet data buffer.
    756  * @return		None
    757  **********************************************************************/
    758 void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct)
    759 {
    760 	uint32_t idx, len;
    761 	uint32_t *dp, *sp;
    762 
    763 	idx = LPC_EMAC->RxConsumeIndex;
    764 	dp = (uint32_t *)pDataStruct->pbDataBuf;
    765 	sp = (uint32_t *)Rx_Desc[idx].Packet;
    766 
    767 	if (pDataStruct->pbDataBuf != NULL) {
    768 		for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) {
    769 			*dp++ = *sp++;
    770 		}
    771 	}
    772 }
    773 
    774 /*********************************************************************//**
    775  * @brief 		Enable/Disable interrupt for each type in EMAC
    776  * @param[in]	ulIntType	Interrupt Type, should be:
    777  * 							- EMAC_INT_RX_OVERRUN: Receive Overrun
    778  * 							- EMAC_INT_RX_ERR: Receive Error
    779  * 							- EMAC_INT_RX_FIN: Receive Descriptor Finish
    780  * 							- EMAC_INT_RX_DONE: Receive Done
    781  * 							- EMAC_INT_TX_UNDERRUN: Transmit Under-run
    782  * 							- EMAC_INT_TX_ERR: Transmit Error
    783  * 							- EMAC_INT_TX_FIN: Transmit descriptor finish
    784  * 							- EMAC_INT_TX_DONE: Transmit Done
    785  * 							- EMAC_INT_SOFT_INT: Software interrupt
    786  * 							- EMAC_INT_WAKEUP: Wakeup interrupt
    787  * @param[in]	NewState	New State of this function, should be:
    788  * 							- ENABLE.
    789  * 							- DISABLE.
    790  * @return		None
    791  **********************************************************************/
    792 void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState)
    793 {
    794 	if (NewState == ENABLE) {
    795 		LPC_EMAC->IntEnable |= ulIntType;
    796 	} else {
    797 		LPC_EMAC->IntEnable &= ~(ulIntType);
    798 	}
    799 }
    800 
    801 /*********************************************************************//**
    802  * @brief 		Check whether if specified interrupt flag is set or not
    803  * 				for each interrupt type in EMAC and clear interrupt pending
    804  * 				if it is set.
    805  * @param[in]	ulIntType	Interrupt Type, should be:
    806  * 							- EMAC_INT_RX_OVERRUN: Receive Overrun
    807  * 							- EMAC_INT_RX_ERR: Receive Error
    808  * 							- EMAC_INT_RX_FIN: Receive Descriptor Finish
    809  * 							- EMAC_INT_RX_DONE: Receive Done
    810  * 							- EMAC_INT_TX_UNDERRUN: Transmit Under-run
    811  * 							- EMAC_INT_TX_ERR: Transmit Error
    812  * 							- EMAC_INT_TX_FIN: Transmit descriptor finish
    813  * 							- EMAC_INT_TX_DONE: Transmit Done
    814  * 							- EMAC_INT_SOFT_INT: Software interrupt
    815  * 							- EMAC_INT_WAKEUP: Wakeup interrupt
    816  * @return		New state of specified interrupt (SET or RESET)
    817  **********************************************************************/
    818 IntStatus EMAC_IntGetStatus(uint32_t ulIntType)
    819 {
    820 	if (LPC_EMAC->IntStatus & ulIntType) {
    821 		LPC_EMAC->IntClear = ulIntType;
    822 		return SET;
    823 	} else {
    824 		return RESET;
    825 	}
    826 }
    827 
    828 
    829 /*********************************************************************//**
    830  * @brief		Check whether if the current RxConsumeIndex is not equal to the
    831  * 				current RxProduceIndex.
    832  * @param[in]	None
    833  * @return		TRUE if they're not equal, otherwise return FALSE
    834  *
    835  * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex,
    836  * it means there're available data has been received. They should be read
    837  * out and released the Receive Data Buffer by updating the RxConsumeIndex value.
    838  **********************************************************************/
    839 Bool EMAC_CheckReceiveIndex(void)
    840 {
    841 	if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) {
    842 		return TRUE;
    843 	} else {
    844 		return FALSE;
    845 	}
    846 }
    847 
    848 
    849 /*********************************************************************//**
    850  * @brief		Check whether if the current TxProduceIndex is not equal to the
    851  * 				current RxProduceIndex - 1.
    852  * @param[in]	None
    853  * @return		TRUE if they're not equal, otherwise return FALSE
    854  *
    855  * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1,
    856  * it means the transmit buffer is available and data can be written to transmit
    857  * buffer to be sent.
    858  **********************************************************************/
    859 Bool EMAC_CheckTransmitIndex(void)
    860 {
    861     uint32_t tmp = LPC_EMAC->TxConsumeIndex;
    862     if (LPC_EMAC->TxProduceIndex == ( tmp - 1 ))
    863     {
    864         return FALSE;
    865     }
    866     else if( ( tmp == 0 ) && ( LPC_EMAC->TxProduceIndex == ( EMAC_NUM_TX_FRAG - 1 ) ) )
    867     {
    868         return FALSE;
    869     }
    870     else
    871     {
    872         return TRUE;
    873     }
    874 }
    875 
    876 
    877 
    878 /*********************************************************************//**
    879  * @brief		Get current status value of receive data (due to RxConsumeIndex)
    880  * @param[in]	ulRxStatType	Received Status type, should be one of following:
    881  * 							- EMAC_RINFO_CTRL_FRAME: Control Frame
    882  * 							- EMAC_RINFO_VLAN: VLAN Frame
    883  * 							- EMAC_RINFO_FAIL_FILT: RX Filter Failed
    884  * 							- EMAC_RINFO_MCAST: Multicast Frame
    885  * 							- EMAC_RINFO_BCAST: Broadcast Frame
    886  * 							- EMAC_RINFO_CRC_ERR: CRC Error in Frame
    887  * 							- EMAC_RINFO_SYM_ERR: Symbol Error from PHY
    888  * 							- EMAC_RINFO_LEN_ERR: Length Error
    889  * 							- EMAC_RINFO_RANGE_ERR: Range error(exceeded max size)
    890  * 							- EMAC_RINFO_ALIGN_ERR: Alignment error
    891  * 							- EMAC_RINFO_OVERRUN: Receive overrun
    892  * 							- EMAC_RINFO_NO_DESCR: No new Descriptor available
    893  * 							- EMAC_RINFO_LAST_FLAG: last Fragment in Frame
    894  * 							- EMAC_RINFO_ERR: Error Occurred (OR of all error)
    895  * @return		Current value of receive data (due to RxConsumeIndex)
    896  **********************************************************************/
    897 FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType)
    898 {
    899 	uint32_t idx;
    900 	idx = LPC_EMAC->RxConsumeIndex;
    901 	return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET);
    902 }
    903 
    904 
    905 /*********************************************************************//**
    906  * @brief		Get size of current Received data in received buffer (due to
    907  * 				RxConsumeIndex)
    908  * @param[in]	None
    909  * @return		Size of received data
    910  **********************************************************************/
    911 uint32_t EMAC_GetReceiveDataSize(void)
    912 {
    913 	uint32_t idx;
    914 	idx =LPC_EMAC->RxConsumeIndex;
    915 	return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE);
    916 }
    917 
    918 /*********************************************************************//**
    919  * @brief		Increase the RxConsumeIndex (after reading the Receive buffer
    920  * 				to release the Receive buffer) and wrap-around the index if
    921  * 				it reaches the maximum Receive Number
    922  * @param[in]	None
    923  * @return		None
    924  **********************************************************************/
    925 void EMAC_UpdateRxConsumeIndex(void)
    926 {
    927 	// Get current Rx consume index
    928 	uint32_t idx = LPC_EMAC->RxConsumeIndex;
    929 
    930 	/* Release frame from EMAC buffer */
    931 	if (++idx == EMAC_NUM_RX_FRAG) idx = 0;
    932 	LPC_EMAC->RxConsumeIndex = idx;
    933 }
    934 
    935 /*********************************************************************//**
    936  * @brief		Increase the TxProduceIndex (after writting to the Transmit buffer
    937  * 				to enable the Transmit buffer) and wrap-around the index if
    938  * 				it reaches the maximum Transmit Number
    939  * @param[in]	None
    940  * @return		None
    941  **********************************************************************/
    942 void EMAC_UpdateTxProduceIndex(void)
    943 {
    944 	// Get current Tx produce index
    945 	uint32_t idx = LPC_EMAC->TxProduceIndex;
    946 
    947 	/* Start frame transmission */
    948 	if (++idx == EMAC_NUM_TX_FRAG) idx = 0;
    949 	LPC_EMAC->TxProduceIndex = idx;
    950 }
    951 
    952 
    953 /**
    954  * @}
    955  */
    956 
    957 #endif /* _EMAC */
    958 
    959 /**
    960  * @}
    961  */
    962 
    963 /* --------------------------------- End Of File ------------------------------ */