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