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