Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
lpc17xx_emac.cpp
00001 /* @cond */ 00002 /** 00003 * @file lpc17xx_emac.c 00004 * @brief Contains all functions support for Ethernet MAC firmware library on LPC17xx 00005 * @version 2.0 00006 * @date 21. May. 2010 00007 * @author NXP MCU SW Application Team 00008 ************************************************************************** 00009 * Software that is described herein is for illustrative purposes only 00010 * which provides customers with programming information regarding the 00011 * products. This software is supplied "AS IS" without any warranties. 00012 * NXP Semiconductors assumes no responsibility or liability for the 00013 * use of the software, conveys no license or title under any patent, 00014 * copyright, or mask work right to the product. NXP Semiconductors 00015 * reserves the right to make changes in the software without 00016 * notification. NXP Semiconductors also make no representation or 00017 * warranty that such application will be suitable for the specified 00018 * use without further testing or modification. 00019 **********************************************************************/ 00020 00021 /* Peripheral group ----------------------------------------------------------- */ 00022 /** @addtogroup EMAC 00023 * @{ 00024 */ 00025 00026 /* Includes ------------------------------------------------------------------- */ 00027 #include "lpc17xx_emac.h" 00028 #include "lpc17xx_clkpwr.h" 00029 00030 /* If this source file built with example, the LPC17xx FW library configuration 00031 * file in each example directory ("lpc17xx_libcfg.h") must be included, 00032 * otherwise the default FW library configuration file must be included instead 00033 */ 00034 #ifdef __BUILD_WITH_EXAMPLE__ 00035 #include "lpc17xx_libcfg.h" 00036 #else 00037 #include "lpc17xx_libcfg_default.h" 00038 #endif /* __BUILD_WITH_EXAMPLE__ */ 00039 00040 00041 #ifdef _EMAC 00042 00043 /* Private Variables ---------------------------------------------------------- */ 00044 /** @defgroup EMAC_Private_Variables EMAC Private Variables 00045 * @{ 00046 */ 00047 00048 /* MII Mgmt Configuration register - Clock divider setting */ 00049 const uint8_t EMAC_clkdiv[] = { 4, 6, 8, 10, 14, 20, 28 }; 00050 00051 /* EMAC local DMA Descriptors */ 00052 00053 /** Rx Descriptor data array */ 00054 static RX_Desc Rx_Desc[EMAC_NUM_RX_FRAG]; 00055 00056 /** Rx Status data array - Must be 8-Byte aligned */ 00057 #if defined ( __CC_ARM ) 00058 static __align(8) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; 00059 #elif defined ( __ICCARM__ ) 00060 #pragma data_alignment=8 00061 static RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; 00062 #elif defined ( __GNUC__ ) 00063 static __attribute__ ((aligned (8))) RX_Stat Rx_Stat[EMAC_NUM_RX_FRAG]; 00064 #endif 00065 00066 /** Tx Descriptor data array */ 00067 static TX_Desc Tx_Desc[EMAC_NUM_TX_FRAG]; 00068 /** Tx Status data array */ 00069 static TX_Stat Tx_Stat[EMAC_NUM_TX_FRAG]; 00070 00071 /* EMAC local DMA buffers */ 00072 /** Rx buffer data */ 00073 static __align(8) uint32_t rx_buf[EMAC_NUM_RX_FRAG][EMAC_ETH_MAX_FLEN>>2] __attribute((section("AHBSRAM1"),aligned)) ; 00074 /** Tx buffer data */ 00075 static __align(8) uint32_t tx_buf[EMAC_NUM_TX_FRAG][EMAC_ETH_MAX_FLEN>>2] __attribute((section("AHBSRAM1"),aligned)) ; 00076 00077 /** 00078 * @} 00079 */ 00080 00081 /* Private Functions ---------------------------------------------------------- */ 00082 static void rx_descr_init (void); 00083 static void tx_descr_init (void); 00084 static int32_t write_PHY (uint32_t PhyReg, uint16_t Value); 00085 static int32_t read_PHY (uint32_t PhyReg); 00086 00087 static void setEmacAddr(uint8_t abStationAddr[]); 00088 static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len); 00089 00090 00091 /*--------------------------- rx_descr_init ---------------------------------*/ 00092 /*********************************************************************//** 00093 * @brief Initializes RX Descriptor 00094 * @param[in] None 00095 * @return None 00096 ***********************************************************************/ 00097 static void rx_descr_init (void) 00098 { 00099 /* Initialize Receive Descriptor and Status array. */ 00100 uint32_t i; 00101 00102 for (i = 0; i < EMAC_NUM_RX_FRAG; i++) { 00103 Rx_Desc[i].Packet = (uint32_t)&rx_buf[i]; 00104 Rx_Desc[i].Ctrl = EMAC_RCTRL_INT | (EMAC_ETH_MAX_FLEN - 1); 00105 Rx_Stat[i].Info = 0; 00106 Rx_Stat[i].HashCRC = 0; 00107 } 00108 00109 /* Set EMAC Receive Descriptor Registers. */ 00110 LPC_EMAC->RxDescriptor = (uint32_t)&Rx_Desc[0]; 00111 LPC_EMAC->RxStatus = (uint32_t)&Rx_Stat[0]; 00112 LPC_EMAC->RxDescriptorNumber = EMAC_NUM_RX_FRAG - 1; 00113 00114 /* Rx Descriptors Point to 0 */ 00115 LPC_EMAC->RxConsumeIndex = 0; 00116 } 00117 00118 00119 /*--------------------------- tx_descr_init ---- ----------------------------*/ 00120 /*********************************************************************//** 00121 * @brief Initializes TX Descriptor 00122 * @param[in] None 00123 * @return None 00124 ***********************************************************************/ 00125 static void tx_descr_init (void) { 00126 /* Initialize Transmit Descriptor and Status array. */ 00127 uint32_t i; 00128 00129 for (i = 0; i < EMAC_NUM_TX_FRAG; i++) { 00130 Tx_Desc[i].Packet = (uint32_t)&tx_buf[i]; 00131 Tx_Desc[i].Ctrl = 0; 00132 Tx_Stat[i].Info = 0; 00133 } 00134 00135 /* Set EMAC Transmit Descriptor Registers. */ 00136 LPC_EMAC->TxDescriptor = (uint32_t)&Tx_Desc[0]; 00137 LPC_EMAC->TxStatus = (uint32_t)&Tx_Stat[0]; 00138 LPC_EMAC->TxDescriptorNumber = EMAC_NUM_TX_FRAG - 1; 00139 00140 /* Tx Descriptors Point to 0 */ 00141 LPC_EMAC->TxProduceIndex = 0; 00142 } 00143 00144 00145 /*--------------------------- write_PHY -------------------------------------*/ 00146 /*********************************************************************//** 00147 * @brief Write value to PHY device 00148 * @param[in] PhyReg: PHY Register address 00149 * @param[in] Value: Value to write 00150 * @return 0 - if success 00151 * 1 - if fail 00152 ***********************************************************************/ 00153 static int32_t write_PHY (uint32_t PhyReg, uint16_t Value) 00154 { 00155 /* Write a data 'Value' to PHY register 'PhyReg'. */ 00156 uint32_t tout; 00157 00158 LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg; 00159 LPC_EMAC->MWTD = Value; 00160 00161 /* Wait until operation completed */ 00162 tout = 0; 00163 for (tout = 0; tout < EMAC_MII_WR_TOUT; tout++) { 00164 if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) { 00165 return (0); 00166 } 00167 } 00168 // Time out! 00169 return (-1); 00170 } 00171 00172 00173 /*--------------------------- read_PHY --------------------------------------*/ 00174 /*********************************************************************//** 00175 * @brief Read value from PHY device 00176 * @param[in] PhyReg: PHY Register address 00177 * @return 0 - if success 00178 * 1 - if fail 00179 ***********************************************************************/ 00180 static int32_t read_PHY (uint32_t PhyReg) 00181 { 00182 /* Read a PHY register 'PhyReg'. */ 00183 uint32_t tout; 00184 00185 LPC_EMAC->MADR = EMAC_DEF_ADR | PhyReg; 00186 LPC_EMAC->MCMD = EMAC_MCMD_READ; 00187 00188 /* Wait until operation completed */ 00189 tout = 0; 00190 for (tout = 0; tout < EMAC_MII_RD_TOUT; tout++) { 00191 if ((LPC_EMAC->MIND & EMAC_MIND_BUSY) == 0) { 00192 LPC_EMAC->MCMD = 0; 00193 return (LPC_EMAC->MRDD); 00194 } 00195 } 00196 // Time out! 00197 return (-1); 00198 } 00199 00200 /*********************************************************************//** 00201 * @brief Set Station MAC address for EMAC module 00202 * @param[in] abStationAddr Pointer to Station address that contains 6-bytes 00203 * of MAC address (should be in order from MAC Address 1 to MAC Address 6) 00204 * @return None 00205 **********************************************************************/ 00206 static void setEmacAddr(uint8_t abStationAddr[]) 00207 { 00208 /* Set the Ethernet MAC Address registers */ 00209 LPC_EMAC->SA0 = ((uint32_t)abStationAddr[5] << 8) | (uint32_t)abStationAddr[4]; 00210 LPC_EMAC->SA1 = ((uint32_t)abStationAddr[3] << 8) | (uint32_t)abStationAddr[2]; 00211 LPC_EMAC->SA2 = ((uint32_t)abStationAddr[1] << 8) | (uint32_t)abStationAddr[0]; 00212 } 00213 00214 00215 /*********************************************************************//** 00216 * @brief Calculates CRC code for number of bytes in the frame 00217 * @param[in] frame_no_fcs Pointer to the first byte of the frame 00218 * @param[in] frame_len length of the frame without the FCS 00219 * @return the CRC as a 32 bit integer 00220 **********************************************************************/ 00221 static int32_t emac_CRCCalc(uint8_t frame_no_fcs[], int32_t frame_len) 00222 { 00223 int i; // iterator 00224 int j; // another iterator 00225 char byte; // current byte 00226 int crc; // CRC result 00227 int q0, q1, q2, q3; // temporary variables 00228 crc = 0xFFFFFFFF; 00229 for (i = 0; i < frame_len; i++) { 00230 byte = *frame_no_fcs++; 00231 for (j = 0; j < 2; j++) { 00232 if (((crc >> 28) ^ (byte >> 3)) & 0x00000001) { 00233 q3 = 0x04C11DB7; 00234 } else { 00235 q3 = 0x00000000; 00236 } 00237 if (((crc >> 29) ^ (byte >> 2)) & 0x00000001) { 00238 q2 = 0x09823B6E; 00239 } else { 00240 q2 = 0x00000000; 00241 } 00242 if (((crc >> 30) ^ (byte >> 1)) & 0x00000001) { 00243 q1 = 0x130476DC; 00244 } else { 00245 q1 = 0x00000000; 00246 } 00247 if (((crc >> 31) ^ (byte >> 0)) & 0x00000001) { 00248 q0 = 0x2608EDB8; 00249 } else { 00250 q0 = 0x00000000; 00251 } 00252 crc = (crc << 4) ^ q3 ^ q2 ^ q1 ^ q0; 00253 byte >>= 4; 00254 } 00255 } 00256 return crc; 00257 } 00258 /* End of Private Functions --------------------------------------------------- */ 00259 00260 00261 /* Public Functions ----------------------------------------------------------- */ 00262 /** @addtogroup EMAC_Public_Functions 00263 * @{ 00264 */ 00265 00266 00267 /*********************************************************************//** 00268 * @brief Initializes the EMAC peripheral according to the specified 00269 * parameters in the EMAC_ConfigStruct. 00270 * @param[in] EMAC_ConfigStruct Pointer to a EMAC_CFG_Type structure 00271 * that contains the configuration information for the 00272 * specified EMAC peripheral. 00273 * @return None 00274 * 00275 * Note: This function will initialize EMAC module according to procedure below: 00276 * - Remove the soft reset condition from the MAC 00277 * - Configure the PHY via the MIIM interface of the MAC 00278 * - Select RMII mode 00279 * - Configure the transmit and receive DMA engines, including the descriptor arrays 00280 * - Configure the host registers (MAC1,MAC2 etc.) in the MAC 00281 * - Enable the receive and transmit data paths 00282 * In default state after initializing, only Rx Done and Tx Done interrupt are enabled, 00283 * all remain interrupts are disabled 00284 * (Ref. from LPC17xx UM) 00285 **********************************************************************/ 00286 Status EMAC_Init(EMAC_CFG_Type *EMAC_ConfigStruct) 00287 { 00288 /* Initialize the EMAC Ethernet controller. */ 00289 int32_t regv,tout, tmp; 00290 00291 /* Set up clock and power for Ethernet module */ 00292 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, ENABLE); 00293 00294 /* Reset all EMAC internal modules */ 00295 LPC_EMAC->MAC1 = EMAC_MAC1_RES_TX | EMAC_MAC1_RES_MCS_TX | EMAC_MAC1_RES_RX | 00296 EMAC_MAC1_RES_MCS_RX | EMAC_MAC1_SIM_RES | EMAC_MAC1_SOFT_RES; 00297 00298 LPC_EMAC->Command = EMAC_CR_REG_RES | EMAC_CR_TX_RES | EMAC_CR_RX_RES | EMAC_CR_PASS_RUNT_FRM; 00299 00300 /* A short delay after reset. */ 00301 for (tout = 100; tout; tout--); 00302 00303 /* Initialize MAC control registers. */ 00304 LPC_EMAC->MAC1 = EMAC_MAC1_PASS_ALL; 00305 LPC_EMAC->MAC2 = EMAC_MAC2_CRC_EN | EMAC_MAC2_PAD_EN; 00306 LPC_EMAC->MAXF = EMAC_ETH_MAX_FLEN; 00307 /* 00308 * Find the clock that close to desired target clock 00309 */ 00310 tmp = SystemCoreClock / EMAC_MCFG_MII_MAXCLK; 00311 for (tout = 0; tout < sizeof (EMAC_clkdiv); tout++){ 00312 if (EMAC_clkdiv[tout] >= tmp) break; 00313 } 00314 tout++; 00315 // Write to MAC configuration register and reset 00316 LPC_EMAC->MCFG = EMAC_MCFG_CLK_SEL(tout) | EMAC_MCFG_RES_MII; 00317 // release reset 00318 LPC_EMAC->MCFG &= ~(EMAC_MCFG_RES_MII); 00319 LPC_EMAC->CLRT = EMAC_CLRT_DEF; 00320 LPC_EMAC->IPGR = EMAC_IPGR_P2_DEF; 00321 00322 /* Enable Reduced MII interface. */ 00323 LPC_EMAC->Command = EMAC_CR_RMII | EMAC_CR_PASS_RUNT_FRM; 00324 00325 /* Reset Reduced MII Logic. */ 00326 LPC_EMAC->SUPP = EMAC_SUPP_RES_RMII; 00327 00328 for (tout = 100; tout; tout--); 00329 LPC_EMAC->SUPP = 0; 00330 00331 /* Put the DP83848C in reset mode */ 00332 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_RESET); 00333 00334 /* Wait for hardware reset to end. */ 00335 for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { 00336 regv = read_PHY (EMAC_PHY_REG_BMCR); 00337 if (!(regv & (EMAC_PHY_BMCR_RESET | EMAC_PHY_BMCR_POWERDOWN))) { 00338 /* Reset complete, device not Power Down. */ 00339 break; 00340 } 00341 if (tout == 0){ 00342 // Time out, return ERROR 00343 return (ERROR); 00344 } 00345 } 00346 00347 // Set PHY mode 00348 if (EMAC_SetPHYMode(EMAC_ConfigStruct->Mode) < 0){ 00349 return (ERROR); 00350 } 00351 00352 // Set EMAC address 00353 setEmacAddr(EMAC_ConfigStruct->pbEMAC_Addr); 00354 00355 /* Initialize Tx and Rx DMA Descriptors */ 00356 rx_descr_init (); 00357 tx_descr_init (); 00358 00359 // Set Receive Filter register: enable broadcast and multicast 00360 LPC_EMAC->RxFilterCtrl = EMAC_RFC_MCAST_EN | EMAC_RFC_BCAST_EN | EMAC_RFC_PERFECT_EN; 00361 00362 /* Enable Rx Done and Tx Done interrupt for EMAC */ 00363 LPC_EMAC->IntEnable = EMAC_INT_RX_DONE/* | EMAC_INT_TX_DONE*/; 00364 00365 /* Reset all interrupts */ 00366 LPC_EMAC->IntClear = 0xFFFF; 00367 00368 /* Enable receive and transmit mode of MAC Ethernet core */ 00369 LPC_EMAC->Command |= (EMAC_CR_RX_EN | EMAC_CR_TX_EN); 00370 LPC_EMAC->MAC1 |= EMAC_MAC1_REC_EN; 00371 00372 return SUCCESS; 00373 } 00374 00375 00376 /*********************************************************************//** 00377 * @brief De-initializes the EMAC peripheral registers to their 00378 * default reset values. 00379 * @param[in] None 00380 * @return None 00381 **********************************************************************/ 00382 void EMAC_DeInit(void) 00383 { 00384 // Disable all interrupt 00385 LPC_EMAC->IntEnable = 0x00; 00386 // Clear all pending interrupt 00387 LPC_EMAC->IntClear = (0xFF) | (EMAC_INT_SOFT_INT | EMAC_INT_WAKEUP); 00388 00389 /* TurnOff clock and power for Ethernet module */ 00390 CLKPWR_ConfigPPWR (CLKPWR_PCONP_PCENET, DISABLE); 00391 } 00392 00393 00394 /*********************************************************************//** 00395 * @brief Check specified PHY status in EMAC peripheral 00396 * @param[in] ulPHYState Specified PHY Status Type, should be: 00397 * - EMAC_PHY_STAT_LINK: Link Status 00398 * - EMAC_PHY_STAT_SPEED: Speed Status 00399 * - EMAC_PHY_STAT_DUP: Duplex Status 00400 * @return Status of specified PHY status (0 or 1). 00401 * (-1) if error. 00402 * 00403 * Note: 00404 * For EMAC_PHY_STAT_LINK, return value: 00405 * - 0: Link Down 00406 * - 1: Link Up 00407 * For EMAC_PHY_STAT_SPEED, return value: 00408 * - 0: 10Mbps 00409 * - 1: 100Mbps 00410 * For EMAC_PHY_STAT_DUP, return value: 00411 * - 0: Half-Duplex 00412 * - 1: Full-Duplex 00413 **********************************************************************/ 00414 int32_t EMAC_CheckPHYStatus(uint32_t ulPHYState) 00415 { 00416 int32_t regv, tmp; 00417 #ifdef MCB_LPC_1768 00418 regv = read_PHY (EMAC_PHY_REG_STS); 00419 switch(ulPHYState){ 00420 case EMAC_PHY_STAT_LINK: 00421 tmp = (regv & EMAC_PHY_SR_LINK) ? 1 : 0; 00422 break; 00423 case EMAC_PHY_STAT_SPEED: 00424 tmp = (regv & EMAC_PHY_SR_SPEED) ? 0 : 1; 00425 break; 00426 case EMAC_PHY_STAT_DUP: 00427 tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0; 00428 break; 00429 #elif defined(IAR_LPC_1768) 00430 /* Use IAR_LPC_1768 board: 00431 * FSZ8721BL doesn't have Status Register 00432 * so we read Basic Mode Status Register (0x01h) instead 00433 */ 00434 regv = read_PHY (EMAC_PHY_REG_BMSR); 00435 switch(ulPHYState){ 00436 case EMAC_PHY_STAT_LINK: 00437 tmp = (regv & EMAC_PHY_BMSR_LINK_STATUS) ? 1 : 0; 00438 break; 00439 case EMAC_PHY_STAT_SPEED: 00440 tmp = (regv & EMAC_PHY_SR_100_SPEED) ? 1 : 0; 00441 break; 00442 case EMAC_PHY_STAT_DUP: 00443 tmp = (regv & EMAC_PHY_SR_FULL_DUP) ? 1 : 0; 00444 break; 00445 #endif 00446 default: 00447 tmp = -1; 00448 break; 00449 } 00450 return (tmp); 00451 } 00452 00453 00454 /*********************************************************************//** 00455 * @brief Set specified PHY mode in EMAC peripheral 00456 * @param[in] ulPHYMode Specified PHY mode, should be: 00457 * - EMAC_MODE_AUTO 00458 * - EMAC_MODE_10M_FULL 00459 * - EMAC_MODE_10M_HALF 00460 * - EMAC_MODE_100M_FULL 00461 * - EMAC_MODE_100M_HALF 00462 * @return Return (0) if no error, otherwise return (-1) 00463 **********************************************************************/ 00464 int32_t EMAC_SetPHYMode(uint32_t ulPHYMode) 00465 { 00466 int32_t id1, id2, tout, regv; 00467 00468 /* Check if this is a DP83848C PHY. */ 00469 id1 = read_PHY (EMAC_PHY_REG_IDR1); 00470 id2 = read_PHY (EMAC_PHY_REG_IDR2); 00471 00472 #ifdef MCB_LPC_1768 00473 if (((id1 << 16) | (id2 & 0xFFF0)) == EMAC_DP83848C_ID) { 00474 switch(ulPHYMode){ 00475 case EMAC_MODE_AUTO: 00476 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG); 00477 #elif defined(IAR_LPC_1768) /* Use IAR LPC1768 KickStart board */ 00478 if (((id1 << 16) | id2) == EMAC_KSZ8721BL_ID) { 00479 /* Configure the PHY device */ 00480 switch(ulPHYMode){ 00481 case EMAC_MODE_AUTO: 00482 /* Use auto-negotiation about the link speed. */ 00483 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_AUTO_NEG); 00484 // write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_BMCR_AN); 00485 #endif 00486 /* Wait to complete Auto_Negotiation */ 00487 for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { 00488 regv = read_PHY (EMAC_PHY_REG_BMSR); 00489 if (regv & EMAC_PHY_BMSR_AUTO_DONE) { 00490 /* Auto-negotiation Complete. */ 00491 break; 00492 } 00493 if (tout == 0){ 00494 // Time out, return error 00495 return (-1); 00496 } 00497 } 00498 break; 00499 case EMAC_MODE_10M_FULL: 00500 /* Connect at 10MBit full-duplex */ 00501 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_10M); 00502 break; 00503 case EMAC_MODE_10M_HALF: 00504 /* Connect at 10MBit half-duplex */ 00505 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_10M); 00506 break; 00507 case EMAC_MODE_100M_FULL: 00508 /* Connect at 100MBit full-duplex */ 00509 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_FULLD_100M); 00510 break; 00511 case EMAC_MODE_100M_HALF: 00512 /* Connect at 100MBit half-duplex */ 00513 write_PHY (EMAC_PHY_REG_BMCR, EMAC_PHY_HALFD_100M); 00514 break; 00515 default: 00516 // un-supported 00517 return (-1); 00518 } 00519 } 00520 // It's not correct module ID 00521 else { 00522 return (-1); 00523 } 00524 00525 // Update EMAC configuration with current PHY status 00526 if (EMAC_UpdatePHYStatus() < 0){ 00527 return (-1); 00528 } 00529 00530 // Complete 00531 return (0); 00532 } 00533 00534 00535 /*********************************************************************//** 00536 * @brief Auto-Configures value for the EMAC configuration register to 00537 * match with current PHY mode 00538 * @param[in] None 00539 * @return Return (0) if no error, otherwise return (-1) 00540 * 00541 * Note: The EMAC configuration will be auto-configured: 00542 * - Speed mode. 00543 * - Half/Full duplex mode 00544 **********************************************************************/ 00545 int32_t EMAC_UpdatePHYStatus(void) 00546 { 00547 int32_t regv, tout; 00548 00549 /* Check the link status. */ 00550 #ifdef MCB_LPC_1768 00551 for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { 00552 regv = read_PHY (EMAC_PHY_REG_STS); 00553 if (regv & EMAC_PHY_SR_LINK) { 00554 /* Link is on. */ 00555 break; 00556 } 00557 if (tout == 0){ 00558 // time out 00559 return (-1); 00560 } 00561 } 00562 /* Configure Full/Half Duplex mode. */ 00563 if (regv & EMAC_PHY_SR_DUP) { 00564 /* Full duplex is enabled. */ 00565 LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; 00566 LPC_EMAC->Command |= EMAC_CR_FULL_DUP; 00567 LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; 00568 } else { 00569 /* Half duplex mode. */ 00570 LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; 00571 } 00572 if (regv & EMAC_PHY_SR_SPEED) { 00573 /* 10MBit mode. */ 00574 LPC_EMAC->SUPP = 0; 00575 } else { 00576 /* 100MBit mode. */ 00577 LPC_EMAC->SUPP = EMAC_SUPP_SPEED; 00578 } 00579 #elif defined(IAR_LPC_1768) 00580 for (tout = EMAC_PHY_RESP_TOUT; tout; tout--) { 00581 regv = read_PHY (EMAC_PHY_REG_BMSR); 00582 if (regv & EMAC_PHY_BMSR_LINK_STATUS) { 00583 /* Link is on. */ 00584 break; 00585 } 00586 if (tout == 0){ 00587 // time out 00588 return (-1); 00589 } 00590 } 00591 00592 /* Configure Full/Half Duplex mode. */ 00593 if (regv & EMAC_PHY_SR_FULL_DUP) { 00594 /* Full duplex is enabled. */ 00595 LPC_EMAC->MAC2 |= EMAC_MAC2_FULL_DUP; 00596 LPC_EMAC->Command |= EMAC_CR_FULL_DUP; 00597 LPC_EMAC->IPGT = EMAC_IPGT_FULL_DUP; 00598 } else { 00599 /* Half duplex mode. */ 00600 LPC_EMAC->IPGT = EMAC_IPGT_HALF_DUP; 00601 } 00602 00603 /* Configure 100MBit/10MBit mode. */ 00604 if (!(regv & EMAC_PHY_SR_100_SPEED)) { 00605 /* 10MBit mode. */ 00606 LPC_EMAC->SUPP = 0; 00607 } else { 00608 /* 100MBit mode. */ 00609 LPC_EMAC->SUPP = EMAC_SUPP_SPEED; 00610 } 00611 #endif 00612 // Complete 00613 return (0); 00614 } 00615 00616 00617 /*********************************************************************//** 00618 * @brief Enable/Disable hash filter functionality for specified destination 00619 * MAC address in EMAC module 00620 * @param[in] dstMAC_addr Pointer to the first MAC destination address, should 00621 * be 6-bytes length, in order LSB to the MSB 00622 * @param[in] NewState New State of this command, should be: 00623 * - ENABLE. 00624 * - DISABLE. 00625 * @return None 00626 * 00627 * Note: 00628 * The standard Ethernet cyclic redundancy check (CRC) function is calculated from 00629 * the 6 byte destination address in the Ethernet frame (this CRC is calculated 00630 * anyway as part of calculating the CRC of the whole frame), then bits [28:23] out of 00631 * the 32 bits CRC result are taken to form the hash. The 6 bit hash is used to access 00632 * the hash table: it is used as an index in the 64 bit HashFilter register that has been 00633 * programmed with accept values. If the selected accept value is 1, the frame is 00634 * accepted. 00635 **********************************************************************/ 00636 void EMAC_SetHashFilter(uint8_t dstMAC_addr[], FunctionalState NewState) 00637 { 00638 uint32_t *pReg; 00639 uint32_t tmp; 00640 int32_t crc; 00641 00642 // Calculate the CRC from the destination MAC address 00643 crc = emac_CRCCalc(dstMAC_addr, 6); 00644 // Extract the value from CRC to get index value for hash filter table 00645 crc = (crc >> 23) & 0x3F; 00646 00647 pReg = (crc > 31) ? ((uint32_t *)&LPC_EMAC->HashFilterH) \ 00648 : ((uint32_t *)&LPC_EMAC->HashFilterL); 00649 tmp = (crc > 31) ? (crc - 32) : crc; 00650 if (NewState == ENABLE) { 00651 (*pReg) |= (1UL << tmp); 00652 } else { 00653 (*pReg) &= ~(1UL << tmp); 00654 } 00655 // Enable Rx Filter 00656 LPC_EMAC->Command &= ~EMAC_CR_PASS_RX_FILT; 00657 } 00658 00659 /*********************************************************************//** 00660 * @brief Enable/Disable Filter mode for each specified type EMAC peripheral 00661 * @param[in] ulFilterMode Filter mode, should be: 00662 * - EMAC_RFC_UCAST_EN: all frames of unicast types 00663 * will be accepted 00664 * - EMAC_RFC_BCAST_EN: broadcast frame will be 00665 * accepted 00666 * - EMAC_RFC_MCAST_EN: all frames of multicast 00667 * types will be accepted 00668 * - EMAC_RFC_UCAST_HASH_EN: The imperfect hash 00669 * filter will be applied to unicast addresses 00670 * - EMAC_RFC_MCAST_HASH_EN: The imperfect hash 00671 * filter will be applied to multicast addresses 00672 * - EMAC_RFC_PERFECT_EN: the destination address 00673 * will be compared with the 6 byte station address 00674 * programmed in the station address by the filter 00675 * - EMAC_RFC_MAGP_WOL_EN: the result of the magic 00676 * packet filter will generate a WoL interrupt when 00677 * there is a match 00678 * - EMAC_RFC_PFILT_WOL_EN: the result of the perfect address 00679 * matching filter and the imperfect hash filter will 00680 * generate a WoL interrupt when there is a match 00681 * @param[in] NewState New State of this command, should be: 00682 * - ENABLE 00683 * - DISABLE 00684 * @return None 00685 **********************************************************************/ 00686 void EMAC_SetFilterMode(uint32_t ulFilterMode, FunctionalState NewState) 00687 { 00688 if (NewState == ENABLE){ 00689 LPC_EMAC->RxFilterCtrl |= ulFilterMode; 00690 } else { 00691 LPC_EMAC->RxFilterCtrl &= ~ulFilterMode; 00692 } 00693 } 00694 00695 /*********************************************************************//** 00696 * @brief Get status of Wake On LAN Filter for each specified 00697 * type in EMAC peripheral, clear this status if it is set 00698 * @param[in] ulWoLMode WoL Filter mode, should be: 00699 * - EMAC_WOL_UCAST: unicast frames caused WoL 00700 * - EMAC_WOL_UCAST: broadcast frame caused WoL 00701 * - EMAC_WOL_MCAST: multicast frame caused WoL 00702 * - EMAC_WOL_UCAST_HASH: unicast frame that passes the 00703 * imperfect hash filter caused WoL 00704 * - EMAC_WOL_MCAST_HASH: multicast frame that passes the 00705 * imperfect hash filter caused WoL 00706 * - EMAC_WOL_PERFECT:perfect address matching filter 00707 * caused WoL 00708 * - EMAC_WOL_RX_FILTER: the receive filter caused WoL 00709 * - EMAC_WOL_MAG_PACKET: the magic packet filter caused WoL 00710 * @return SET/RESET 00711 **********************************************************************/ 00712 FlagStatus EMAC_GetWoLStatus(uint32_t ulWoLMode) 00713 { 00714 if (LPC_EMAC->RxFilterWoLStatus & ulWoLMode) { 00715 LPC_EMAC->RxFilterWoLClear = ulWoLMode; 00716 return SET; 00717 } else { 00718 return RESET; 00719 } 00720 } 00721 00722 00723 /*********************************************************************//** 00724 * @brief Write data to Tx packet data buffer at current index due to 00725 * TxProduceIndex 00726 * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure 00727 * data that contain specified information about 00728 * Packet data buffer. 00729 * @return None 00730 **********************************************************************/ 00731 void EMAC_WritePacketBuffer(EMAC_PACKETBUF_Type *pDataStruct) 00732 { 00733 uint32_t idx,len; 00734 uint32_t *sp,*dp; 00735 00736 idx = LPC_EMAC->TxProduceIndex; 00737 sp = (uint32_t *)pDataStruct->pbDataBuf; 00738 dp = (uint32_t *)Tx_Desc[idx].Packet; 00739 /* Copy frame data to EMAC packet buffers. */ 00740 for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) { 00741 *dp++ = *sp++; 00742 } 00743 Tx_Desc[idx].Ctrl = (pDataStruct->ulDataLen - 1) | (EMAC_TCTRL_INT | EMAC_TCTRL_LAST); 00744 } 00745 00746 /*********************************************************************//** 00747 * @brief Read data from Rx packet data buffer at current index due 00748 * to RxConsumeIndex 00749 * @param[in] pDataStruct Pointer to a EMAC_PACKETBUF_Type structure 00750 * data that contain specified information about 00751 * Packet data buffer. 00752 * @return None 00753 **********************************************************************/ 00754 void EMAC_ReadPacketBuffer(EMAC_PACKETBUF_Type *pDataStruct) 00755 { 00756 uint32_t idx, len; 00757 uint32_t *dp, *sp; 00758 00759 idx = LPC_EMAC->RxConsumeIndex; 00760 dp = (uint32_t *)pDataStruct->pbDataBuf; 00761 sp = (uint32_t *)Rx_Desc[idx].Packet; 00762 00763 if (pDataStruct->pbDataBuf != NULL) { 00764 for (len = (pDataStruct->ulDataLen + 3) >> 2; len; len--) { 00765 *dp++ = *sp++; 00766 } 00767 } 00768 } 00769 00770 /*********************************************************************//** 00771 * @brief Enable/Disable interrupt for each type in EMAC 00772 * @param[in] ulIntType Interrupt Type, should be: 00773 * - EMAC_INT_RX_OVERRUN: Receive Overrun 00774 * - EMAC_INT_RX_ERR: Receive Error 00775 * - EMAC_INT_RX_FIN: Receive Descriptor Finish 00776 * - EMAC_INT_RX_DONE: Receive Done 00777 * - EMAC_INT_TX_UNDERRUN: Transmit Under-run 00778 * - EMAC_INT_TX_ERR: Transmit Error 00779 * - EMAC_INT_TX_FIN: Transmit descriptor finish 00780 * - EMAC_INT_TX_DONE: Transmit Done 00781 * - EMAC_INT_SOFT_INT: Software interrupt 00782 * - EMAC_INT_WAKEUP: Wakeup interrupt 00783 * @param[in] NewState New State of this function, should be: 00784 * - ENABLE. 00785 * - DISABLE. 00786 * @return None 00787 **********************************************************************/ 00788 void EMAC_IntCmd(uint32_t ulIntType, FunctionalState NewState) 00789 { 00790 if (NewState == ENABLE) { 00791 LPC_EMAC->IntEnable |= ulIntType; 00792 } else { 00793 LPC_EMAC->IntEnable &= ~(ulIntType); 00794 } 00795 } 00796 00797 /*********************************************************************//** 00798 * @brief Check whether if specified interrupt flag is set or not 00799 * for each interrupt type in EMAC and clear interrupt pending 00800 * if it is set. 00801 * @param[in] ulIntType Interrupt Type, should be: 00802 * - EMAC_INT_RX_OVERRUN: Receive Overrun 00803 * - EMAC_INT_RX_ERR: Receive Error 00804 * - EMAC_INT_RX_FIN: Receive Descriptor Finish 00805 * - EMAC_INT_RX_DONE: Receive Done 00806 * - EMAC_INT_TX_UNDERRUN: Transmit Under-run 00807 * - EMAC_INT_TX_ERR: Transmit Error 00808 * - EMAC_INT_TX_FIN: Transmit descriptor finish 00809 * - EMAC_INT_TX_DONE: Transmit Done 00810 * - EMAC_INT_SOFT_INT: Software interrupt 00811 * - EMAC_INT_WAKEUP: Wakeup interrupt 00812 * @return New state of specified interrupt (SET or RESET) 00813 **********************************************************************/ 00814 IntStatus EMAC_IntGetStatus(uint32_t ulIntType) 00815 { 00816 if (LPC_EMAC->IntStatus & ulIntType) { 00817 LPC_EMAC->IntClear = ulIntType; 00818 return SET; 00819 } else { 00820 return RESET; 00821 } 00822 } 00823 00824 00825 /*********************************************************************//** 00826 * @brief Check whether if the current RxConsumeIndex is not equal to the 00827 * current RxProduceIndex. 00828 * @param[in] None 00829 * @return TRUE if they're not equal, otherwise return FALSE 00830 * 00831 * Note: In case the RxConsumeIndex is not equal to the RxProduceIndex, 00832 * it means there're available data has been received. They should be read 00833 * out and released the Receive Data Buffer by updating the RxConsumeIndex value. 00834 **********************************************************************/ 00835 Bool EMAC_CheckReceiveIndex(void) 00836 { 00837 if (LPC_EMAC->RxConsumeIndex != LPC_EMAC->RxProduceIndex) { 00838 return TRUE; 00839 } else { 00840 return FALSE; 00841 } 00842 } 00843 00844 00845 /*********************************************************************//** 00846 * @brief Check whether if the current TxProduceIndex is not equal to the 00847 * current RxProduceIndex - 1. 00848 * @param[in] None 00849 * @return TRUE if they're not equal, otherwise return FALSE 00850 * 00851 * Note: In case the RxConsumeIndex is equal to the RxProduceIndex - 1, 00852 * it means the transmit buffer is available and data can be written to transmit 00853 * buffer to be sent. 00854 **********************************************************************/ 00855 Bool EMAC_CheckTransmitIndex(void) 00856 { 00857 uint32_t tmp = LPC_EMAC->TxConsumeIndex -1; 00858 if (LPC_EMAC->TxProduceIndex == tmp) { 00859 return FALSE; 00860 } else { 00861 return TRUE; 00862 } 00863 } 00864 00865 00866 /*********************************************************************//** 00867 * @brief Get current status value of receive data (due to RxConsumeIndex) 00868 * @param[in] ulRxStatType Received Status type, should be one of following: 00869 * - EMAC_RINFO_CTRL_FRAME: Control Frame 00870 * - EMAC_RINFO_VLAN: VLAN Frame 00871 * - EMAC_RINFO_FAIL_FILT: RX Filter Failed 00872 * - EMAC_RINFO_MCAST: Multicast Frame 00873 * - EMAC_RINFO_BCAST: Broadcast Frame 00874 * - EMAC_RINFO_CRC_ERR: CRC Error in Frame 00875 * - EMAC_RINFO_SYM_ERR: Symbol Error from PHY 00876 * - EMAC_RINFO_LEN_ERR: Length Error 00877 * - EMAC_RINFO_RANGE_ERR: Range error(exceeded max size) 00878 * - EMAC_RINFO_ALIGN_ERR: Alignment error 00879 * - EMAC_RINFO_OVERRUN: Receive overrun 00880 * - EMAC_RINFO_NO_DESCR: No new Descriptor available 00881 * - EMAC_RINFO_LAST_FLAG: last Fragment in Frame 00882 * - EMAC_RINFO_ERR: Error Occurred (OR of all error) 00883 * @return Current value of receive data (due to RxConsumeIndex) 00884 **********************************************************************/ 00885 FlagStatus EMAC_CheckReceiveDataStatus(uint32_t ulRxStatType) 00886 { 00887 uint32_t idx; 00888 idx = LPC_EMAC->RxConsumeIndex; 00889 return (((Rx_Stat[idx].Info) & ulRxStatType) ? SET : RESET); 00890 } 00891 00892 00893 /*********************************************************************//** 00894 * @brief Get size of current Received data in received buffer (due to 00895 * RxConsumeIndex) 00896 * @param[in] None 00897 * @return Size of received data 00898 **********************************************************************/ 00899 uint32_t EMAC_GetReceiveDataSize(void) 00900 { 00901 uint32_t idx; 00902 idx =LPC_EMAC->RxConsumeIndex; 00903 return ((Rx_Stat[idx].Info) & EMAC_RINFO_SIZE); 00904 } 00905 00906 /*********************************************************************//** 00907 * @brief Increase the RxConsumeIndex (after reading the Receive buffer 00908 * to release the Receive buffer) and wrap-around the index if 00909 * it reaches the maximum Receive Number 00910 * @param[in] None 00911 * @return None 00912 **********************************************************************/ 00913 void EMAC_UpdateRxConsumeIndex(void) 00914 { 00915 // Get current Rx consume index 00916 uint32_t idx = LPC_EMAC->RxConsumeIndex; 00917 00918 /* Release frame from EMAC buffer */ 00919 if (++idx == EMAC_NUM_RX_FRAG) idx = 0; 00920 LPC_EMAC->RxConsumeIndex = idx; 00921 } 00922 00923 /*********************************************************************//** 00924 * @brief Increase the TxProduceIndex (after writting to the Transmit buffer 00925 * to enable the Transmit buffer) and wrap-around the index if 00926 * it reaches the maximum Transmit Number 00927 * @param[in] None 00928 * @return None 00929 **********************************************************************/ 00930 void EMAC_UpdateTxProduceIndex(void) 00931 { 00932 // Get current Tx produce index 00933 uint32_t idx = LPC_EMAC->TxProduceIndex; 00934 00935 /* Start frame transmission */ 00936 if (++idx == EMAC_NUM_TX_FRAG) idx = 0; 00937 LPC_EMAC->TxProduceIndex = idx; 00938 } 00939 00940 00941 /** 00942 * @} 00943 */ 00944 00945 #endif /* _EMAC */ 00946 00947 /** 00948 * @} 00949 */ 00950 00951 /* --------------------------------- End Of File ------------------------------ */ 00952 /* @endcond */
Generated on Wed Jul 13 2022 06:09:33 by
1.7.2