Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
lpc175x_eth.c
00001 /** 00002 * @file lpc175x_eth.c 00003 * @brief LPC1758 Ethernet MAC controller 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL NIC_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "lpc17xx.h" 00034 #include "core/net.h" 00035 #include "drivers/lpc175x_eth.h" 00036 #include "debug.h" 00037 00038 //Underlying network interface 00039 static NetInterface *nicDriverInterface; 00040 00041 //IAR EWARM compiler? 00042 #if defined(__ICCARM__) 00043 00044 //Transmit buffer 00045 #pragma data_alignment = 4 00046 static uint8_t txBuffer[LPC175X_ETH_TX_BUFFER_COUNT][LPC175X_ETH_TX_BUFFER_SIZE]; 00047 //Receive buffer 00048 #pragma data_alignment = 4 00049 static uint8_t rxBuffer[LPC175X_ETH_RX_BUFFER_COUNT][LPC175X_ETH_RX_BUFFER_SIZE]; 00050 //Transmit descriptors 00051 #pragma data_alignment = 4 00052 static Lpc175xTxDesc txDesc[LPC175X_ETH_TX_BUFFER_COUNT]; 00053 //Transmit status array 00054 #pragma data_alignment = 4 00055 static Lpc175xTxStatus txStatus[LPC175X_ETH_TX_BUFFER_COUNT]; 00056 //Receive descriptors 00057 #pragma data_alignment = 4 00058 static Lpc175xRxDesc rxDesc[LPC175X_ETH_RX_BUFFER_COUNT]; 00059 //Receive status array 00060 #pragma data_alignment = 8 00061 static Lpc175xRxStatus rxStatus[LPC175X_ETH_RX_BUFFER_COUNT]; 00062 00063 //Keil MDK-ARM or GCC compiler? 00064 #else 00065 00066 //Transmit buffer 00067 static uint8_t txBuffer[LPC175X_ETH_TX_BUFFER_COUNT][LPC175X_ETH_TX_BUFFER_SIZE] 00068 __attribute__((aligned(4))); 00069 //Receive buffer 00070 static uint8_t rxBuffer[LPC175X_ETH_RX_BUFFER_COUNT][LPC175X_ETH_RX_BUFFER_SIZE] 00071 __attribute__((aligned(4))); 00072 //Transmit descriptors 00073 static Lpc175xTxDesc txDesc[LPC175X_ETH_TX_BUFFER_COUNT] 00074 __attribute__((aligned(4))); 00075 //Transmit status array 00076 static Lpc175xTxStatus txStatus[LPC175X_ETH_TX_BUFFER_COUNT] 00077 __attribute__((aligned(4))); 00078 //Receive descriptors 00079 static Lpc175xRxDesc rxDesc[LPC175X_ETH_RX_BUFFER_COUNT] 00080 __attribute__((aligned(4))); 00081 //Receive status array 00082 static Lpc175xRxStatus rxStatus[LPC175X_ETH_RX_BUFFER_COUNT] 00083 __attribute__((aligned(8))); 00084 00085 #endif 00086 00087 00088 /** 00089 * @brief LPC175x Ethernet MAC driver 00090 **/ 00091 00092 const NicDriver lpc175xEthDriver = 00093 { 00094 NIC_TYPE_ETHERNET, 00095 ETH_MTU, 00096 lpc175xEthInit, 00097 lpc175xEthTick, 00098 lpc175xEthEnableIrq, 00099 lpc175xEthDisableIrq, 00100 lpc175xEthEventHandler, 00101 lpc175xEthSendPacket, 00102 lpc175xEthSetMulticastFilter, 00103 lpc175xEthUpdateMacConfig, 00104 lpc175xEthWritePhyReg, 00105 lpc175xEthReadPhyReg, 00106 TRUE, 00107 TRUE, 00108 TRUE, 00109 FALSE 00110 }; 00111 00112 00113 /** 00114 * @brief LPC175x Ethernet MAC initialization 00115 * @param[in] interface Underlying network interface 00116 * @return Error code 00117 **/ 00118 00119 error_t lpc175xEthInit(NetInterface *interface) 00120 { 00121 error_t error; 00122 00123 //Debug message 00124 TRACE_INFO("Initializing LPC175x Ethernet MAC...\r\n"); 00125 00126 //Save underlying network interface 00127 nicDriverInterface = interface; 00128 00129 //Power up EMAC controller 00130 LPC_SC->PCONP |= PCONP_PCENET; 00131 00132 //GPIO configuration 00133 lpc175xEthInitGpio(interface); 00134 00135 //Reset host registers, transmit datapath and receive datapath 00136 LPC_EMAC->Command = COMMAND_RX_RESET | COMMAND_TX_RESET | COMMAND_REG_RESET; 00137 00138 //Reset EMAC controller 00139 LPC_EMAC->MAC1 = MAC1_SOFT_RESET | MAC1_SIMULATION_RESET | 00140 MAC1_RESET_MCS_RX | MAC1_RESET_RX | MAC1_RESET_MCS_TX | MAC1_RESET_TX; 00141 00142 //Initialize MAC related registers 00143 LPC_EMAC->MAC1 = 0; 00144 LPC_EMAC->MAC2 = MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE; 00145 LPC_EMAC->IPGR = IPGR_DEFAULT_VALUE; 00146 LPC_EMAC->CLRT = CLRT_DEFAULT_VALUE; 00147 00148 //Select RMII mode 00149 LPC_EMAC->Command = COMMAND_RMII; 00150 00151 //PHY transceiver initialization 00152 error = interface->phyDriver->init(interface); 00153 //Failed to initialize PHY transceiver? 00154 if(error) 00155 return error; 00156 00157 //Initialize TX and RX descriptor arrays 00158 lpc175xEthInitDesc(interface); 00159 00160 //Set the MAC address 00161 LPC_EMAC->SA0 = interface->macAddr.w[2]; 00162 LPC_EMAC->SA1 = interface->macAddr.w[1]; 00163 LPC_EMAC->SA2 = interface->macAddr.w[0]; 00164 00165 //Initialize hash table 00166 LPC_EMAC->HashFilterL = 0; 00167 LPC_EMAC->HashFilterH = 0; 00168 00169 //Configure the receive filter 00170 LPC_EMAC->RxFilterCtrl = RFC_ACCEPT_PERFECT_EN | 00171 RFC_ACCEPT_MULTICAST_HASH_EN | RFC_ACCEPT_BROADCAST_EN; 00172 00173 //Program the MAXF register with the maximum frame length to be accepted 00174 LPC_EMAC->MAXF = 1518; 00175 00176 //Reset EMAC interrupt flags 00177 LPC_EMAC->IntClear = 0xFFFF; 00178 //Enable desired EMAC interrupts 00179 LPC_EMAC->IntEnable = INT_TX_DONE | INT_RX_DONE; 00180 00181 //Set priority grouping (5 bits for pre-emption priority, no bits for subpriority) 00182 NVIC_SetPriorityGrouping(LPC175X_ETH_IRQ_PRIORITY_GROUPING); 00183 00184 //Configure Ethernet interrupt priority 00185 NVIC_SetPriority(ENET_IRQn, NVIC_EncodePriority(LPC175X_ETH_IRQ_PRIORITY_GROUPING, 00186 LPC175X_ETH_IRQ_GROUP_PRIORITY, LPC175X_ETH_IRQ_SUB_PRIORITY)); 00187 00188 //Enable transmission and reception 00189 LPC_EMAC->Command |= COMMAND_TX_ENABLE | COMMAND_RX_ENABLE; 00190 //Allow frames to be received 00191 LPC_EMAC->MAC1 |= MAC1_RECEIVE_ENABLE; 00192 00193 //Accept any packets from the upper layer 00194 osSetEvent(&interface->nicTxEvent); 00195 00196 //Successful initialization 00197 return NO_ERROR; 00198 } 00199 00200 00201 //MCB1758 evaluation board? 00202 #if defined(USE_MCB1758) 00203 00204 /** 00205 * @brief GPIO configuration 00206 * @param[in] interface Underlying network interface 00207 **/ 00208 00209 void lpc175xEthInitGpio(NetInterface *interface) 00210 { 00211 //Configure P1.0 (ENET_TXD0), P1.1 (ENET_TXD1), P1.4 (ENET_TX_EN), P1.8 (ENET_CRS), 00212 //P1.9 (ENET_RXD0), P1.10 (ENET_RXD1), P1.14 (RX_ER) and P1.15 (ENET_REF_CLK) 00213 LPC_PINCON->PINSEL2 &= ~(PINSEL2_P1_0_MASK | PINSEL2_P1_1_MASK | 00214 PINSEL2_P1_4_MASK | PINSEL2_P1_8_MASK | PINSEL2_P1_9_MASK | 00215 PINSEL2_P1_10_MASK | PINSEL2_P1_14_MASK | PINSEL2_P1_15_MASK); 00216 00217 LPC_PINCON->PINSEL2 |= PINSEL2_P1_0_ENET_TXD0 | PINSEL2_P1_1_ENET_TXD1 | 00218 PINSEL2_P1_4_ENET_TX_EN | PINSEL2_P1_8_ENET_CRS | PINSEL2_P1_9_ENET_RXD0 | 00219 PINSEL2_P1_10_ENET_RXD1 | PINSEL2_P1_14_ENET_RX_ER | PINSEL2_P1_15_ENET_REF_CLK; 00220 00221 //Configure P2.8 (ENET_MDC) and P2.9 (ENET_MDIO) as GPIOs 00222 LPC_PINCON->PINSEL4 &= ~(PINSEL4_P2_8_MASK | PINSEL4_P2_9_MASK); 00223 LPC_PINCON->PINSEL4 |= PINSEL4_P2_8_GPIO | PINSEL4_P2_9_GPIO; 00224 00225 //SMI software implementation to drive MDC and MDIO 00226 LPC175X_ETH_MDC_GPIO->FIOCLR = LPC175X_ETH_MDC_MASK; 00227 LPC175X_ETH_MDC_GPIO->FIODIR |= LPC175X_ETH_MDC_MASK; 00228 LPC175X_ETH_MDIO_GPIO->FIODIR &= ~LPC175X_ETH_MDIO_MASK; 00229 } 00230 00231 #endif 00232 00233 00234 /** 00235 * @brief Initialize TX and RX descriptors 00236 * @param[in] interface Underlying network interface 00237 **/ 00238 00239 void lpc175xEthInitDesc(NetInterface *interface) 00240 { 00241 uint_t i; 00242 00243 //Initialize TX descriptors 00244 for(i = 0; i < LPC175X_ETH_TX_BUFFER_COUNT; i++) 00245 { 00246 //Base address of the buffer containing transmit data 00247 txDesc[i].packet = (uint32_t) txBuffer[i]; 00248 //Transmit descriptor control word 00249 txDesc[i].control = 0; 00250 //Transmit status information word 00251 txStatus[i].info = 0; 00252 } 00253 00254 //Initialize RX descriptors 00255 for(i = 0; i < LPC175X_ETH_RX_BUFFER_COUNT; i++) 00256 { 00257 //Base address of the buffer for storing receive data 00258 rxDesc[i].packet = (uint32_t) rxBuffer[i]; 00259 //Receive descriptor control word 00260 rxDesc[i].control = RX_CTRL_INTERRUPT | (LPC175X_ETH_RX_BUFFER_SIZE - 1); 00261 //Receive status information word 00262 rxStatus[i].info = 0; 00263 //Receive status HashCRC word 00264 rxStatus[i].hashCrc = 0; 00265 } 00266 00267 //Initialize EMAC transmit descriptor registers 00268 LPC_EMAC->TxDescriptor = (uint32_t) txDesc; 00269 LPC_EMAC->TxStatus = (uint32_t) txStatus; 00270 LPC_EMAC->TxDescriptorNumber = LPC175X_ETH_TX_BUFFER_COUNT - 1; 00271 LPC_EMAC->TxProduceIndex = 0; 00272 00273 //Initialize EMAC receive descriptor registers 00274 LPC_EMAC->RxDescriptor = (uint32_t) rxDesc; 00275 LPC_EMAC->RxStatus = (uint32_t) rxStatus; 00276 LPC_EMAC->RxDescriptorNumber = LPC175X_ETH_RX_BUFFER_COUNT - 1; 00277 LPC_EMAC->RxConsumeIndex = 0; 00278 } 00279 00280 00281 /** 00282 * @brief LPC175x Ethernet MAC timer handler 00283 * 00284 * This routine is periodically called by the TCP/IP stack to 00285 * handle periodic operations such as polling the link state 00286 * 00287 * @param[in] interface Underlying network interface 00288 **/ 00289 00290 void lpc175xEthTick(NetInterface *interface) 00291 { 00292 //Handle periodic operations 00293 interface->phyDriver->tick(interface); 00294 } 00295 00296 00297 /** 00298 * @brief Enable interrupts 00299 * @param[in] interface Underlying network interface 00300 **/ 00301 00302 void lpc175xEthEnableIrq(NetInterface *interface) 00303 { 00304 //Enable Ethernet MAC interrupts 00305 NVIC_EnableIRQ(ENET_IRQn); 00306 //Enable Ethernet PHY interrupts 00307 interface->phyDriver->enableIrq(interface); 00308 } 00309 00310 00311 /** 00312 * @brief Disable interrupts 00313 * @param[in] interface Underlying network interface 00314 **/ 00315 00316 void lpc175xEthDisableIrq(NetInterface *interface) 00317 { 00318 //Disable Ethernet MAC interrupts 00319 NVIC_DisableIRQ(ENET_IRQn); 00320 //Disable Ethernet PHY interrupts 00321 interface->phyDriver->disableIrq(interface); 00322 } 00323 00324 00325 /** 00326 * @brief LPC175x Ethernet MAC interrupt service routine 00327 **/ 00328 00329 void ENET_IRQHandler(void) 00330 { 00331 uint_t i; 00332 bool_t flag; 00333 uint32_t status; 00334 00335 //Enter interrupt service routine 00336 osEnterIsr(); 00337 00338 //This flag will be set if a higher priority task must be woken 00339 flag = FALSE; 00340 00341 //Read interrupt status register 00342 status = LPC_EMAC->IntStatus; 00343 00344 //A packet has been transmitted? 00345 if(status & INT_TX_DONE) 00346 { 00347 //Clear TxDone interrupt flag 00348 LPC_EMAC->IntClear = INT_TX_DONE; 00349 00350 //Get the index of the next descriptor 00351 i = LPC_EMAC->TxProduceIndex + 1; 00352 00353 //Wrap around if necessary 00354 if(i >= LPC175X_ETH_TX_BUFFER_COUNT) 00355 i = 0; 00356 00357 //Check whether the TX buffer is available for writing 00358 if(i != LPC_EMAC->TxConsumeIndex) 00359 { 00360 //Notify the TCP/IP stack that the transmitter is ready to send 00361 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00362 } 00363 } 00364 00365 //A packet has been received? 00366 if(status & INT_RX_DONE) 00367 { 00368 //Disable RxDone interrupts 00369 LPC_EMAC->IntEnable &= ~INT_RX_DONE; 00370 00371 //Set event flag 00372 nicDriverInterface->nicEvent = TRUE; 00373 //Notify the TCP/IP stack of the event 00374 flag |= osSetEventFromIsr(&netEvent); 00375 } 00376 00377 //Leave interrupt service routine 00378 osExitIsr(flag); 00379 } 00380 00381 00382 /** 00383 * @brief LPC175x Ethernet MAC event handler 00384 * @param[in] interface Underlying network interface 00385 **/ 00386 00387 void lpc175xEthEventHandler(NetInterface *interface) 00388 { 00389 error_t error; 00390 00391 //Packet received? 00392 if(LPC_EMAC->IntStatus & INT_RX_DONE) 00393 { 00394 //Clear RxDone interrupt flag 00395 LPC_EMAC->IntClear = INT_RX_DONE; 00396 00397 //Process all pending packets 00398 do 00399 { 00400 //Read incoming packet 00401 error = lpc175xEthReceivePacket(interface); 00402 00403 //No more data in the receive buffer? 00404 } while(error != ERROR_BUFFER_EMPTY); 00405 } 00406 00407 //Re-enable TxDone and RxDone interrupts 00408 LPC_EMAC->IntEnable = INT_TX_DONE | INT_RX_DONE; 00409 } 00410 00411 00412 /** 00413 * @brief Send a packet 00414 * @param[in] interface Underlying network interface 00415 * @param[in] buffer Multi-part buffer containing the data to send 00416 * @param[in] offset Offset to the first data byte 00417 * @return Error code 00418 **/ 00419 00420 error_t lpc175xEthSendPacket(NetInterface *interface, 00421 const NetBuffer *buffer, size_t offset) 00422 { 00423 uint_t i; 00424 uint_t j; 00425 size_t length; 00426 00427 //Retrieve the length of the packet 00428 length = netBufferGetLength(buffer) - offset; 00429 00430 //Check the frame length 00431 if(!length) 00432 { 00433 //The transmitter can accept another packet 00434 osSetEvent(&interface->nicTxEvent); 00435 //We are done since the buffer is empty 00436 return NO_ERROR; 00437 } 00438 else if(length > LPC175X_ETH_TX_BUFFER_SIZE) 00439 { 00440 //The transmitter can accept another packet 00441 osSetEvent(&interface->nicTxEvent); 00442 //Report an error 00443 return ERROR_INVALID_LENGTH; 00444 } 00445 00446 //Get the index of the current descriptor 00447 i = LPC_EMAC->TxProduceIndex; 00448 //Get the index of the next descriptor 00449 j = i + 1; 00450 00451 //Wrap around if necessary 00452 if(j >= LPC175X_ETH_TX_BUFFER_COUNT) 00453 j = 0; 00454 00455 //Check whether the transmit descriptor array is full 00456 if(j == LPC_EMAC->TxConsumeIndex) 00457 return ERROR_FAILURE; 00458 00459 //Copy user data to the transmit buffer 00460 netBufferRead((uint8_t *) txDesc[i].packet, buffer, offset, length); 00461 00462 //Write the transmit control word 00463 txDesc[i].control = TX_CTRL_INTERRUPT | TX_CTRL_LAST | 00464 TX_CTRL_CRC | TX_CTRL_PAD | ((length - 1) & TX_CTRL_SIZE); 00465 00466 //Increment index and wrap around if necessary 00467 if(++i >= LPC175X_ETH_TX_BUFFER_COUNT) 00468 i = 0; 00469 00470 //Save the resulting value 00471 LPC_EMAC->TxProduceIndex = i; 00472 00473 //Get the index of the next descriptor 00474 j = i + 1; 00475 00476 //Wrap around if necessary 00477 if(j >= LPC175X_ETH_TX_BUFFER_COUNT) 00478 j = 0; 00479 00480 //Check whether the next buffer is available for writing 00481 if(j != LPC_EMAC->TxConsumeIndex) 00482 { 00483 //The transmitter can accept another packet 00484 osSetEvent(&interface->nicTxEvent); 00485 } 00486 00487 //Successful write operation 00488 return NO_ERROR; 00489 } 00490 00491 00492 /** 00493 * @brief Receive a packet 00494 * @param[in] interface Underlying network interface 00495 * @return Error code 00496 **/ 00497 00498 error_t lpc175xEthReceivePacket(NetInterface *interface) 00499 { 00500 error_t error; 00501 size_t n; 00502 uint_t i; 00503 00504 //Point to the current descriptor 00505 i = LPC_EMAC->RxConsumeIndex; 00506 00507 //Make sure the current buffer is available for reading 00508 if(i != LPC_EMAC->RxProduceIndex) 00509 { 00510 //Retrieve the length of the frame 00511 n = (rxStatus[i].info & RX_STATUS_SIZE) + 1; 00512 //Limit the number of data to read 00513 n = MIN(n, LPC175X_ETH_RX_BUFFER_SIZE); 00514 00515 //Pass the packet to the upper layer 00516 nicProcessPacket(interface, (uint8_t *) rxDesc[i].packet, n); 00517 00518 //Increment index and wrap around if necessary 00519 if(++i >= LPC175X_ETH_RX_BUFFER_COUNT) 00520 i = 0; 00521 00522 //Save the resulting value 00523 LPC_EMAC->RxConsumeIndex = i; 00524 00525 //Valid packet received 00526 error = NO_ERROR; 00527 } 00528 else 00529 { 00530 //No more data in the receive buffer 00531 error = ERROR_BUFFER_EMPTY; 00532 } 00533 00534 //Return status code 00535 return error; 00536 } 00537 00538 00539 /** 00540 * @brief Configure multicast MAC address filtering 00541 * @param[in] interface Underlying network interface 00542 * @return Error code 00543 **/ 00544 00545 error_t lpc175xEthSetMulticastFilter(NetInterface *interface) 00546 { 00547 uint_t i; 00548 uint_t k; 00549 uint32_t crc; 00550 uint32_t hashTable[2]; 00551 MacFilterEntry *entry; 00552 00553 //Debug message 00554 TRACE_DEBUG("Updating LPC175x hash table...\r\n"); 00555 00556 //Clear hash table 00557 hashTable[0] = 0; 00558 hashTable[1] = 0; 00559 00560 //The MAC filter table contains the multicast MAC addresses 00561 //to accept when receiving an Ethernet frame 00562 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00563 { 00564 //Point to the current entry 00565 entry = &interface->macMulticastFilter[i]; 00566 00567 //Valid entry? 00568 if(entry->refCount > 0) 00569 { 00570 //Compute CRC over the current MAC address 00571 crc = lpc175xEthCalcCrc(&entry->addr, sizeof(MacAddr)); 00572 //Bits [28:23] are used to form the hash 00573 k = (crc >> 23) & 0x3F; 00574 //Update hash table contents 00575 hashTable[k / 32] |= (1 << (k % 32)); 00576 } 00577 } 00578 00579 //Write the hash table 00580 LPC_EMAC->HashFilterL = hashTable[0]; 00581 LPC_EMAC->HashFilterH = hashTable[1]; 00582 00583 //Debug message 00584 TRACE_DEBUG(" HashFilterL = %08" PRIX32 "\r\n", LPC_EMAC->HashFilterL); 00585 TRACE_DEBUG(" HashFilterH = %08" PRIX32 "\r\n", LPC_EMAC->HashFilterH); 00586 00587 //Successful processing 00588 return NO_ERROR; 00589 } 00590 00591 00592 /** 00593 * @brief Adjust MAC configuration parameters for proper operation 00594 * @param[in] interface Underlying network interface 00595 * @return Error code 00596 **/ 00597 00598 error_t lpc175xEthUpdateMacConfig(NetInterface *interface) 00599 { 00600 //10BASE-T or 100BASE-TX operation mode? 00601 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00602 LPC_EMAC->SUPP = SUPP_SPEED; 00603 else 00604 LPC_EMAC->SUPP = 0; 00605 00606 //Half-duplex or full-duplex mode? 00607 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00608 { 00609 //The MAC operates in full-duplex mode 00610 LPC_EMAC->MAC2 |= MAC2_FULL_DUPLEX; 00611 LPC_EMAC->Command |= COMMAND_FULL_DUPLEX; 00612 //Configure Back-to-Back Inter-Packet Gap 00613 LPC_EMAC->IPGT = IPGT_FULL_DUPLEX; 00614 } 00615 else 00616 { 00617 //The MAC operates in half-duplex mode 00618 LPC_EMAC->MAC2 &= ~MAC2_FULL_DUPLEX; 00619 LPC_EMAC->Command &= ~COMMAND_FULL_DUPLEX; 00620 //Configure Back-to-Back Inter-Packet Gap 00621 LPC_EMAC->IPGT = IPGT_HALF_DUPLEX; 00622 } 00623 00624 //Successful processing 00625 return NO_ERROR; 00626 } 00627 00628 00629 /** 00630 * @brief Write PHY register 00631 * @param[in] phyAddr PHY address 00632 * @param[in] regAddr Register address 00633 * @param[in] data Register value 00634 **/ 00635 00636 void lpc175xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00637 { 00638 //Synchronization pattern 00639 lpc175xEthWriteSmi(SMI_SYNC, 32); 00640 //Start of frame 00641 lpc175xEthWriteSmi(SMI_START, 2); 00642 //Set up a write operation 00643 lpc175xEthWriteSmi(SMI_WRITE, 2); 00644 //Write PHY address 00645 lpc175xEthWriteSmi(phyAddr, 5); 00646 //Write register address 00647 lpc175xEthWriteSmi(regAddr, 5); 00648 //Turnaround 00649 lpc175xEthWriteSmi(SMI_TA, 2); 00650 //Write register value 00651 lpc175xEthWriteSmi(data, 16); 00652 //Release MDIO 00653 lpc175xEthReadSmi(1); 00654 } 00655 00656 00657 /** 00658 * @brief Read PHY register 00659 * @param[in] phyAddr PHY address 00660 * @param[in] regAddr Register address 00661 * @return Register value 00662 **/ 00663 00664 uint16_t lpc175xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00665 { 00666 uint16_t data; 00667 00668 //Synchronization pattern 00669 lpc175xEthWriteSmi(SMI_SYNC, 32); 00670 //Start of frame 00671 lpc175xEthWriteSmi(SMI_START, 2); 00672 //Set up a read operation 00673 lpc175xEthWriteSmi(SMI_READ, 2); 00674 //Write PHY address 00675 lpc175xEthWriteSmi(phyAddr, 5); 00676 //Write register address 00677 lpc175xEthWriteSmi(regAddr, 5); 00678 //Turnaround to avoid contention 00679 lpc175xEthReadSmi(1); 00680 //Read register value 00681 data = lpc175xEthReadSmi(16); 00682 //Force the PHY to release the MDIO pin 00683 lpc175xEthReadSmi(1); 00684 00685 //Return PHY register contents 00686 return data; 00687 } 00688 00689 00690 /** 00691 * @brief SMI write operation 00692 * @param[in] data Raw data to be written 00693 * @param[in] length Number of bits to be written 00694 **/ 00695 00696 void lpc175xEthWriteSmi(uint32_t data, uint_t length) 00697 { 00698 //Skip the most significant bits since they are meaningless 00699 data <<= 32 - length; 00700 00701 //Configure MDIO as an output 00702 LPC175X_ETH_MDIO_GPIO->FIODIR |= LPC175X_ETH_MDIO_MASK; 00703 00704 //Write the specified number of bits 00705 while(length--) 00706 { 00707 //Write MDIO 00708 if(data & 0x80000000) 00709 LPC175X_ETH_MDIO_GPIO->FIOSET = LPC175X_ETH_MDIO_MASK; 00710 else 00711 LPC175X_ETH_MDIO_GPIO->FIOCLR = LPC175X_ETH_MDIO_MASK; 00712 00713 //Assert MDC 00714 usleep(1); 00715 LPC175X_ETH_MDC_GPIO->FIOSET = LPC175X_ETH_MDC_MASK; 00716 //Deassert MDC 00717 usleep(1); 00718 LPC175X_ETH_MDC_GPIO->FIOCLR = LPC175X_ETH_MDC_MASK; 00719 00720 //Rotate data 00721 data <<= 1; 00722 } 00723 } 00724 00725 00726 /** 00727 * @brief SMI read operation 00728 * @param[in] length Number of bits to be read 00729 * @return Data resulting from the MDIO read operation 00730 **/ 00731 00732 uint32_t lpc175xEthReadSmi(uint_t length) 00733 { 00734 uint32_t data = 0; 00735 00736 //Configure MDIO as an input 00737 LPC175X_ETH_MDIO_GPIO->FIODIR &= ~LPC175X_ETH_MDIO_MASK; 00738 00739 //Read the specified number of bits 00740 while(length--) 00741 { 00742 //Rotate data 00743 data <<= 1; 00744 00745 //Assert MDC 00746 LPC175X_ETH_MDC_GPIO->FIOSET = LPC175X_ETH_MDC_MASK; 00747 usleep(1); 00748 //Deassert MDC 00749 LPC175X_ETH_MDC_GPIO->FIOCLR = LPC175X_ETH_MDC_MASK; 00750 usleep(1); 00751 00752 //Check MDIO state 00753 if(LPC175X_ETH_MDIO_GPIO->FIOPIN & LPC175X_ETH_MDIO_MASK) 00754 data |= 0x00000001; 00755 } 00756 00757 //Return the received data 00758 return data; 00759 } 00760 00761 00762 /** 00763 * @brief CRC calculation 00764 * @param[in] data Pointer to the data over which to calculate the CRC 00765 * @param[in] length Number of bytes to process 00766 * @return Resulting CRC value 00767 **/ 00768 00769 uint32_t lpc175xEthCalcCrc(const void *data, size_t length) 00770 { 00771 uint_t i; 00772 uint_t j; 00773 00774 //Point to the data over which to calculate the CRC 00775 const uint8_t *p = (uint8_t *) data; 00776 //CRC preset value 00777 uint32_t crc = 0xFFFFFFFF; 00778 00779 //Loop through data 00780 for(i = 0; i < length; i++) 00781 { 00782 //The message is processed bit by bit 00783 for(j = 0; j < 8; j++) 00784 { 00785 //Update CRC value 00786 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00787 crc = (crc << 1) ^ 0x04C11DB7; 00788 else 00789 crc = crc << 1; 00790 } 00791 } 00792 00793 //Return CRC value 00794 return crc; 00795 } 00796
Generated on Tue Jul 12 2022 17:10:14 by
1.7.2