Embed:
(wiki syntax)
Show/hide line numbers
pic32mx_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file pic32mx_eth.c 00003 * @brief PIC32MX 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 <p32xxxx.h> 00034 #include <sys/kmem.h> 00035 #include "core/net.h" 00036 #include "drivers/pic32mx_eth.h" 00037 #include "debug.h" 00038 00039 //Underlying network interface 00040 static NetInterface *nicDriverInterface; 00041 00042 //Transmit buffer 00043 static uint8_t txBuffer[PIC32MX_ETH_TX_BUFFER_COUNT][PIC32MX_ETH_TX_BUFFER_SIZE] 00044 __attribute__((aligned(4))); 00045 //Receive buffer 00046 static uint8_t rxBuffer[PIC32MX_ETH_RX_BUFFER_COUNT][PIC32MX_ETH_RX_BUFFER_SIZE] 00047 __attribute__((aligned(4))); 00048 //Transmit buffer descriptors 00049 static Pic32mxTxBufferDesc txBufferDesc[PIC32MX_ETH_TX_BUFFER_COUNT] 00050 __attribute__((aligned(4))); 00051 //Receive buffer descriptors 00052 static Pic32mxRxBufferDesc rxBufferDesc[PIC32MX_ETH_RX_BUFFER_COUNT] 00053 __attribute__((aligned(4))); 00054 00055 //Pointer to the current TX buffer descriptor 00056 static Pic32mxTxBufferDesc *txCurBufferDesc; 00057 //Pointer to the current RX buffer descriptor 00058 static Pic32mxRxBufferDesc *rxCurBufferDesc; 00059 00060 00061 /** 00062 * @brief PIC32MX Ethernet MAC driver 00063 **/ 00064 00065 const NicDriver pic32mxEthDriver = 00066 { 00067 NIC_TYPE_ETHERNET, 00068 ETH_MTU, 00069 pic32mxEthInit, 00070 pic32mxEthTick, 00071 pic32mxEthEnableIrq, 00072 pic32mxEthDisableIrq, 00073 pic32mxEthEventHandler, 00074 pic32mxEthSendPacket, 00075 pic32mxEthSetMulticastFilter, 00076 pic32mxEthUpdateMacConfig, 00077 pic32mxEthWritePhyReg, 00078 pic32mxEthReadPhyReg, 00079 TRUE, 00080 TRUE, 00081 TRUE, 00082 FALSE 00083 }; 00084 00085 00086 /** 00087 * @brief PIC32MX Ethernet MAC initialization 00088 * @param[in] interface Underlying network interface 00089 * @return Error code 00090 **/ 00091 00092 error_t pic32mxEthInit(NetInterface *interface) 00093 { 00094 error_t error; 00095 00096 //Debug message 00097 TRACE_INFO("Initializing PIC32MX Ethernet MAC...\r\n"); 00098 00099 //Save underlying network interface 00100 nicDriverInterface = interface; 00101 00102 //GPIO configuration 00103 pic32mxEthInitGpio(interface); 00104 00105 //Disable Ethernet interrupts 00106 IEC1CLR = _IEC1_ETHIE_MASK; 00107 //Turn the Ethernet controller off 00108 ETHCON1CLR = _ETHCON1_ON_MASK | _ETHCON1_TXRTS_POSITION | _ETHCON1_RXEN_MASK; 00109 00110 //Wait activity abort by polling the ETHBUSY bit 00111 while(ETHSTAT & _ETHSTAT_ETHBUSY_MASK); 00112 00113 //Enable the Ethernet controller by setting the ON bit 00114 ETHCON1SET = _ETHCON1_ON_MASK; 00115 00116 //Clear Ethernet interrupt flag 00117 IFS1CLR = _IFS1_ETHIF_MASK; 00118 //Disable any Ethernet controller interrupt generation 00119 ETHIEN = 0; 00120 ETHIRQ = 0; 00121 //Clear the TX and RX start addresses 00122 ETHTXST = 0; 00123 ETHRXST = 0; 00124 00125 //Reset the MAC using SOFTRESET 00126 EMAC1CFG1SET = _EMAC1CFG1_SOFTRESET_MASK; 00127 EMAC1CFG1CLR = _EMAC1CFG1_SOFTRESET_MASK; 00128 00129 //Reset the RMII module 00130 EMAC1SUPPSET = _EMAC1SUPP_RESETRMII_MASK; 00131 EMAC1SUPPCLR = _EMAC1SUPP_RESETRMII_MASK; 00132 00133 //Issue an MIIM block reset by setting the RESETMGMT bit 00134 EMAC1MCFGSET = _EMAC1MCFG_RESETMGMT_MASK; 00135 EMAC1MCFGCLR = _EMAC1MCFG_RESETMGMT_MASK; 00136 00137 //Select the proper divider for the MDC clock 00138 EMAC1MCFG = _EMAC1MCFG_CLKSEL_DIV40; 00139 00140 //PHY transceiver initialization 00141 error = interface->phyDriver->init(interface); 00142 //Failed to initialize PHY transceiver? 00143 if(error) 00144 return error; 00145 00146 //Optionally set the station MAC address 00147 if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR)) 00148 { 00149 //Use the factory preprogrammed station address 00150 interface->macAddr.w[0] = EMAC1SA2; 00151 interface->macAddr.w[1] = EMAC1SA1; 00152 interface->macAddr.w[2] = EMAC1SA0; 00153 00154 //Generate the 64-bit interface identifier 00155 macAddrToEui64(&interface->macAddr, &interface->eui64); 00156 } 00157 else 00158 { 00159 //Override the factory preprogrammed address 00160 EMAC1SA0 = interface->macAddr.w[2]; 00161 EMAC1SA1 = interface->macAddr.w[1]; 00162 EMAC1SA2 = interface->macAddr.w[0]; 00163 } 00164 00165 //Initialize hash table 00166 ETHHT0 = 0; 00167 ETHHT1 = 0; 00168 00169 //Configure the receive filter 00170 ETHRXFC = _ETHRXFC_HTEN_MASK | _ETHRXFC_CRCOKEN_MASK | 00171 _ETHRXFC_RUNTEN_MASK | _ETHRXFC_UCEN_MASK | _ETHRXFC_BCEN_MASK; 00172 00173 //Disable flow control 00174 EMAC1CFG1 = _EMAC1CFG1_RXENABLE_MASK; 00175 //Automatic padding and CRC generation 00176 EMAC1CFG2 = _EMAC1CFG2_PADENABLE_MASK | _EMAC1CFG2_CRCENABLE_MASK; 00177 //Set the maximum frame length 00178 EMAC1MAXF = 1518; 00179 00180 //Initialize DMA descriptor lists 00181 pic32mxEthInitBufferDesc(interface); 00182 00183 //Enable desired interrupts 00184 ETHIENSET = _ETHIEN_PKTPENDIE_MASK | _ETHIEN_TXDONEIE_MASK; 00185 00186 //Set interrupt priority 00187 IPC12CLR = _IPC12_ETHIP_MASK; 00188 IPC12SET = (PIC32MX_ETH_IRQ_PRIORITY << _IPC12_ETHIP_POSITION); 00189 //Set interrupt subpriority 00190 IPC12CLR = _IPC12_ETHIS_MASK; 00191 IPC12SET = (PIC32MX_ETH_IRQ_SUB_PRIORITY << _IPC12_ETHIS_POSITION); 00192 00193 //Enable the reception by setting the RXEN bit 00194 ETHCON1SET = _ETHCON1_RXEN_MASK; 00195 00196 //Accept any packets from the upper layer 00197 osSetEvent(&interface->nicTxEvent); 00198 00199 //Successful initialization 00200 return NO_ERROR; 00201 } 00202 00203 00204 //PIC32 Ethernet Starter Kit? 00205 #if defined(USE_PIC32_ETH_STARTER_KIT) || defined(USE_PIC32_ETH_STARTER_KIT_2) 00206 00207 /** 00208 * @brief GPIO configuration 00209 * @param[in] interface Underlying network interface 00210 **/ 00211 00212 void pic32mxEthInitGpio(NetInterface *interface) 00213 { 00214 //No analog pins are shared with the alternate RMII interface 00215 } 00216 00217 #endif 00218 00219 00220 /** 00221 * @brief Initialize DMA descriptor lists 00222 * @param[in] interface Underlying network interface 00223 **/ 00224 00225 void pic32mxEthInitBufferDesc(NetInterface *interface) 00226 { 00227 uint_t i; 00228 00229 //Initialize TX descriptor list 00230 for(i = 0; i < PIC32MX_ETH_TX_BUFFER_COUNT; i++) 00231 { 00232 //Point to the current descriptor 00233 txCurBufferDesc = KVA0_TO_KVA1(&txBufferDesc[i]); 00234 00235 //Use linked list rather than linear list 00236 txCurBufferDesc->control = ETH_TX_CTRL_NPV; 00237 //Transmit buffer address 00238 txCurBufferDesc->address = (uint32_t) KVA_TO_PA(txBuffer[i]); 00239 //Transmit status vector 00240 txCurBufferDesc->status1 = 0; 00241 txCurBufferDesc->status2 = 0; 00242 //Next descriptor address 00243 txCurBufferDesc->next = (uint32_t) KVA_TO_PA(&txBufferDesc[i + 1]); 00244 } 00245 00246 //The last descriptor is chained to the first entry 00247 txCurBufferDesc->next = (uint32_t) KVA_TO_PA(&txBufferDesc[0]); 00248 //Point to the very first descriptor 00249 txCurBufferDesc = KVA0_TO_KVA1(&txBufferDesc[0]); 00250 00251 //Initialize RX descriptor list 00252 for(i = 0; i < PIC32MX_ETH_RX_BUFFER_COUNT; i++) 00253 { 00254 //Point to the current descriptor 00255 rxCurBufferDesc = KVA0_TO_KVA1(&rxBufferDesc[i]); 00256 00257 //The descriptor is initially owned by the DMA 00258 rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN; 00259 //Receive buffer address 00260 rxCurBufferDesc->address = (uint32_t) KVA_TO_PA(rxBuffer[i]); 00261 //Receive status vector 00262 rxCurBufferDesc->status1 = 0; 00263 rxCurBufferDesc->status2 = 0; 00264 //Next descriptor address 00265 rxCurBufferDesc->next = (uint32_t) KVA_TO_PA(&rxBufferDesc[i + 1]); 00266 } 00267 00268 //The last descriptor is chained to the first entry 00269 rxCurBufferDesc->next = (uint32_t) KVA_TO_PA(&rxBufferDesc[0]); 00270 //Point to the very first descriptor 00271 rxCurBufferDesc = KVA0_TO_KVA1(&rxBufferDesc[0]); 00272 00273 //Starting address of TX descriptor table 00274 ETHTXST = (uint32_t) KVA_TO_PA(&txBufferDesc[0]); 00275 //Starting address of RX descriptor table 00276 ETHRXST = (uint32_t) KVA_TO_PA(&rxBufferDesc[0]); 00277 //Set receive buffer size 00278 ETHCON2 = PIC32MX_ETH_RX_BUFFER_SIZE; 00279 } 00280 00281 00282 /** 00283 * @brief PIC32MX 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 pic32mxEthTick(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 pic32mxEthEnableIrq(NetInterface *interface) 00304 { 00305 //Enable Ethernet MAC interrupts 00306 IEC1SET = _IEC1_ETHIE_MASK; 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 pic32mxEthDisableIrq(NetInterface *interface) 00318 { 00319 //Disable Ethernet MAC interrupts 00320 IEC1CLR = _IEC1_ETHIE_MASK; 00321 //Disable Ethernet PHY interrupts 00322 interface->phyDriver->disableIrq(interface); 00323 } 00324 00325 00326 /** 00327 * @brief PIC32MX Ethernet MAC interrupt service routine 00328 **/ 00329 00330 void pic32mxEthIrqHandler(void) 00331 { 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 = ETHIRQ; 00343 00344 //A packet has been transmitted? 00345 if(status & _ETHIRQ_TXDONE_MASK) 00346 { 00347 //Clear TXDONE interrupt flag 00348 ETHIRQCLR = _ETHIRQ_TXDONE_MASK; 00349 00350 //Check whether the TX buffer is available for writing 00351 if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN)) 00352 { 00353 //Notify the TCP/IP stack that the transmitter is ready to send 00354 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00355 } 00356 } 00357 00358 //A packet has been received? 00359 if(status & _ETHIRQ_PKTPEND_MASK) 00360 { 00361 //Disable PKTPEND interrupt 00362 ETHIENCLR = _ETHIEN_PKTPENDIE_MASK; 00363 00364 //Set event flag 00365 nicDriverInterface->nicEvent = TRUE; 00366 //Notify the TCP/IP stack of the event 00367 flag |= osSetEventFromIsr(&netEvent); 00368 } 00369 00370 //Clear ETHIF interrupt flag before exiting the service routine 00371 IFS1CLR = _IFS1_ETHIF_MASK; 00372 00373 //Leave interrupt service routine 00374 osExitIsr(flag); 00375 } 00376 00377 00378 /** 00379 * @brief PIC32MX Ethernet MAC event handler 00380 * @param[in] interface Underlying network interface 00381 **/ 00382 00383 void pic32mxEthEventHandler(NetInterface *interface) 00384 { 00385 error_t error; 00386 00387 //Packet received? 00388 if(ETHIRQ & _ETHIRQ_PKTPEND_MASK) 00389 { 00390 //Process all pending packets 00391 do 00392 { 00393 //Read incoming packet 00394 error = pic32mxEthReceivePacket(interface); 00395 00396 //No more data in the receive buffer? 00397 } while(error != ERROR_BUFFER_EMPTY); 00398 } 00399 00400 //Re-enable PKTPEND interrupt 00401 ETHIENSET = _ETHIEN_PKTPENDIE_MASK; 00402 } 00403 00404 00405 /** 00406 * @brief Send a packet 00407 * @param[in] interface Underlying network interface 00408 * @param[in] buffer Multi-part buffer containing the data to send 00409 * @param[in] offset Offset to the first data byte 00410 * @return Error code 00411 **/ 00412 00413 error_t pic32mxEthSendPacket(NetInterface *interface, 00414 const NetBuffer *buffer, size_t offset) 00415 { 00416 size_t length; 00417 uint32_t value; 00418 00419 //Retrieve the length of the packet 00420 length = netBufferGetLength(buffer) - offset; 00421 00422 //Check the frame length 00423 if(length > PIC32MX_ETH_TX_BUFFER_SIZE) 00424 { 00425 //The transmitter can accept another packet 00426 osSetEvent(&interface->nicTxEvent); 00427 //Report an error 00428 return ERROR_INVALID_LENGTH; 00429 } 00430 00431 //Make sure the current buffer is available for writing 00432 if(txCurBufferDesc->control & ETH_TX_CTRL_EOWN) 00433 return ERROR_FAILURE; 00434 00435 //Copy user data to the transmit buffer 00436 netBufferRead(PA_TO_KVA1(txCurBufferDesc->address), buffer, offset, length); 00437 00438 //Write the number of bytes to send 00439 value = (length << 16) & ETH_TX_CTRL_BYTE_COUNT; 00440 //Set SOP and EOP flags since the data fits in a single buffer 00441 value |= ETH_TX_CTRL_SOP | ETH_TX_CTRL_EOP | ETH_TX_CTRL_NPV; 00442 //Give the ownership of the descriptor to the DMA 00443 txCurBufferDesc->control = value | ETH_TX_CTRL_EOWN; 00444 00445 //Set TXRTS bit to start the transmission 00446 ETHCON1SET = _ETHCON1_TXRTS_MASK; 00447 00448 //Point to the next descriptor in the list 00449 txCurBufferDesc = PA_TO_KVA1(txCurBufferDesc->next); 00450 00451 //Check whether the next buffer is available for writing 00452 if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN)) 00453 { 00454 //The transmitter can accept another packet 00455 osSetEvent(&interface->nicTxEvent); 00456 } 00457 00458 //Data successfully written 00459 return NO_ERROR; 00460 } 00461 00462 00463 /** 00464 * @brief Receive a packet 00465 * @param[in] interface Underlying network interface 00466 * @return Error code 00467 **/ 00468 00469 error_t pic32mxEthReceivePacket(NetInterface *interface) 00470 { 00471 static uint8_t temp[PIC32MX_ETH_RX_BUFFER_SIZE]; 00472 error_t error; 00473 size_t n; 00474 00475 //The current buffer is available for reading? 00476 if(!(rxCurBufferDesc->control & ETH_RX_CTRL_EOWN)) 00477 { 00478 //SOP and EOP flags should be set 00479 if((rxCurBufferDesc->control & ETH_RX_CTRL_SOP) && 00480 (rxCurBufferDesc->control & ETH_RX_CTRL_EOP)) 00481 { 00482 //Make sure no error occurred 00483 if(rxCurBufferDesc->status2 & ETH_RX_STATUS2_OK) 00484 { 00485 //Retrieve the length of the frame 00486 n = (rxCurBufferDesc->control & ETH_RX_CTRL_BYTE_COUNT) >> 16; 00487 //Limit the number of data to read 00488 n = MIN(n, PIC32MX_ETH_RX_BUFFER_SIZE); 00489 00490 //Copy data from the receive buffer 00491 memcpy(temp, PA_TO_KVA1(rxCurBufferDesc->address), n); 00492 00493 //Pass the packet to the upper layer 00494 nicProcessPacket(interface, temp, n); 00495 00496 //Valid packet received 00497 error = NO_ERROR; 00498 } 00499 else 00500 { 00501 //The received packet contains an error 00502 error = ERROR_INVALID_PACKET; 00503 } 00504 } 00505 else 00506 { 00507 //The packet is not valid 00508 error = ERROR_INVALID_PACKET; 00509 } 00510 00511 //Give the ownership of the descriptor back to the DMA 00512 rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN; 00513 00514 //Point to the next descriptor in the list 00515 rxCurBufferDesc = PA_TO_KVA1(rxCurBufferDesc->next); 00516 00517 //Decrement BUFCNT counter 00518 ETHCON1SET = _ETHCON1_BUFCDEC_MASK; 00519 } 00520 else 00521 { 00522 //No more data in the receive buffer 00523 error = ERROR_BUFFER_EMPTY; 00524 } 00525 00526 //Return status code 00527 return error; 00528 } 00529 00530 00531 /** 00532 * @brief Configure multicast MAC address filtering 00533 * @param[in] interface Underlying network interface 00534 * @return Error code 00535 **/ 00536 00537 error_t pic32mxEthSetMulticastFilter(NetInterface *interface) 00538 { 00539 uint_t i; 00540 uint_t k; 00541 uint32_t crc; 00542 uint32_t hashTable[2]; 00543 MacFilterEntry *entry; 00544 00545 //Debug message 00546 TRACE_DEBUG("Updating PIC32MX hash table...\r\n"); 00547 00548 //Clear hash table 00549 hashTable[0] = 0; 00550 hashTable[1] = 0; 00551 00552 //The MAC filter table contains the multicast MAC addresses 00553 //to accept when receiving an Ethernet frame 00554 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00555 { 00556 //Point to the current entry 00557 entry = &interface->macMulticastFilter[i]; 00558 00559 //Valid entry? 00560 if(entry->refCount > 0) 00561 { 00562 //Compute CRC over the current MAC address 00563 crc = pic32mxEthCalcCrc(&entry->addr, sizeof(MacAddr)); 00564 //Calculate the corresponding index in the table 00565 k = (crc >> 23) & 0x3F; 00566 //Update hash table contents 00567 hashTable[k / 32] |= (1 << (k % 32)); 00568 } 00569 } 00570 00571 //Write the hash table 00572 ETHHT0 = hashTable[0]; 00573 ETHHT1 = hashTable[1]; 00574 00575 //Debug message 00576 TRACE_DEBUG(" ETHHT0 = %08" PRIX32 "\r\n", ETHHT0); 00577 TRACE_DEBUG(" ETHHT1 = %08" PRIX32 "\r\n", ETHHT1); 00578 00579 //Successful processing 00580 return NO_ERROR; 00581 } 00582 00583 00584 /** 00585 * @brief Adjust MAC configuration parameters for proper operation 00586 * @param[in] interface Underlying network interface 00587 * @return Error code 00588 **/ 00589 00590 error_t pic32mxEthUpdateMacConfig(NetInterface *interface) 00591 { 00592 //Check current operating speed 00593 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00594 { 00595 //100BASE-TX operation mode 00596 EMAC1SUPPSET = _EMAC1SUPP_SPEEDRMII_MASK; 00597 } 00598 else 00599 { 00600 //10BASE-T operation mode 00601 EMAC1SUPPCLR = _EMAC1SUPP_SPEEDRMII_MASK; 00602 } 00603 00604 //Half-duplex or full-duplex mode? 00605 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00606 { 00607 //Configure FULLDPLX bit to match the current duplex mode 00608 EMAC1CFG2SET = _EMAC1CFG2_FULLDPLX_MASK; 00609 //Configure the Back-to-Back Inter-Packet Gap register 00610 EMAC1IPGT = 0x15; 00611 } 00612 else 00613 { 00614 //Configure FULLDPLX bit to match the current duplex mode 00615 EMAC1CFG2CLR = _EMAC1CFG2_FULLDPLX_MASK; 00616 //Configure the Back-to-Back Inter-Packet Gap register 00617 EMAC1IPGT = 0x12; 00618 } 00619 00620 //Successful processing 00621 return NO_ERROR; 00622 } 00623 00624 00625 /** 00626 * @brief Write PHY register 00627 * @param[in] phyAddr PHY address 00628 * @param[in] regAddr Register address 00629 * @param[in] data Register value 00630 **/ 00631 00632 void pic32mxEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00633 { 00634 //Set PHY address and register address 00635 EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr; 00636 //Start a write operation 00637 EMAC1MWTD = data & _EMAC1MWTD_MWTD_MASK; 00638 00639 //Wait for busy bit to be set 00640 __asm__ __volatile__ ("nop;"); 00641 __asm__ __volatile__ ("nop;"); 00642 __asm__ __volatile__ ("nop;"); 00643 00644 //Wait for the write to complete 00645 while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK); 00646 } 00647 00648 00649 /** 00650 * @brief Read PHY register 00651 * @param[in] phyAddr PHY address 00652 * @param[in] regAddr Register address 00653 * @return Register value 00654 **/ 00655 00656 uint16_t pic32mxEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00657 { 00658 //Set PHY address and register address 00659 EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr; 00660 //Start a read operation 00661 EMAC1MCMD = _EMAC1MCMD_READ_MASK; 00662 00663 //Wait for busy bit to be set 00664 __asm__ __volatile__ ("nop;"); 00665 __asm__ __volatile__ ("nop;"); 00666 __asm__ __volatile__ ("nop;"); 00667 00668 //Wait for the read to complete 00669 while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK); 00670 00671 //Clear command register 00672 EMAC1MCMD = 0; 00673 //Return PHY register contents 00674 return EMAC1MRDD & _EMAC1MRDD_MRDD_MASK; 00675 } 00676 00677 00678 /** 00679 * @brief CRC calculation 00680 * @param[in] data Pointer to the data over which to calculate the CRC 00681 * @param[in] length Number of bytes to process 00682 * @return Resulting CRC value 00683 **/ 00684 00685 uint32_t pic32mxEthCalcCrc(const void *data, size_t length) 00686 { 00687 uint_t i; 00688 uint_t j; 00689 00690 //Point to the data over which to calculate the CRC 00691 const uint8_t *p = (uint8_t *) data; 00692 //CRC preset value 00693 uint32_t crc = 0xFFFFFFFF; 00694 00695 //Loop through data 00696 for(i = 0; i < length; i++) 00697 { 00698 //The message is processed bit by bit 00699 for(j = 0; j < 8; j++) 00700 { 00701 //Update CRC value 00702 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00703 crc = (crc << 1) ^ 0x04C11DB7; 00704 else 00705 crc = crc << 1; 00706 } 00707 } 00708 00709 //Return CRC value 00710 return crc; 00711 } 00712
Generated on Tue Jul 12 2022 17:10:15 by
