Rewrite from scratch a TCP/IP stack for mbed. So far the following parts are usable: Drivers: - EMAC driver (from CMSIS 2.0) Protocols: - Ethernet protocol - ARP over ethernet for IPv4 - IPv4 over Ethernet - ICMPv4 over IPv4 - UDPv4 over IPv4 APIs: - Sockets for UDPv4 The structure of this stack is designed to be very modular. Each protocol can register one or more protocol to handle its payload, and in each protocol, an API can be hooked (like Sockets for example). This is an early release.
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