Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
lpc23xx_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file lpc23xx_eth.c 00003 * @brief LPC2300 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 "lpc23xx.h" 00034 #include "core/net.h" 00035 #include "drivers/lpc23xx_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[LPC23XX_ETH_TX_BUFFER_COUNT][LPC23XX_ETH_TX_BUFFER_SIZE]; 00047 //Receive buffer 00048 #pragma data_alignment = 4 00049 static uint8_t rxBuffer[LPC23XX_ETH_RX_BUFFER_COUNT][LPC23XX_ETH_RX_BUFFER_SIZE]; 00050 //Transmit descriptors 00051 #pragma data_alignment = 4 00052 static Lpc23xxTxDesc txDesc[LPC23XX_ETH_TX_BUFFER_COUNT]; 00053 //Transmit status array 00054 #pragma data_alignment = 4 00055 static Lpc23xxTxStatus txStatus[LPC23XX_ETH_TX_BUFFER_COUNT]; 00056 //Receive descriptors 00057 #pragma data_alignment = 4 00058 static Lpc23xxRxDesc rxDesc[LPC23XX_ETH_RX_BUFFER_COUNT]; 00059 //Receive status array 00060 #pragma data_alignment = 8 00061 static Lpc23xxRxStatus rxStatus[LPC23XX_ETH_RX_BUFFER_COUNT]; 00062 00063 //Keil MDK-ARM or GCC compiler? 00064 #else 00065 00066 //Transmit buffer 00067 static uint8_t txBuffer[LPC23XX_ETH_TX_BUFFER_COUNT][LPC23XX_ETH_TX_BUFFER_SIZE] 00068 __attribute__((aligned(4))); 00069 //Receive buffer 00070 static uint8_t rxBuffer[LPC23XX_ETH_RX_BUFFER_COUNT][LPC23XX_ETH_RX_BUFFER_SIZE] 00071 __attribute__((aligned(4))); 00072 //Transmit descriptors 00073 static Lpc23xxTxDesc txDesc[LPC23XX_ETH_TX_BUFFER_COUNT] 00074 __attribute__((aligned(4))); 00075 //Transmit status array 00076 static Lpc23xxTxStatus txStatus[LPC23XX_ETH_TX_BUFFER_COUNT] 00077 __attribute__((aligned(4))); 00078 //Receive descriptors 00079 static Lpc23xxRxDesc rxDesc[LPC23XX_ETH_RX_BUFFER_COUNT] 00080 __attribute__((aligned(4))); 00081 //Receive status array 00082 static Lpc23xxRxStatus rxStatus[LPC23XX_ETH_RX_BUFFER_COUNT] 00083 __attribute__((aligned(8))); 00084 00085 #endif 00086 00087 00088 /** 00089 * @brief LPC23xx Ethernet MAC driver 00090 **/ 00091 00092 const NicDriver lpc23xxEthDriver = 00093 { 00094 NIC_TYPE_ETHERNET, 00095 ETH_MTU, 00096 lpc23xxEthInit, 00097 lpc23xxEthTick, 00098 lpc23xxEthEnableIrq, 00099 lpc23xxEthDisableIrq, 00100 lpc23xxEthEventHandler, 00101 lpc23xxEthSendPacket, 00102 lpc23xxEthSetMulticastFilter, 00103 lpc23xxEthUpdateMacConfig, 00104 lpc23xxEthWritePhyReg, 00105 lpc23xxEthReadPhyReg, 00106 TRUE, 00107 TRUE, 00108 TRUE, 00109 FALSE 00110 }; 00111 00112 00113 /** 00114 * @brief LPC23xx Ethernet MAC initialization 00115 * @param[in] interface Underlying network interface 00116 * @return Error code 00117 **/ 00118 00119 error_t lpc23xxEthInit(NetInterface *interface) 00120 { 00121 error_t error; 00122 00123 //Debug message 00124 TRACE_INFO("Initializing LPC23xx Ethernet MAC...\r\n"); 00125 00126 //Save underlying network interface 00127 nicDriverInterface = interface; 00128 00129 //Power up EMAC controller 00130 PCONP |= PCONP_PCENET; 00131 00132 //GPIO configuration 00133 lpc23xxEthInitGpio(interface); 00134 00135 //Reset host registers, transmit datapath and receive datapath 00136 MAC_COMMAND = COMMAND_RX_RESET | COMMAND_TX_RESET | COMMAND_REG_RESET; 00137 00138 //Reset EMAC controller 00139 MAC_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 MAC_MAC1 = 0; 00144 MAC_MAC2 = MAC2_PAD_CRC_ENABLE | MAC2_CRC_ENABLE; 00145 MAC_IPGR = IPGR_DEFAULT_VALUE; 00146 MAC_CLRT = CLRT_DEFAULT_VALUE; 00147 00148 //Select RMII mode 00149 MAC_COMMAND = COMMAND_RMII; 00150 00151 //Configure MDC clock 00152 MAC_MCFG = MCFG_CLOCK_SELECT_DIV28; 00153 //Reset MII management interface 00154 MAC_MCFG |= MCFG_RESET_MII_MGMT; 00155 MAC_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 lpc23xxEthInitDesc(interface); 00165 00166 //Set the MAC address 00167 MAC_SA0 = interface->macAddr.w[2]; 00168 MAC_SA1 = interface->macAddr.w[1]; 00169 MAC_SA2 = interface->macAddr.w[0]; 00170 00171 //Initialize hash table 00172 MAC_HASHFILTERL = 0; 00173 MAC_HASHFILTERH = 0; 00174 00175 //Configure the receive filter 00176 MAC_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 MAC_MAXF = 1518; 00181 00182 //Reset EMAC interrupt flags 00183 MAC_INTCLEAR = 0xFFFF; 00184 //Enable desired EMAC interrupts 00185 MAC_INTENABLE = INT_TX_DONE | INT_RX_DONE; 00186 00187 //The interrupt request is assigned to the IRQ category 00188 VICIntSelect &= ~VIC_INT_ETHERNET; 00189 //Register interrupt handler 00190 VICVectAddr21 = (uint32_t) lpc23xxEthIrqHandler; 00191 //Configure interrupt priority 00192 VICVectPriority21 = LPC23XX_ETH_IRQ_PRIORITY; 00193 00194 //Enable transmission and reception 00195 MAC_COMMAND |= COMMAND_TX_ENABLE | COMMAND_RX_ENABLE; 00196 //Allow frames to be received 00197 MAC_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 //LPC2378-STK evaluation board? 00208 #if defined(USE_LPC2378_STK) 00209 00210 /** 00211 * @brief GPIO configuration 00212 * @param[in] interface Underlying network interface 00213 **/ 00214 00215 void lpc23xxEthInitGpio(NetInterface *interface) 00216 { 00217 //Configure P1.0 (ENET_TXD0), P1.1 (ENET_TXD1), P1.4 (ENET_TX_EN), P1.8 (ENET_CRS), 00218 //P1.9 (ENET_RXD0), P1.10 (ENET_RXD1), P1.14 (RX_ER) and P1.15 (ENET_REF_CLK) 00219 PINSEL2 &= ~(PINSEL2_P1_0_MASK | PINSEL2_P1_1_MASK | 00220 PINSEL2_P1_4_MASK | PINSEL2_P1_8_MASK | PINSEL2_P1_9_MASK | 00221 PINSEL2_P1_10_MASK | PINSEL2_P1_14_MASK | PINSEL2_P1_15_MASK); 00222 00223 PINSEL2 |= PINSEL2_P1_0_ENET_TXD0 | PINSEL2_P1_1_ENET_TXD1 | 00224 PINSEL2_P1_4_ENET_TX_EN | PINSEL2_P1_8_ENET_CRS | PINSEL2_P1_9_ENET_RXD0 | 00225 PINSEL2_P1_10_ENET_RXD1 | PINSEL2_P1_14_ENET_RX_ER | PINSEL2_P1_15_ENET_REF_CLK; 00226 00227 //Configure P1.16 (ENET_MDC) and P1.17 (ENET_MDIO) 00228 PINSEL3 &= ~(PINSEL3_P1_16_MASK | PINSEL3_P1_17_MASK); 00229 PINSEL3 |= PINSEL3_P1_16_ENET_MDC | PINSEL3_P1_17_ENET_MDIO; 00230 } 00231 00232 #endif 00233 00234 00235 /** 00236 * @brief Initialize TX and RX descriptors 00237 * @param[in] interface Underlying network interface 00238 **/ 00239 00240 void lpc23xxEthInitDesc(NetInterface *interface) 00241 { 00242 uint_t i; 00243 00244 //Initialize TX descriptors 00245 for(i = 0; i < LPC23XX_ETH_TX_BUFFER_COUNT; i++) 00246 { 00247 //Base address of the buffer containing transmit data 00248 txDesc[i].packet = (uint32_t) txBuffer[i]; 00249 //Transmit descriptor control word 00250 txDesc[i].control = 0; 00251 //Transmit status information word 00252 txStatus[i].info = 0; 00253 } 00254 00255 //Initialize RX descriptors 00256 for(i = 0; i < LPC23XX_ETH_RX_BUFFER_COUNT; i++) 00257 { 00258 //Base address of the buffer for storing receive data 00259 rxDesc[i].packet = (uint32_t) rxBuffer[i]; 00260 //Receive descriptor control word 00261 rxDesc[i].control = RX_CTRL_INTERRUPT | (LPC23XX_ETH_RX_BUFFER_SIZE - 1); 00262 //Receive status information word 00263 rxStatus[i].info = 0; 00264 //Receive status HashCRC word 00265 rxStatus[i].hashCrc = 0; 00266 } 00267 00268 //Initialize EMAC transmit descriptor registers 00269 MAC_TXDESCRIPTOR = (uint32_t) txDesc; 00270 MAC_TXSTATUS = (uint32_t) txStatus; 00271 MAC_TXDESCRIPTORNUM = LPC23XX_ETH_TX_BUFFER_COUNT - 1; 00272 MAC_TXPRODUCEINDEX = 0; 00273 00274 //Initialize EMAC receive descriptor registers 00275 MAC_RXDESCRIPTOR = (uint32_t) rxDesc; 00276 MAC_RXSTATUS = (uint32_t) rxStatus; 00277 MAC_RXDESCRIPTORNUM = LPC23XX_ETH_RX_BUFFER_COUNT - 1; 00278 MAC_RXCONSUMEINDEX = 0; 00279 } 00280 00281 00282 /** 00283 * @brief LPC23xx Ethernet MAC timer handler 00284 * 00285 * This routine is periodically called by the TCP/IP stack to 00286 * handle periodic operations such as polling the link state 00287 * 00288 * @param[in] interface Underlying network interface 00289 **/ 00290 00291 void lpc23xxEthTick(NetInterface *interface) 00292 { 00293 //Handle periodic operations 00294 interface->phyDriver->tick(interface); 00295 } 00296 00297 00298 /** 00299 * @brief Enable interrupts 00300 * @param[in] interface Underlying network interface 00301 **/ 00302 00303 void lpc23xxEthEnableIrq(NetInterface *interface) 00304 { 00305 //Enable Ethernet MAC interrupts 00306 VICIntEnable = VIC_INT_ETHERNET; 00307 //Enable Ethernet PHY interrupts 00308 interface->phyDriver->enableIrq(interface); 00309 } 00310 00311 00312 /** 00313 * @brief Disable interrupts 00314 * @param[in] interface Underlying network interface 00315 **/ 00316 00317 void lpc23xxEthDisableIrq(NetInterface *interface) 00318 { 00319 //Disable Ethernet MAC interrupts 00320 VICIntEnClr = VIC_INT_ETHERNET; 00321 //Disable Ethernet PHY interrupts 00322 interface->phyDriver->disableIrq(interface); 00323 } 00324 00325 00326 /** 00327 * @brief LPC23xx Ethernet MAC interrupt service routine 00328 **/ 00329 00330 __irq void lpc23xxEthIrqHandler(void) 00331 { 00332 uint_t i; 00333 bool_t flag; 00334 uint32_t status; 00335 00336 //Enter interrupt service routine 00337 osEnterIsr(); 00338 00339 //This flag will be set if a higher priority task must be woken 00340 flag = FALSE; 00341 00342 //Read interrupt status register 00343 status = MAC_INTSTATUS; 00344 00345 //A packet has been transmitted? 00346 if(status & INT_TX_DONE) 00347 { 00348 //Clear TxDone interrupt flag 00349 MAC_INTCLEAR = INT_TX_DONE; 00350 00351 //Get the index of the next descriptor 00352 i = MAC_TXPRODUCEINDEX + 1; 00353 00354 //Wrap around if necessary 00355 if(i >= LPC23XX_ETH_TX_BUFFER_COUNT) 00356 i = 0; 00357 00358 //Check whether the TX buffer is available for writing 00359 if(i != MAC_TXCONSUMEINDEX) 00360 { 00361 //Notify the TCP/IP stack that the transmitter is ready to send 00362 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00363 } 00364 } 00365 00366 //A packet has been received? 00367 if(status & INT_RX_DONE) 00368 { 00369 //Disable RxDone interrupts 00370 MAC_INTENABLE &= ~INT_RX_DONE; 00371 00372 //Set event flag 00373 nicDriverInterface->nicEvent = TRUE; 00374 //Notify the TCP/IP stack of the event 00375 flag |= osSetEventFromIsr(&netEvent); 00376 } 00377 00378 //Leave interrupt service routine 00379 osExitIsr(flag); 00380 } 00381 00382 00383 /** 00384 * @brief LPC23xx Ethernet MAC event handler 00385 * @param[in] interface Underlying network interface 00386 **/ 00387 00388 void lpc23xxEthEventHandler(NetInterface *interface) 00389 { 00390 error_t error; 00391 00392 //Packet received? 00393 if(MAC_INTSTATUS & INT_RX_DONE) 00394 { 00395 //Clear RxDone interrupt flag 00396 MAC_INTCLEAR = INT_RX_DONE; 00397 00398 //Process all pending packets 00399 do 00400 { 00401 //Read incoming packet 00402 error = lpc23xxEthReceivePacket(interface); 00403 00404 //No more data in the receive buffer? 00405 } while(error != ERROR_BUFFER_EMPTY); 00406 } 00407 00408 //Re-enable TxDone and RxDone interrupts 00409 MAC_INTENABLE = INT_TX_DONE | INT_RX_DONE; 00410 } 00411 00412 00413 /** 00414 * @brief Send a packet 00415 * @param[in] interface Underlying network interface 00416 * @param[in] buffer Multi-part buffer containing the data to send 00417 * @param[in] offset Offset to the first data byte 00418 * @return Error code 00419 **/ 00420 00421 error_t lpc23xxEthSendPacket(NetInterface *interface, 00422 const NetBuffer *buffer, size_t offset) 00423 { 00424 uint_t i; 00425 uint_t j; 00426 size_t length; 00427 00428 //Retrieve the length of the packet 00429 length = netBufferGetLength(buffer) - offset; 00430 00431 //Check the frame length 00432 if(!length) 00433 { 00434 //The transmitter can accept another packet 00435 osSetEvent(&interface->nicTxEvent); 00436 //We are done since the buffer is empty 00437 return NO_ERROR; 00438 } 00439 else if(length > LPC23XX_ETH_TX_BUFFER_SIZE) 00440 { 00441 //The transmitter can accept another packet 00442 osSetEvent(&interface->nicTxEvent); 00443 //Report an error 00444 return ERROR_INVALID_LENGTH; 00445 } 00446 00447 //Get the index of the current descriptor 00448 i = MAC_TXPRODUCEINDEX; 00449 //Get the index of the next descriptor 00450 j = i + 1; 00451 00452 //Wrap around if necessary 00453 if(j >= LPC23XX_ETH_TX_BUFFER_COUNT) 00454 j = 0; 00455 00456 //Check whether the transmit descriptor array is full 00457 if(j == MAC_TXCONSUMEINDEX) 00458 return ERROR_FAILURE; 00459 00460 //Copy user data to the transmit buffer 00461 netBufferRead((uint8_t *) txDesc[i].packet, buffer, offset, length); 00462 00463 //Write the transmit control word 00464 txDesc[i].control = TX_CTRL_INTERRUPT | TX_CTRL_LAST | 00465 TX_CTRL_CRC | TX_CTRL_PAD | ((length - 1) & TX_CTRL_SIZE); 00466 00467 //Increment index and wrap around if necessary 00468 if(++i >= LPC23XX_ETH_TX_BUFFER_COUNT) 00469 i = 0; 00470 00471 //Save the resulting value 00472 MAC_TXPRODUCEINDEX = i; 00473 00474 //Get the index of the next descriptor 00475 j = i + 1; 00476 00477 //Wrap around if necessary 00478 if(j >= LPC23XX_ETH_TX_BUFFER_COUNT) 00479 j = 0; 00480 00481 //Check whether the next buffer is available for writing 00482 if(j != MAC_TXCONSUMEINDEX) 00483 { 00484 //The transmitter can accept another packet 00485 osSetEvent(&interface->nicTxEvent); 00486 } 00487 00488 //Successful write operation 00489 return NO_ERROR; 00490 } 00491 00492 00493 /** 00494 * @brief Receive a packet 00495 * @param[in] interface Underlying network interface 00496 * @return Error code 00497 **/ 00498 00499 error_t lpc23xxEthReceivePacket(NetInterface *interface) 00500 { 00501 error_t error; 00502 size_t n; 00503 uint_t i; 00504 00505 //Point to the current descriptor 00506 i = MAC_RXCONSUMEINDEX; 00507 00508 //Make sure the current buffer is available for reading 00509 if(i != MAC_RXPRODUCEINDEX) 00510 { 00511 //Retrieve the length of the frame 00512 n = (rxStatus[i].info & RX_STATUS_SIZE) + 1; 00513 //Limit the number of data to read 00514 n = MIN(n, LPC23XX_ETH_RX_BUFFER_SIZE); 00515 00516 //Pass the packet to the upper layer 00517 nicProcessPacket(interface, (uint8_t *) rxDesc[i].packet, n); 00518 00519 //Increment index and wrap around if necessary 00520 if(++i >= LPC23XX_ETH_RX_BUFFER_COUNT) 00521 i = 0; 00522 00523 //Save the resulting value 00524 MAC_RXCONSUMEINDEX = i; 00525 00526 //Valid packet received 00527 error = NO_ERROR; 00528 } 00529 else 00530 { 00531 //No more data in the receive buffer 00532 error = ERROR_BUFFER_EMPTY; 00533 } 00534 00535 //Return status code 00536 return error; 00537 } 00538 00539 00540 /** 00541 * @brief Configure multicast MAC address filtering 00542 * @param[in] interface Underlying network interface 00543 * @return Error code 00544 **/ 00545 00546 error_t lpc23xxEthSetMulticastFilter(NetInterface *interface) 00547 { 00548 uint_t i; 00549 uint_t k; 00550 uint32_t crc; 00551 uint32_t hashTable[2]; 00552 MacFilterEntry *entry; 00553 00554 //Debug message 00555 TRACE_DEBUG("Updating LPC23xx hash table...\r\n"); 00556 00557 //Clear hash table 00558 hashTable[0] = 0; 00559 hashTable[1] = 0; 00560 00561 //The MAC filter table contains the multicast MAC addresses 00562 //to accept when receiving an Ethernet frame 00563 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00564 { 00565 //Point to the current entry 00566 entry = &interface->macMulticastFilter[i]; 00567 00568 //Valid entry? 00569 if(entry->refCount > 0) 00570 { 00571 //Compute CRC over the current MAC address 00572 crc = lpc23xxEthCalcCrc(&entry->addr, sizeof(MacAddr)); 00573 //Bits [28:23] are used to form the hash 00574 k = (crc >> 23) & 0x3F; 00575 //Update hash table contents 00576 hashTable[k / 32] |= (1 << (k % 32)); 00577 } 00578 } 00579 00580 //Write the hash table 00581 MAC_HASHFILTERL = hashTable[0]; 00582 MAC_HASHFILTERH = hashTable[1]; 00583 00584 //Debug message 00585 TRACE_DEBUG(" HashFilterL = %08" PRIX32 "\r\n", MAC_HASHFILTERL); 00586 TRACE_DEBUG(" HashFilterH = %08" PRIX32 "\r\n", MAC_HASHFILTERH); 00587 00588 //Successful processing 00589 return NO_ERROR; 00590 } 00591 00592 00593 /** 00594 * @brief Adjust MAC configuration parameters for proper operation 00595 * @param[in] interface Underlying network interface 00596 * @return Error code 00597 **/ 00598 00599 error_t lpc23xxEthUpdateMacConfig(NetInterface *interface) 00600 { 00601 //10BASE-T or 100BASE-TX operation mode? 00602 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00603 MAC_SUPP = SUPP_SPEED; 00604 else 00605 MAC_SUPP = 0; 00606 00607 //Half-duplex or full-duplex mode? 00608 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00609 { 00610 //The MAC operates in full-duplex mode 00611 MAC_MAC2 |= MAC2_FULL_DUPLEX; 00612 MAC_COMMAND |= COMMAND_FULL_DUPLEX; 00613 //Configure Back-to-Back Inter-Packet Gap 00614 MAC_IPGT = IPGT_FULL_DUPLEX; 00615 } 00616 else 00617 { 00618 //The MAC operates in half-duplex mode 00619 MAC_MAC2 &= ~MAC2_FULL_DUPLEX; 00620 MAC_COMMAND &= ~COMMAND_FULL_DUPLEX; 00621 //Configure Back-to-Back Inter-Packet Gap 00622 MAC_IPGT = IPGT_HALF_DUPLEX; 00623 } 00624 00625 //Successful processing 00626 return NO_ERROR; 00627 } 00628 00629 00630 /** 00631 * @brief Write PHY register 00632 * @param[in] phyAddr PHY address 00633 * @param[in] regAddr Register address 00634 * @param[in] data Register value 00635 **/ 00636 00637 void lpc23xxEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00638 { 00639 //Clear MCMD register 00640 MAC_MCMD = 0; 00641 00642 //PHY address 00643 MAC_MADR = (phyAddr << 8) & MADR_PHY_ADDRESS; 00644 //Register address 00645 MAC_MADR |= regAddr & MADR_REGISTER_ADDRESS; 00646 //Data to be written in the PHY register 00647 MAC_MWTD = data & MWTD_WRITE_DATA; 00648 00649 //Wait for the write to complete 00650 while(MAC_MIND & MIND_BUSY); 00651 } 00652 00653 00654 /** 00655 * @brief Read PHY register 00656 * @param[in] phyAddr PHY address 00657 * @param[in] regAddr Register address 00658 * @return Register value 00659 **/ 00660 00661 uint16_t lpc23xxEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00662 { 00663 //PHY address 00664 MAC_MADR = (phyAddr << 8) & MADR_PHY_ADDRESS; 00665 //Register address 00666 MAC_MADR |= regAddr & MADR_REGISTER_ADDRESS; 00667 00668 //Start a read operation 00669 MAC_MCMD = MCMD_READ; 00670 //Wait for the read to complete 00671 while(MAC_MIND & MIND_BUSY); 00672 //Clear MCMD register 00673 MAC_MCMD = 0; 00674 00675 //Return PHY register contents 00676 return MAC_MRDD & MRDD_READ_DATA; 00677 } 00678 00679 00680 /** 00681 * @brief CRC calculation 00682 * @param[in] data Pointer to the data over which to calculate the CRC 00683 * @param[in] length Number of bytes to process 00684 * @return Resulting CRC value 00685 **/ 00686 00687 uint32_t lpc23xxEthCalcCrc(const void *data, size_t length) 00688 { 00689 uint_t i; 00690 uint_t j; 00691 00692 //Point to the data over which to calculate the CRC 00693 const uint8_t *p = (uint8_t *) data; 00694 //CRC preset value 00695 uint32_t crc = 0xFFFFFFFF; 00696 00697 //Loop through data 00698 for(i = 0; i < length; i++) 00699 { 00700 //The message is processed bit by bit 00701 for(j = 0; j < 8; j++) 00702 { 00703 //Update CRC value 00704 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00705 crc = (crc << 1) ^ 0x04C11DB7; 00706 else 00707 crc = crc << 1; 00708 } 00709 } 00710 00711 //Return CRC value 00712 return crc; 00713 } 00714
Generated on Tue Jul 12 2022 17:10:14 by
