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.
lpc178x_eth.c
00001 /** 00002 * @file lpc178x_eth.c 00003 * @brief LPC1786/88 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 "lpc177x_8x.h" 00034 #include "core/net.h" 00035 #include "drivers/lpc178x_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[LPC178X_ETH_TX_BUFFER_COUNT][LPC178X_ETH_TX_BUFFER_SIZE]; 00047 //Receive buffer 00048 #pragma data_alignment = 4 00049 static uint8_t rxBuffer[LPC178X_ETH_RX_BUFFER_COUNT][LPC178X_ETH_RX_BUFFER_SIZE]; 00050 //Transmit descriptors 00051 #pragma data_alignment = 4 00052 static Lpc178xTxDesc txDesc[LPC178X_ETH_TX_BUFFER_COUNT]; 00053 //Transmit status array 00054 #pragma data_alignment = 4 00055 static Lpc178xTxStatus txStatus[LPC178X_ETH_TX_BUFFER_COUNT]; 00056 //Receive descriptors 00057 #pragma data_alignment = 4 00058 static Lpc178xRxDesc rxDesc[LPC178X_ETH_RX_BUFFER_COUNT]; 00059 //Receive status array 00060 #pragma data_alignment = 8 00061 static Lpc178xRxStatus rxStatus[LPC178X_ETH_RX_BUFFER_COUNT]; 00062 00063 //Keil MDK-ARM or GCC compiler? 00064 #else 00065 00066 //Transmit buffer 00067 static uint8_t txBuffer[LPC178X_ETH_TX_BUFFER_COUNT][LPC178X_ETH_TX_BUFFER_SIZE] 00068 __attribute__((aligned(4))); 00069 //Receive buffer 00070 static uint8_t rxBuffer[LPC178X_ETH_RX_BUFFER_COUNT][LPC178X_ETH_RX_BUFFER_SIZE] 00071 __attribute__((aligned(4))); 00072 //Transmit descriptors 00073 static Lpc178xTxDesc txDesc[LPC178X_ETH_TX_BUFFER_COUNT] 00074 __attribute__((aligned(4))); 00075 //Transmit status array 00076 static Lpc178xTxStatus txStatus[LPC178X_ETH_TX_BUFFER_COUNT] 00077 __attribute__((aligned(4))); 00078 //Receive descriptors 00079 static Lpc178xRxDesc rxDesc[LPC178X_ETH_RX_BUFFER_COUNT] 00080 __attribute__((aligned(4))); 00081 //Receive status array 00082 static Lpc178xRxStatus rxStatus[LPC178X_ETH_RX_BUFFER_COUNT] 00083 __attribute__((aligned(8))); 00084 00085 #endif 00086 00087 00088 /** 00089 * @brief LPC178x Ethernet MAC driver 00090 **/ 00091 00092 const NicDriver lpc178xEthDriver = 00093 { 00094 NIC_TYPE_ETHERNET, 00095 ETH_MTU, 00096 lpc178xEthInit, 00097 lpc178xEthTick, 00098 lpc178xEthEnableIrq, 00099 lpc178xEthDisableIrq, 00100 lpc178xEthEventHandler, 00101 lpc178xEthSendPacket, 00102 lpc178xEthSetMulticastFilter, 00103 lpc178xEthUpdateMacConfig, 00104 lpc178xEthWritePhyReg, 00105 lpc178xEthReadPhyReg, 00106 TRUE, 00107 TRUE, 00108 TRUE, 00109 FALSE 00110 }; 00111 00112 00113 /** 00114 * @brief LPC178x Ethernet MAC initialization 00115 * @param[in] interface Underlying network interface 00116 * @return Error code 00117 **/ 00118 00119 error_t lpc178xEthInit(NetInterface *interface) 00120 { 00121 error_t error; 00122 00123 //Debug message 00124 TRACE_INFO("Initializing LPC178x 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 lpc178xEthInitGpio(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 //Configure MDC clock 00152 LPC_EMAC->MCFG = MCFG_CLOCK_SELECT_DIV48; 00153 //Reset MII management interface 00154 LPC_EMAC->MCFG |= MCFG_RESET_MII_MGMT; 00155 LPC_EMAC->MCFG &= ~MCFG_RESET_MII_MGMT; 00156 00157 //PHY transceiver initialization 00158 error = interface->phyDriver->init(interface); 00159 //Failed to initialize PHY transceiver? 00160 if(error) 00161 return error; 00162 00163 //Initialize TX and RX descriptor arrays 00164 lpc178xEthInitDesc(interface); 00165 00166 //Set the MAC address 00167 LPC_EMAC->SA0 = interface->macAddr.w[2]; 00168 LPC_EMAC->SA1 = interface->macAddr.w[1]; 00169 LPC_EMAC->SA2 = interface->macAddr.w[0]; 00170 00171 //Initialize hash table 00172 LPC_EMAC->HashFilterL = 0; 00173 LPC_EMAC->HashFilterH = 0; 00174 00175 //Configure the receive filter 00176 LPC_EMAC->RxFilterCtrl = RFC_ACCEPT_PERFECT_EN | 00177 RFC_ACCEPT_MULTICAST_HASH_EN | RFC_ACCEPT_BROADCAST_EN; 00178 00179 //Program the MAXF register with the maximum frame length to be accepted 00180 LPC_EMAC->MAXF = 1518; 00181 00182 //Reset EMAC interrupt flags 00183 LPC_EMAC->IntClear = 0xFFFF; 00184 //Enable desired EMAC interrupts 00185 LPC_EMAC->IntEnable = INT_TX_DONE | INT_RX_DONE; 00186 00187 //Set priority grouping (5 bits for pre-emption priority, no bits for subpriority) 00188 NVIC_SetPriorityGrouping(LPC178X_ETH_IRQ_PRIORITY_GROUPING); 00189 00190 //Configure Ethernet interrupt priority 00191 NVIC_SetPriority(ENET_IRQn, NVIC_EncodePriority(LPC178X_ETH_IRQ_PRIORITY_GROUPING, 00192 LPC178X_ETH_IRQ_GROUP_PRIORITY, LPC178X_ETH_IRQ_SUB_PRIORITY)); 00193 00194 //Enable transmission and reception 00195 LPC_EMAC->Command |= COMMAND_TX_ENABLE | COMMAND_RX_ENABLE; 00196 //Allow frames to be received 00197 LPC_EMAC->MAC1 |= MAC1_RECEIVE_ENABLE; 00198 00199 //Accept any packets from the upper layer 00200 osSetEvent(&interface->nicTxEvent); 00201 00202 //Successful initialization 00203 return NO_ERROR; 00204 } 00205 00206 00207 //LPC1788-32 Developer's Kit? 00208 #if defined(USE_LPC1788_32_DEV_KIT) 00209 00210 /** 00211 * @brief GPIO configuration 00212 * @param[in] interface Underlying network interface 00213 **/ 00214 00215 void lpc178xEthInitGpio(NetInterface *interface) 00216 { 00217 //Power up GPIO 00218 LPC_SC->PCONP |= PCONP_PCGPIO; 00219 00220 //Configure P1.0 (ENET_TXD0) 00221 LPC_IOCON->P1_0 = IOCON_SLEW | IOCON_FUNC_1; 00222 //Configure P1.1 (ENET_TXD1) 00223 LPC_IOCON->P1_1 = IOCON_SLEW | IOCON_FUNC_1; 00224 //Configure P1.4 (ENET_TX_EN) 00225 LPC_IOCON->P1_4 = IOCON_SLEW | IOCON_FUNC_1; 00226 //Configure P1.8 (ENET_CRS) 00227 LPC_IOCON->P1_8 = IOCON_SLEW | IOCON_FUNC_1; 00228 //Configure P1.9 (ENET_RXD0) 00229 LPC_IOCON->P1_9 = IOCON_SLEW | IOCON_FUNC_1; 00230 //Configure P1.10 (ENET_RXD1) 00231 LPC_IOCON->P1_10 = IOCON_SLEW | IOCON_FUNC_1; 00232 //Configure P1.14 (RX_ER) 00233 LPC_IOCON->P1_14 = IOCON_SLEW | IOCON_FUNC_1; 00234 //Configure P1.15 (ENET_REF_CLK) 00235 LPC_IOCON->P1_15 = IOCON_SLEW | IOCON_FUNC_1; 00236 //Configure P1.16 (ENET_MDC) 00237 LPC_IOCON->P1_16 = IOCON_MODE_PULL_UP | IOCON_FUNC_1; 00238 //Configure P1.17 (ENET_MDIO) 00239 LPC_IOCON->P1_17 = IOCON_MODE_PULL_UP | IOCON_FUNC_1; 00240 } 00241 00242 #endif 00243 00244 00245 /** 00246 * @brief Initialize TX and RX descriptors 00247 * @param[in] interface Underlying network interface 00248 **/ 00249 00250 void lpc178xEthInitDesc(NetInterface *interface) 00251 { 00252 uint_t i; 00253 00254 //Initialize TX descriptors 00255 for(i = 0; i < LPC178X_ETH_TX_BUFFER_COUNT; i++) 00256 { 00257 //Base address of the buffer containing transmit data 00258 txDesc[i].packet = (uint32_t) txBuffer[i]; 00259 //Transmit descriptor control word 00260 txDesc[i].control = 0; 00261 //Transmit status information word 00262 txStatus[i].info = 0; 00263 } 00264 00265 //Initialize RX descriptors 00266 for(i = 0; i < LPC178X_ETH_RX_BUFFER_COUNT; i++) 00267 { 00268 //Base address of the buffer for storing receive data 00269 rxDesc[i].packet = (uint32_t) rxBuffer[i]; 00270 //Receive descriptor control word 00271 rxDesc[i].control = RX_CTRL_INTERRUPT | (LPC178X_ETH_RX_BUFFER_SIZE - 1); 00272 //Receive status information word 00273 rxStatus[i].info = 0; 00274 //Receive status HashCRC word 00275 rxStatus[i].hashCrc = 0; 00276 } 00277 00278 //Initialize EMAC transmit descriptor registers 00279 LPC_EMAC->TxDescriptor = (uint32_t) txDesc; 00280 LPC_EMAC->TxStatus = (uint32_t) txStatus; 00281 LPC_EMAC->TxDescriptorNumber = LPC178X_ETH_TX_BUFFER_COUNT - 1; 00282 LPC_EMAC->TxProduceIndex = 0; 00283 00284 //Initialize EMAC receive descriptor registers 00285 LPC_EMAC->RxDescriptor = (uint32_t) rxDesc; 00286 LPC_EMAC->RxStatus = (uint32_t) rxStatus; 00287 LPC_EMAC->RxDescriptorNumber = LPC178X_ETH_RX_BUFFER_COUNT - 1; 00288 LPC_EMAC->RxConsumeIndex = 0; 00289 } 00290 00291 00292 /** 00293 * @brief LPC178x Ethernet MAC timer handler 00294 * 00295 * This routine is periodically called by the TCP/IP stack to 00296 * handle periodic operations such as polling the link state 00297 * 00298 * @param[in] interface Underlying network interface 00299 **/ 00300 00301 void lpc178xEthTick(NetInterface *interface) 00302 { 00303 //Handle periodic operations 00304 interface->phyDriver->tick(interface); 00305 } 00306 00307 00308 /** 00309 * @brief Enable interrupts 00310 * @param[in] interface Underlying network interface 00311 **/ 00312 00313 void lpc178xEthEnableIrq(NetInterface *interface) 00314 { 00315 //Enable Ethernet MAC interrupts 00316 NVIC_EnableIRQ(ENET_IRQn); 00317 //Enable Ethernet PHY interrupts 00318 interface->phyDriver->enableIrq(interface); 00319 } 00320 00321 00322 /** 00323 * @brief Disable interrupts 00324 * @param[in] interface Underlying network interface 00325 **/ 00326 00327 void lpc178xEthDisableIrq(NetInterface *interface) 00328 { 00329 //Disable Ethernet MAC interrupts 00330 NVIC_DisableIRQ(ENET_IRQn); 00331 //Disable Ethernet PHY interrupts 00332 interface->phyDriver->disableIrq(interface); 00333 } 00334 00335 00336 /** 00337 * @brief LPC178x Ethernet MAC interrupt service routine 00338 **/ 00339 00340 void ENET_IRQHandler(void) 00341 { 00342 uint_t i; 00343 bool_t flag; 00344 uint32_t status; 00345 00346 //Enter interrupt service routine 00347 osEnterIsr(); 00348 00349 //This flag will be set if a higher priority task must be woken 00350 flag = FALSE; 00351 00352 //Read interrupt status register 00353 status = LPC_EMAC->IntStatus; 00354 00355 //A packet has been transmitted? 00356 if(status & INT_TX_DONE) 00357 { 00358 //Clear TxDone interrupt flag 00359 LPC_EMAC->IntClear = INT_TX_DONE; 00360 00361 //Get the index of the next descriptor 00362 i = LPC_EMAC->TxProduceIndex + 1; 00363 00364 //Wrap around if necessary 00365 if(i >= LPC178X_ETH_TX_BUFFER_COUNT) 00366 i = 0; 00367 00368 //Check whether the TX buffer is available for writing 00369 if(i != LPC_EMAC->TxConsumeIndex) 00370 { 00371 //Notify the TCP/IP stack that the transmitter is ready to send 00372 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00373 } 00374 } 00375 00376 //A packet has been received? 00377 if(status & INT_RX_DONE) 00378 { 00379 //Disable RxDone interrupts 00380 LPC_EMAC->IntEnable &= ~INT_RX_DONE; 00381 00382 //Set event flag 00383 nicDriverInterface->nicEvent = TRUE; 00384 //Notify the TCP/IP stack of the event 00385 flag |= osSetEventFromIsr(&netEvent); 00386 } 00387 00388 //Leave interrupt service routine 00389 osExitIsr(flag); 00390 } 00391 00392 00393 /** 00394 * @brief LPC178x Ethernet MAC event handler 00395 * @param[in] interface Underlying network interface 00396 **/ 00397 00398 void lpc178xEthEventHandler(NetInterface *interface) 00399 { 00400 error_t error; 00401 00402 //Packet received? 00403 if(LPC_EMAC->IntStatus & INT_RX_DONE) 00404 { 00405 //Clear RxDone interrupt flag 00406 LPC_EMAC->IntClear = INT_RX_DONE; 00407 00408 //Process all pending packets 00409 do 00410 { 00411 //Read incoming packet 00412 error = lpc178xEthReceivePacket(interface); 00413 00414 //No more data in the receive buffer? 00415 } while(error != ERROR_BUFFER_EMPTY); 00416 } 00417 00418 //Re-enable TxDone and RxDone interrupts 00419 LPC_EMAC->IntEnable = INT_TX_DONE | INT_RX_DONE; 00420 } 00421 00422 00423 /** 00424 * @brief Send a packet 00425 * @param[in] interface Underlying network interface 00426 * @param[in] buffer Multi-part buffer containing the data to send 00427 * @param[in] offset Offset to the first data byte 00428 * @return Error code 00429 **/ 00430 00431 error_t lpc178xEthSendPacket(NetInterface *interface, 00432 const NetBuffer *buffer, size_t offset) 00433 { 00434 uint_t i; 00435 uint_t j; 00436 size_t length; 00437 00438 //Retrieve the length of the packet 00439 length = netBufferGetLength(buffer) - offset; 00440 00441 //Check the frame length 00442 if(!length) 00443 { 00444 //The transmitter can accept another packet 00445 osSetEvent(&interface->nicTxEvent); 00446 //We are done since the buffer is empty 00447 return NO_ERROR; 00448 } 00449 else if(length > LPC178X_ETH_TX_BUFFER_SIZE) 00450 { 00451 //The transmitter can accept another packet 00452 osSetEvent(&interface->nicTxEvent); 00453 //Report an error 00454 return ERROR_INVALID_LENGTH; 00455 } 00456 00457 //Get the index of the current descriptor 00458 i = LPC_EMAC->TxProduceIndex; 00459 //Get the index of the next descriptor 00460 j = i + 1; 00461 00462 //Wrap around if necessary 00463 if(j >= LPC178X_ETH_TX_BUFFER_COUNT) 00464 j = 0; 00465 00466 //Check whether the transmit descriptor array is full 00467 if(j == LPC_EMAC->TxConsumeIndex) 00468 return ERROR_FAILURE; 00469 00470 //Copy user data to the transmit buffer 00471 netBufferRead((uint8_t *) txDesc[i].packet, buffer, offset, length); 00472 00473 //Write the transmit control word 00474 txDesc[i].control = TX_CTRL_INTERRUPT | TX_CTRL_LAST | 00475 TX_CTRL_CRC | TX_CTRL_PAD | ((length - 1) & TX_CTRL_SIZE); 00476 00477 //Increment index and wrap around if necessary 00478 if(++i >= LPC178X_ETH_TX_BUFFER_COUNT) 00479 i = 0; 00480 00481 //Save the resulting value 00482 LPC_EMAC->TxProduceIndex = i; 00483 00484 //Get the index of the next descriptor 00485 j = i + 1; 00486 00487 //Wrap around if necessary 00488 if(j >= LPC178X_ETH_TX_BUFFER_COUNT) 00489 j = 0; 00490 00491 //Check whether the next buffer is available for writing 00492 if(j != LPC_EMAC->TxConsumeIndex) 00493 { 00494 //The transmitter can accept another packet 00495 osSetEvent(&interface->nicTxEvent); 00496 } 00497 00498 //Successful write operation 00499 return NO_ERROR; 00500 } 00501 00502 00503 /** 00504 * @brief Receive a packet 00505 * @param[in] interface Underlying network interface 00506 * @return Error code 00507 **/ 00508 00509 error_t lpc178xEthReceivePacket(NetInterface *interface) 00510 { 00511 error_t error; 00512 size_t n; 00513 uint_t i; 00514 00515 //Point to the current descriptor 00516 i = LPC_EMAC->RxConsumeIndex; 00517 00518 //Make sure the current buffer is available for reading 00519 if(i != LPC_EMAC->RxProduceIndex) 00520 { 00521 //Retrieve the length of the frame 00522 n = (rxStatus[i].info & RX_STATUS_SIZE) + 1; 00523 //Limit the number of data to read 00524 n = MIN(n, LPC178X_ETH_RX_BUFFER_SIZE); 00525 00526 //Pass the packet to the upper layer 00527 nicProcessPacket(interface, (uint8_t *) rxDesc[i].packet, n); 00528 00529 //Increment index and wrap around if necessary 00530 if(++i >= LPC178X_ETH_RX_BUFFER_COUNT) 00531 i = 0; 00532 00533 //Save the resulting value 00534 LPC_EMAC->RxConsumeIndex = i; 00535 00536 //Valid packet received 00537 error = NO_ERROR; 00538 } 00539 else 00540 { 00541 //No more data in the receive buffer 00542 error = ERROR_BUFFER_EMPTY; 00543 } 00544 00545 //Return status code 00546 return error; 00547 } 00548 00549 00550 /** 00551 * @brief Configure multicast MAC address filtering 00552 * @param[in] interface Underlying network interface 00553 * @return Error code 00554 **/ 00555 00556 error_t lpc178xEthSetMulticastFilter(NetInterface *interface) 00557 { 00558 uint_t i; 00559 uint_t k; 00560 uint32_t crc; 00561 uint32_t hashTable[2]; 00562 MacFilterEntry *entry; 00563 00564 //Debug message 00565 TRACE_DEBUG("Updating LPC178x hash table...\r\n"); 00566 00567 //Clear hash table 00568 hashTable[0] = 0; 00569 hashTable[1] = 0; 00570 00571 //The MAC filter table contains the multicast MAC addresses 00572 //to accept when receiving an Ethernet frame 00573 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00574 { 00575 //Point to the current entry 00576 entry = &interface->macMulticastFilter[i]; 00577 00578 //Valid entry? 00579 if(entry->refCount > 0) 00580 { 00581 //Compute CRC over the current MAC address 00582 crc = lpc178xEthCalcCrc(&entry->addr, sizeof(MacAddr)); 00583 //Bits [28:23] are used to form the hash 00584 k = (crc >> 23) & 0x3F; 00585 //Update hash table contents 00586 hashTable[k / 32] |= (1 << (k % 32)); 00587 } 00588 } 00589 00590 //Write the hash table 00591 LPC_EMAC->HashFilterL = hashTable[0]; 00592 LPC_EMAC->HashFilterH = hashTable[1]; 00593 00594 //Debug message 00595 TRACE_DEBUG(" HashFilterL = %08" PRIX32 "\r\n", LPC_EMAC->HashFilterL); 00596 TRACE_DEBUG(" HashFilterH = %08" PRIX32 "\r\n", LPC_EMAC->HashFilterH); 00597 00598 //Successful processing 00599 return NO_ERROR; 00600 } 00601 00602 00603 /** 00604 * @brief Adjust MAC configuration parameters for proper operation 00605 * @param[in] interface Underlying network interface 00606 * @return Error code 00607 **/ 00608 00609 error_t lpc178xEthUpdateMacConfig(NetInterface *interface) 00610 { 00611 //10BASE-T or 100BASE-TX operation mode? 00612 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00613 LPC_EMAC->SUPP = SUPP_SPEED; 00614 else 00615 LPC_EMAC->SUPP = 0; 00616 00617 //Half-duplex or full-duplex mode? 00618 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00619 { 00620 //The MAC operates in full-duplex mode 00621 LPC_EMAC->MAC2 |= MAC2_FULL_DUPLEX; 00622 LPC_EMAC->Command |= COMMAND_FULL_DUPLEX; 00623 //Configure Back-to-Back Inter-Packet Gap 00624 LPC_EMAC->IPGT = IPGT_FULL_DUPLEX; 00625 } 00626 else 00627 { 00628 //The MAC operates in half-duplex mode 00629 LPC_EMAC->MAC2 &= ~MAC2_FULL_DUPLEX; 00630 LPC_EMAC->Command &= ~COMMAND_FULL_DUPLEX; 00631 //Configure Back-to-Back Inter-Packet Gap 00632 LPC_EMAC->IPGT = IPGT_HALF_DUPLEX; 00633 } 00634 00635 //Successful processing 00636 return NO_ERROR; 00637 } 00638 00639 00640 /** 00641 * @brief Write PHY register 00642 * @param[in] phyAddr PHY address 00643 * @param[in] regAddr Register address 00644 * @param[in] data Register value 00645 **/ 00646 00647 void lpc178xEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00648 { 00649 //Clear MCMD register 00650 LPC_EMAC->MCMD = 0; 00651 00652 //PHY address 00653 LPC_EMAC->MADR = (phyAddr << 8) & MADR_PHY_ADDRESS; 00654 //Register address 00655 LPC_EMAC->MADR |= regAddr & MADR_REGISTER_ADDRESS; 00656 //Data to be written in the PHY register 00657 LPC_EMAC->MWTD = data & MWTD_WRITE_DATA; 00658 00659 //Wait for the write to complete 00660 while(LPC_EMAC->MIND & MIND_BUSY); 00661 } 00662 00663 00664 /** 00665 * @brief Read PHY register 00666 * @param[in] phyAddr PHY address 00667 * @param[in] regAddr Register address 00668 * @return Register value 00669 **/ 00670 00671 uint16_t lpc178xEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00672 { 00673 //PHY address 00674 LPC_EMAC->MADR = (phyAddr << 8) & MADR_PHY_ADDRESS; 00675 //Register address 00676 LPC_EMAC->MADR |= regAddr & MADR_REGISTER_ADDRESS; 00677 00678 //Start a read operation 00679 LPC_EMAC->MCMD = MCMD_READ; 00680 //Wait for the read to complete 00681 while(LPC_EMAC->MIND & MIND_BUSY); 00682 //Clear MCMD register 00683 LPC_EMAC->MCMD = 0; 00684 00685 //Return PHY register contents 00686 return LPC_EMAC->MRDD & MRDD_READ_DATA; 00687 } 00688 00689 00690 /** 00691 * @brief CRC calculation 00692 * @param[in] data Pointer to the data over which to calculate the CRC 00693 * @param[in] length Number of bytes to process 00694 * @return Resulting CRC value 00695 **/ 00696 00697 uint32_t lpc178xEthCalcCrc(const void *data, size_t length) 00698 { 00699 uint_t i; 00700 uint_t j; 00701 00702 //Point to the data over which to calculate the CRC 00703 const uint8_t *p = (uint8_t *) data; 00704 //CRC preset value 00705 uint32_t crc = 0xFFFFFFFF; 00706 00707 //Loop through data 00708 for(i = 0; i < length; i++) 00709 { 00710 //The message is processed bit by bit 00711 for(j = 0; j < 8; j++) 00712 { 00713 //Update CRC value 00714 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00715 crc = (crc << 1) ^ 0x04C11DB7; 00716 else 00717 crc = crc << 1; 00718 } 00719 } 00720 00721 //Return CRC value 00722 return crc; 00723 } 00724
Generated on Tue Jul 12 2022 17:10:14 by
1.7.2