Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
pic32mz_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file pic32mz_eth.c 00003 * @brief PIC32MZ 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/pic32mz_eth.h" 00037 #include "debug.h" 00038 00039 //Underlying network interface 00040 static NetInterface *nicDriverInterface; 00041 00042 //Transmit buffer 00043 static uint8_t txBuffer[PIC32MZ_ETH_TX_BUFFER_COUNT][PIC32MZ_ETH_TX_BUFFER_SIZE] 00044 __attribute__((aligned(4))); 00045 //Receive buffer 00046 static uint8_t rxBuffer[PIC32MZ_ETH_RX_BUFFER_COUNT][PIC32MZ_ETH_RX_BUFFER_SIZE] 00047 __attribute__((aligned(4))); 00048 //Transmit buffer descriptors 00049 static Pic32mzTxBufferDesc txBufferDesc[PIC32MZ_ETH_TX_BUFFER_COUNT] 00050 __attribute__((aligned(4))); 00051 //Receive buffer descriptors 00052 static Pic32mzRxBufferDesc rxBufferDesc[PIC32MZ_ETH_RX_BUFFER_COUNT] 00053 __attribute__((aligned(4))); 00054 00055 //Pointer to the current TX buffer descriptor 00056 static Pic32mzTxBufferDesc *txCurBufferDesc; 00057 //Pointer to the current RX buffer descriptor 00058 static Pic32mzRxBufferDesc *rxCurBufferDesc; 00059 00060 00061 /** 00062 * @brief PIC32MZ Ethernet MAC driver 00063 **/ 00064 00065 const NicDriver pic32mzEthDriver = 00066 { 00067 NIC_TYPE_ETHERNET, 00068 ETH_MTU, 00069 pic32mzEthInit, 00070 pic32mzEthTick, 00071 pic32mzEthEnableIrq, 00072 pic32mzEthDisableIrq, 00073 pic32mzEthEventHandler, 00074 pic32mzEthSendPacket, 00075 pic32mzEthSetMulticastFilter, 00076 pic32mzEthUpdateMacConfig, 00077 pic32mzEthWritePhyReg, 00078 pic32mzEthReadPhyReg, 00079 TRUE, 00080 TRUE, 00081 TRUE, 00082 FALSE 00083 }; 00084 00085 00086 /** 00087 * @brief PIC32MZ Ethernet MAC initialization 00088 * @param[in] interface Underlying network interface 00089 * @return Error code 00090 **/ 00091 00092 error_t pic32mzEthInit(NetInterface *interface) 00093 { 00094 error_t error; 00095 00096 //Debug message 00097 TRACE_INFO("Initializing PIC32MZ Ethernet MAC...\r\n"); 00098 00099 //Save underlying network interface 00100 nicDriverInterface = interface; 00101 00102 //GPIO configuration 00103 pic32mzEthInitGpio(interface); 00104 00105 //Disable Ethernet interrupts 00106 IEC4CLR = _IEC4_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 IFS4CLR = _IFS4_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_DIV50; 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 pic32mzEthInitBufferDesc(interface); 00182 00183 //Enable desired interrupts 00184 ETHIENSET = _ETHIEN_PKTPENDIE_MASK | _ETHIEN_TXDONEIE_MASK; 00185 00186 //Set interrupt priority 00187 IPC38CLR = _IPC38_ETHIP_MASK; 00188 IPC38SET = (PIC32MZ_ETH_IRQ_PRIORITY << _IPC38_ETHIP_POSITION); 00189 //Set interrupt subpriority 00190 IPC38CLR = _IPC38_ETHIS_MASK; 00191 IPC38SET = (PIC32MZ_ETH_IRQ_SUB_PRIORITY << _IPC38_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 //PIC32MZ EC Starter Kit, PIC32MZ EF Starter Kit or IoT Ethernet Kit? 00205 #if defined(USE_PIC32MZ_EC_STARTER_KIT) || defined(USE_PIC32MZ_EF_STARTER_KIT) || \ 00206 defined(USE_IOT_ETHERNET_KIT) 00207 00208 /** 00209 * @brief GPIO configuration 00210 * @param[in] interface Underlying network interface 00211 **/ 00212 00213 void pic32mzEthInitGpio(NetInterface *interface) 00214 { 00215 //PIC32MZ EC Starter Kit or PIC32MZ EF Starter Kit? 00216 #if defined(USE_PIC32MZ_EC_STARTER_KIT) || defined(USE_PIC32MZ_EF_STARTER_KIT) 00217 //Disable analog pad on ETXD0 (AN35/RJ8) 00218 ANSELJCLR = _ANSELJ_ANSJ8_MASK; 00219 //Disable analog pad on ETXD1 (AN36/RJ9) 00220 ANSELJCLR = _ANSELJ_ANSJ9_MASK; 00221 //Disable analog pad on EREFCLK (AN37/RJ11) 00222 ANSELJCLR = _ANSELJ_ANSJ11_MASK; 00223 //Disable analog pad on ERXERR (AN40/RH4) 00224 ANSELHCLR = _ANSELH_ANSH4_MASK; 00225 //Disable analog pad on ERXD1 (AN41/RH5) 00226 ANSELHCLR = _ANSELH_ANSH5_MASK; 00227 00228 //IoT Ethernet Kit? 00229 #elif defined(USE_IOT_ETHERNET_KIT) 00230 //Disable analog pad on ERXERR (AN18/RE4) 00231 ANSELECLR = _ANSELE_ANSE4_MASK; 00232 //Disable analog pad on ETXEN (AN17/RE5) 00233 ANSELECLR = _ANSELE_ANSE5_MASK; 00234 //Disable analog pad on ETXD0 (AN16/RE6) 00235 ANSELECLR = _ANSELE_ANSE6_MASK; 00236 //Disable analog pad on ETXD1 (AN15/RE7) 00237 ANSELECLR = _ANSELE_ANSE7_MASK; 00238 #endif 00239 } 00240 00241 #endif 00242 00243 00244 /** 00245 * @brief Initialize DMA descriptor lists 00246 * @param[in] interface Underlying network interface 00247 **/ 00248 00249 void pic32mzEthInitBufferDesc(NetInterface *interface) 00250 { 00251 uint_t i; 00252 00253 //Initialize TX descriptor list 00254 for(i = 0; i < PIC32MZ_ETH_TX_BUFFER_COUNT; i++) 00255 { 00256 //Point to the current descriptor 00257 txCurBufferDesc = KVA0_TO_KVA1(&txBufferDesc[i]); 00258 00259 //Use linked list rather than linear list 00260 txCurBufferDesc->control = ETH_TX_CTRL_NPV; 00261 //Transmit buffer address 00262 txCurBufferDesc->address = (uint32_t) KVA_TO_PA(txBuffer[i]); 00263 //Transmit status vector 00264 txCurBufferDesc->status1 = 0; 00265 txCurBufferDesc->status2 = 0; 00266 //Next descriptor address 00267 txCurBufferDesc->next = (uint32_t) KVA_TO_PA(&txBufferDesc[i + 1]); 00268 } 00269 00270 //The last descriptor is chained to the first entry 00271 txCurBufferDesc->next = (uint32_t) KVA_TO_PA(&txBufferDesc[0]); 00272 //Point to the very first descriptor 00273 txCurBufferDesc = KVA0_TO_KVA1(&txBufferDesc[0]); 00274 00275 //Initialize RX descriptor list 00276 for(i = 0; i < PIC32MZ_ETH_RX_BUFFER_COUNT; i++) 00277 { 00278 //Point to the current descriptor 00279 rxCurBufferDesc = KVA0_TO_KVA1(&rxBufferDesc[i]); 00280 00281 //The descriptor is initially owned by the DMA 00282 rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN; 00283 //Receive buffer address 00284 rxCurBufferDesc->address = (uint32_t) KVA_TO_PA(rxBuffer[i]); 00285 //Receive status vector 00286 rxCurBufferDesc->status1 = 0; 00287 rxCurBufferDesc->status2 = 0; 00288 //Next descriptor address 00289 rxCurBufferDesc->next = (uint32_t) KVA_TO_PA(&rxBufferDesc[i + 1]); 00290 } 00291 00292 //The last descriptor is chained to the first entry 00293 rxCurBufferDesc->next = (uint32_t) KVA_TO_PA(&rxBufferDesc[0]); 00294 //Point to the very first descriptor 00295 rxCurBufferDesc = KVA0_TO_KVA1(&rxBufferDesc[0]); 00296 00297 //Starting address of TX descriptor table 00298 ETHTXST = (uint32_t) KVA_TO_PA(&txBufferDesc[0]); 00299 //Starting address of RX descriptor table 00300 ETHRXST = (uint32_t) KVA_TO_PA(&rxBufferDesc[0]); 00301 //Set receive buffer size 00302 ETHCON2 = PIC32MZ_ETH_RX_BUFFER_SIZE; 00303 } 00304 00305 00306 /** 00307 * @brief PIC32MZ Ethernet MAC timer handler 00308 * 00309 * This routine is periodically called by the TCP/IP stack to 00310 * handle periodic operations such as polling the link state 00311 * 00312 * @param[in] interface Underlying network interface 00313 **/ 00314 00315 void pic32mzEthTick(NetInterface *interface) 00316 { 00317 //Handle periodic operations 00318 interface->phyDriver->tick(interface); 00319 } 00320 00321 00322 /** 00323 * @brief Enable interrupts 00324 * @param[in] interface Underlying network interface 00325 **/ 00326 00327 void pic32mzEthEnableIrq(NetInterface *interface) 00328 { 00329 //Enable Ethernet MAC interrupts 00330 IEC4SET = _IEC4_ETHIE_MASK; 00331 //Enable Ethernet PHY interrupts 00332 interface->phyDriver->enableIrq(interface); 00333 } 00334 00335 00336 /** 00337 * @brief Disable interrupts 00338 * @param[in] interface Underlying network interface 00339 **/ 00340 00341 void pic32mzEthDisableIrq(NetInterface *interface) 00342 { 00343 //Disable Ethernet MAC interrupts 00344 IEC4CLR = _IEC4_ETHIE_MASK; 00345 //Disable Ethernet PHY interrupts 00346 interface->phyDriver->disableIrq(interface); 00347 } 00348 00349 00350 /** 00351 * @brief PIC32MZ Ethernet MAC interrupt service routine 00352 **/ 00353 00354 void pic32mzEthIrqHandler(void) 00355 { 00356 bool_t flag; 00357 uint32_t status; 00358 00359 //Enter interrupt service routine 00360 osEnterIsr(); 00361 00362 //This flag will be set if a higher priority task must be woken 00363 flag = FALSE; 00364 00365 //Read interrupt status register 00366 status = ETHIRQ; 00367 00368 //A packet has been transmitted? 00369 if(status & _ETHIRQ_TXDONE_MASK) 00370 { 00371 //Clear TXDONE interrupt flag 00372 ETHIRQCLR = _ETHIRQ_TXDONE_MASK; 00373 00374 //Check whether the TX buffer is available for writing 00375 if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN)) 00376 { 00377 //Notify the TCP/IP stack that the transmitter is ready to send 00378 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00379 } 00380 } 00381 00382 //A packet has been received? 00383 if(status & _ETHIRQ_PKTPEND_MASK) 00384 { 00385 //Disable PKTPEND interrupt 00386 ETHIENCLR = _ETHIEN_PKTPENDIE_MASK; 00387 00388 //Set event flag 00389 nicDriverInterface->nicEvent = TRUE; 00390 //Notify the TCP/IP stack of the event 00391 flag |= osSetEventFromIsr(&netEvent); 00392 } 00393 00394 //Clear ETHIF interrupt flag before exiting the service routine 00395 IFS4CLR = _IFS4_ETHIF_MASK; 00396 00397 //Leave interrupt service routine 00398 osExitIsr(flag); 00399 } 00400 00401 00402 /** 00403 * @brief PIC32MZ Ethernet MAC event handler 00404 * @param[in] interface Underlying network interface 00405 **/ 00406 00407 void pic32mzEthEventHandler(NetInterface *interface) 00408 { 00409 error_t error; 00410 00411 //Packet received? 00412 if(ETHIRQ & _ETHIRQ_PKTPEND_MASK) 00413 { 00414 //Process all pending packets 00415 do 00416 { 00417 //Read incoming packet 00418 error = pic32mzEthReceivePacket(interface); 00419 00420 //No more data in the receive buffer? 00421 } while(error != ERROR_BUFFER_EMPTY); 00422 } 00423 00424 //Re-enable PKTPEND interrupt 00425 ETHIENSET = _ETHIEN_PKTPENDIE_MASK; 00426 } 00427 00428 00429 /** 00430 * @brief Send a packet 00431 * @param[in] interface Underlying network interface 00432 * @param[in] buffer Multi-part buffer containing the data to send 00433 * @param[in] offset Offset to the first data byte 00434 * @return Error code 00435 **/ 00436 00437 error_t pic32mzEthSendPacket(NetInterface *interface, 00438 const NetBuffer *buffer, size_t offset) 00439 { 00440 size_t length; 00441 uint32_t value; 00442 00443 //Retrieve the length of the packet 00444 length = netBufferGetLength(buffer) - offset; 00445 00446 //Check the frame length 00447 if(length > PIC32MZ_ETH_TX_BUFFER_SIZE) 00448 { 00449 //The transmitter can accept another packet 00450 osSetEvent(&interface->nicTxEvent); 00451 //Report an error 00452 return ERROR_INVALID_LENGTH; 00453 } 00454 00455 //Make sure the current buffer is available for writing 00456 if(txCurBufferDesc->control & ETH_TX_CTRL_EOWN) 00457 return ERROR_FAILURE; 00458 00459 //Copy user data to the transmit buffer 00460 netBufferRead(PA_TO_KVA1(txCurBufferDesc->address), buffer, offset, length); 00461 00462 //Write the number of bytes to send 00463 value = (length << 16) & ETH_TX_CTRL_BYTE_COUNT; 00464 //Set SOP and EOP flags since the data fits in a single buffer 00465 value |= ETH_TX_CTRL_SOP | ETH_TX_CTRL_EOP | ETH_TX_CTRL_NPV; 00466 //Give the ownership of the descriptor to the DMA 00467 txCurBufferDesc->control = value | ETH_TX_CTRL_EOWN; 00468 00469 //Set TXRTS bit to start the transmission 00470 ETHCON1SET = _ETHCON1_TXRTS_MASK; 00471 00472 //Point to the next descriptor in the list 00473 txCurBufferDesc = PA_TO_KVA1(txCurBufferDesc->next); 00474 00475 //Check whether the next buffer is available for writing 00476 if(!(txCurBufferDesc->control & ETH_TX_CTRL_EOWN)) 00477 { 00478 //The transmitter can accept another packet 00479 osSetEvent(&interface->nicTxEvent); 00480 } 00481 00482 //Data successfully written 00483 return NO_ERROR; 00484 } 00485 00486 00487 /** 00488 * @brief Receive a packet 00489 * @param[in] interface Underlying network interface 00490 * @return Error code 00491 **/ 00492 00493 error_t pic32mzEthReceivePacket(NetInterface *interface) 00494 { 00495 static uint8_t temp[PIC32MZ_ETH_RX_BUFFER_SIZE]; 00496 error_t error; 00497 size_t n; 00498 00499 //The current buffer is available for reading? 00500 if(!(rxCurBufferDesc->control & ETH_RX_CTRL_EOWN)) 00501 { 00502 //SOP and EOP flags should be set 00503 if((rxCurBufferDesc->control & ETH_RX_CTRL_SOP) && 00504 (rxCurBufferDesc->control & ETH_RX_CTRL_EOP)) 00505 { 00506 //Make sure no error occurred 00507 if(rxCurBufferDesc->status2 & ETH_RX_STATUS2_OK) 00508 { 00509 //Retrieve the length of the frame 00510 n = (rxCurBufferDesc->control & ETH_RX_CTRL_BYTE_COUNT) >> 16; 00511 //Limit the number of data to read 00512 n = MIN(n, PIC32MZ_ETH_RX_BUFFER_SIZE); 00513 00514 //Copy data from the receive buffer 00515 memcpy(temp, PA_TO_KVA1(rxCurBufferDesc->address), n); 00516 00517 //Pass the packet to the upper layer 00518 nicProcessPacket(interface, temp, n); 00519 00520 //Valid packet received 00521 error = NO_ERROR; 00522 } 00523 else 00524 { 00525 //The received packet contains an error 00526 error = ERROR_INVALID_PACKET; 00527 } 00528 } 00529 else 00530 { 00531 //The packet is not valid 00532 error = ERROR_INVALID_PACKET; 00533 } 00534 00535 //Give the ownership of the descriptor back to the DMA 00536 rxCurBufferDesc->control = ETH_RX_CTRL_NPV | ETH_RX_CTRL_EOWN; 00537 00538 //Point to the next descriptor in the list 00539 rxCurBufferDesc = PA_TO_KVA1(rxCurBufferDesc->next); 00540 00541 //Decrement BUFCNT counter 00542 ETHCON1SET = _ETHCON1_BUFCDEC_MASK; 00543 } 00544 else 00545 { 00546 //No more data in the receive buffer 00547 error = ERROR_BUFFER_EMPTY; 00548 } 00549 00550 //Return status code 00551 return error; 00552 } 00553 00554 00555 /** 00556 * @brief Configure multicast MAC address filtering 00557 * @param[in] interface Underlying network interface 00558 * @return Error code 00559 **/ 00560 00561 error_t pic32mzEthSetMulticastFilter(NetInterface *interface) 00562 { 00563 uint_t i; 00564 uint_t k; 00565 uint32_t crc; 00566 uint32_t hashTable[2]; 00567 MacFilterEntry *entry; 00568 00569 //Debug message 00570 TRACE_DEBUG("Updating PIC32MZ hash table...\r\n"); 00571 00572 //Clear hash table 00573 hashTable[0] = 0; 00574 hashTable[1] = 0; 00575 00576 //The MAC filter table contains the multicast MAC addresses 00577 //to accept when receiving an Ethernet frame 00578 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00579 { 00580 //Point to the current entry 00581 entry = &interface->macMulticastFilter[i]; 00582 00583 //Valid entry? 00584 if(entry->refCount > 0) 00585 { 00586 //Compute CRC over the current MAC address 00587 crc = pic32mzEthCalcCrc(&entry->addr, sizeof(MacAddr)); 00588 //Calculate the corresponding index in the table 00589 k = (crc >> 23) & 0x3F; 00590 //Update hash table contents 00591 hashTable[k / 32] |= (1 << (k % 32)); 00592 } 00593 } 00594 00595 //Write the hash table 00596 ETHHT0 = hashTable[0]; 00597 ETHHT1 = hashTable[1]; 00598 00599 //Debug message 00600 TRACE_DEBUG(" ETHHT0 = %08" PRIX32 "\r\n", ETHHT0); 00601 TRACE_DEBUG(" ETHHT1 = %08" PRIX32 "\r\n", ETHHT1); 00602 00603 //Successful processing 00604 return NO_ERROR; 00605 } 00606 00607 00608 /** 00609 * @brief Adjust MAC configuration parameters for proper operation 00610 * @param[in] interface Underlying network interface 00611 * @return Error code 00612 **/ 00613 00614 error_t pic32mzEthUpdateMacConfig(NetInterface *interface) 00615 { 00616 //Check current operating speed 00617 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00618 { 00619 //100BASE-TX operation mode 00620 EMAC1SUPPSET = _EMAC1SUPP_SPEEDRMII_MASK; 00621 } 00622 else 00623 { 00624 //10BASE-T operation mode 00625 EMAC1SUPPCLR = _EMAC1SUPP_SPEEDRMII_MASK; 00626 } 00627 00628 //Half-duplex or full-duplex mode? 00629 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00630 { 00631 //Configure FULLDPLX bit to match the current duplex mode 00632 EMAC1CFG2SET = _EMAC1CFG2_FULLDPLX_MASK; 00633 //Configure the Back-to-Back Inter-Packet Gap register 00634 EMAC1IPGT = 0x15; 00635 } 00636 else 00637 { 00638 //Configure FULLDPLX bit to match the current duplex mode 00639 EMAC1CFG2CLR = _EMAC1CFG2_FULLDPLX_MASK; 00640 //Configure the Back-to-Back Inter-Packet Gap register 00641 EMAC1IPGT = 0x12; 00642 } 00643 00644 //Successful processing 00645 return NO_ERROR; 00646 } 00647 00648 00649 /** 00650 * @brief Write PHY register 00651 * @param[in] phyAddr PHY address 00652 * @param[in] regAddr Register address 00653 * @param[in] data Register value 00654 **/ 00655 00656 void pic32mzEthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00657 { 00658 uint_t i; 00659 00660 //Set PHY address and register address 00661 EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr; 00662 //Start a write operation 00663 EMAC1MWTD = data & _EMAC1MWTD_MWTD_MASK; 00664 00665 //Wait for busy bit to be set 00666 for(i = 0; i < 16; i++) 00667 __asm__ __volatile__ ("nop;"); 00668 00669 //Wait for the write to complete 00670 while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK); 00671 } 00672 00673 00674 /** 00675 * @brief Read PHY register 00676 * @param[in] phyAddr PHY address 00677 * @param[in] regAddr Register address 00678 * @return Register value 00679 **/ 00680 00681 uint16_t pic32mzEthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00682 { 00683 uint_t i; 00684 00685 //Set PHY address and register address 00686 EMAC1MADR = (phyAddr << _EMAC1MADR_PHYADDR_POSITION) | regAddr; 00687 //Start a read operation 00688 EMAC1MCMD = _EMAC1MCMD_READ_MASK; 00689 00690 //Wait for busy bit to be set 00691 for(i = 0; i < 16; i++) 00692 __asm__ __volatile__ ("nop;"); 00693 00694 //Wait for the read to complete 00695 while(EMAC1MIND & _EMAC1MIND_MIIMBUSY_MASK); 00696 00697 //Clear command register 00698 EMAC1MCMD = 0; 00699 //Return PHY register contents 00700 return EMAC1MRDD & _EMAC1MRDD_MRDD_MASK; 00701 } 00702 00703 00704 /** 00705 * @brief CRC calculation 00706 * @param[in] data Pointer to the data over which to calculate the CRC 00707 * @param[in] length Number of bytes to process 00708 * @return Resulting CRC value 00709 **/ 00710 00711 uint32_t pic32mzEthCalcCrc(const void *data, size_t length) 00712 { 00713 uint_t i; 00714 uint_t j; 00715 00716 //Point to the data over which to calculate the CRC 00717 const uint8_t *p = (uint8_t *) data; 00718 //CRC preset value 00719 uint32_t crc = 0xFFFFFFFF; 00720 00721 //Loop through data 00722 for(i = 0; i < length; i++) 00723 { 00724 //The message is processed bit by bit 00725 for(j = 0; j < 8; j++) 00726 { 00727 //Update CRC value 00728 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00729 crc = (crc << 1) ^ 0x04C11DB7; 00730 else 00731 crc = crc << 1; 00732 } 00733 } 00734 00735 //Return CRC value 00736 return crc; 00737 } 00738
Generated on Tue Jul 12 2022 17:10:15 by
