Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
a2fxxxm3_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file a2fxxxm3_eth.c 00003 * @brief SmartFusion (A2FxxxM3) 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 "a2fxxxm3.h" 00034 #include "drivers/mss_ethernet_mac/mss_ethernet_mac_regs.h" 00035 #include "drivers/mss_ethernet_mac/mss_ethernet_mac_desc.h" 00036 #include "core/net.h" 00037 #include "drivers/a2fxxxm3_eth.h" 00038 #include "debug.h" 00039 00040 //Underlying network interface 00041 static NetInterface *nicDriverInterface; 00042 00043 //IAR EWARM compiler? 00044 #if defined(__ICCARM__) 00045 00046 //Transmit buffer 00047 #pragma data_alignment = 4 00048 static uint8_t txBuffer[A2FXXXM3_ETH_TX_BUFFER_COUNT][A2FXXXM3_ETH_TX_BUFFER_SIZE]; 00049 //Receive buffer 00050 #pragma data_alignment = 4 00051 static uint8_t rxBuffer[A2FXXXM3_ETH_RX_BUFFER_COUNT][A2FXXXM3_ETH_RX_BUFFER_SIZE]; 00052 //Transmit DMA descriptors 00053 #pragma data_alignment = 4 00054 static A2fxxxm3TxDmaDesc txDmaDesc[A2FXXXM3_ETH_TX_BUFFER_COUNT]; 00055 //Receive DMA descriptors 00056 #pragma data_alignment = 4 00057 static A2fxxxm3RxDmaDesc rxDmaDesc[A2FXXXM3_ETH_RX_BUFFER_COUNT]; 00058 00059 //Keil MDK-ARM or GCC compiler? 00060 #else 00061 00062 //Transmit buffer 00063 static uint8_t txBuffer[A2FXXXM3_ETH_TX_BUFFER_COUNT][A2FXXXM3_ETH_TX_BUFFER_SIZE] 00064 __attribute__((aligned(4))); 00065 //Receive buffer 00066 static uint8_t rxBuffer[A2FXXXM3_ETH_RX_BUFFER_COUNT][A2FXXXM3_ETH_RX_BUFFER_SIZE] 00067 __attribute__((aligned(4))); 00068 //Transmit DMA descriptors 00069 static A2fxxxm3TxDmaDesc txDmaDesc[A2FXXXM3_ETH_TX_BUFFER_COUNT] 00070 __attribute__((aligned(4))); 00071 //Receive DMA descriptors 00072 static A2fxxxm3RxDmaDesc rxDmaDesc[A2FXXXM3_ETH_RX_BUFFER_COUNT] 00073 __attribute__((aligned(4))); 00074 00075 #endif 00076 00077 //Pointer to the current TX DMA descriptor 00078 static A2fxxxm3TxDmaDesc *txCurDmaDesc; 00079 //Pointer to the current RX DMA descriptor 00080 static A2fxxxm3RxDmaDesc *rxCurDmaDesc; 00081 00082 00083 /** 00084 * @brief A2FxxxM3 Ethernet MAC driver 00085 **/ 00086 00087 const NicDriver a2fxxxm3EthDriver = 00088 { 00089 NIC_TYPE_ETHERNET, 00090 ETH_MTU, 00091 a2fxxxm3EthInit, 00092 a2fxxxm3EthTick, 00093 a2fxxxm3EthEnableIrq, 00094 a2fxxxm3EthDisableIrq, 00095 a2fxxxm3EthEventHandler, 00096 a2fxxxm3EthSendPacket, 00097 a2fxxxm3EthSetMulticastFilter, 00098 a2fxxxm3EthUpdateMacConfig, 00099 a2fxxxm3EthWritePhyReg, 00100 a2fxxxm3EthReadPhyReg, 00101 TRUE, 00102 TRUE, 00103 TRUE, 00104 FALSE 00105 }; 00106 00107 00108 /** 00109 * @brief A2FxxxM3 Ethernet MAC initialization 00110 * @param[in] interface Underlying network interface 00111 * @return Error code 00112 **/ 00113 00114 error_t a2fxxxm3EthInit(NetInterface *interface) 00115 { 00116 error_t error; 00117 00118 //Debug message 00119 TRACE_INFO("Initializing A2FxxxM3 Ethernet MAC...\r\n"); 00120 00121 //Save underlying network interface 00122 nicDriverInterface = interface; 00123 00124 //Perform a software reset 00125 MAC->CSR0 |= CSR0_SWR_MASK; 00126 //Wait for the reset to complete 00127 while(MAC->CSR0 & CSR0_SWR_MASK); 00128 00129 //PHY transceiver initialization 00130 error = interface->phyDriver->init(interface); 00131 //Failed to initialize PHY transceiver? 00132 if(error) 00133 return error; 00134 00135 //Enable store and forward mode 00136 MAC->CSR6 |= CSR6_SF_MASK; 00137 00138 //Initialize DMA descriptor lists 00139 a2fxxxm3EthInitDmaDesc(interface); 00140 00141 //Enable the desired Ethernet interrupts 00142 MAC->CSR7 |= CSR7_NIE_MASK | CSR7_RIE_MASK | CSR7_TIE_MASK; 00143 00144 //Set priority grouping (5 bits for pre-emption priority, no bits for subpriority) 00145 NVIC_SetPriorityGrouping(A2FXXXM3_ETH_IRQ_PRIORITY_GROUPING); 00146 00147 //Configure Ethernet interrupt priority 00148 NVIC_SetPriority(EthernetMAC_IRQn, NVIC_EncodePriority(A2FXXXM3_ETH_IRQ_PRIORITY_GROUPING, 00149 A2FXXXM3_ETH_IRQ_GROUP_PRIORITY, A2FXXXM3_ETH_IRQ_SUB_PRIORITY)); 00150 00151 //Enable transmission and reception 00152 MAC->CSR6 |= CSR6_ST_MASK | CSR6_SR_MASK; 00153 00154 //Set MAC address 00155 error = a2fxxxm3EthSendSetup(interface); 00156 //Any error to report? 00157 if(error) 00158 return error; 00159 00160 //Accept any packets from the upper layer 00161 osSetEvent(&interface->nicTxEvent); 00162 00163 //Successful initialization 00164 return NO_ERROR; 00165 } 00166 00167 00168 /** 00169 * @brief Initialize DMA descriptor lists 00170 * @param[in] interface Underlying network interface 00171 **/ 00172 00173 void a2fxxxm3EthInitDmaDesc(NetInterface *interface) 00174 { 00175 uint_t i; 00176 00177 //Initialize TX DMA descriptor list 00178 for(i = 0; i < A2FXXXM3_ETH_TX_BUFFER_COUNT; i++) 00179 { 00180 //The descriptor is initially owned by the user 00181 txDmaDesc[i].tdes0 = 0; 00182 //Use chain structure rather than ring structure 00183 txDmaDesc[i].tdes1 = TDES1_TCH; 00184 //Transmit buffer address 00185 txDmaDesc[i].tdes2 = (uint32_t) txBuffer[i]; 00186 //Next descriptor address 00187 txDmaDesc[i].tdes3 = (uint32_t) &txDmaDesc[i + 1]; 00188 } 00189 00190 //The last descriptor is chained to the first entry 00191 txDmaDesc[i - 1].tdes3 = (uint32_t) &txDmaDesc[0]; 00192 //Point to the very first descriptor 00193 txCurDmaDesc = &txDmaDesc[0]; 00194 00195 //Initialize RX DMA descriptor list 00196 for(i = 0; i < A2FXXXM3_ETH_RX_BUFFER_COUNT; i++) 00197 { 00198 //The descriptor is initially owned by the DMA 00199 rxDmaDesc[i].rdes0 = RDES0_OWN; 00200 //Use chain structure rather than ring structure 00201 rxDmaDesc[i].rdes1 = RDES1_RCH | (A2FXXXM3_ETH_RX_BUFFER_SIZE & RDES1_RBS1_MASK); 00202 //Receive buffer address 00203 rxDmaDesc[i].rdes2 = (uint32_t) rxBuffer[i]; 00204 //Next descriptor address 00205 rxDmaDesc[i].rdes3 = (uint32_t) &rxDmaDesc[i + 1]; 00206 } 00207 00208 //The last descriptor is chained to the first entry 00209 rxDmaDesc[i - 1].rdes3 = (uint32_t) &rxDmaDesc[0]; 00210 //Point to the very first descriptor 00211 rxCurDmaDesc = &rxDmaDesc[0]; 00212 00213 //Start location of the TX descriptor list 00214 MAC->CSR4 = (uint32_t) txDmaDesc; 00215 //Start location of the RX descriptor list 00216 MAC->CSR3 = (uint32_t) rxDmaDesc; 00217 } 00218 00219 00220 /** 00221 * @brief A2FxxxM3 Ethernet MAC timer handler 00222 * 00223 * This routine is periodically called by the TCP/IP stack to 00224 * handle periodic operations such as polling the link state 00225 * 00226 * @param[in] interface Underlying network interface 00227 **/ 00228 00229 void a2fxxxm3EthTick(NetInterface *interface) 00230 { 00231 //Handle periodic operations 00232 interface->phyDriver->tick(interface); 00233 } 00234 00235 00236 /** 00237 * @brief Enable interrupts 00238 * @param[in] interface Underlying network interface 00239 **/ 00240 00241 void a2fxxxm3EthEnableIrq(NetInterface *interface) 00242 { 00243 //Enable Ethernet MAC interrupts 00244 NVIC_EnableIRQ(EthernetMAC_IRQn); 00245 //Enable Ethernet PHY interrupts 00246 interface->phyDriver->enableIrq(interface); 00247 } 00248 00249 00250 /** 00251 * @brief Disable interrupts 00252 * @param[in] interface Underlying network interface 00253 **/ 00254 00255 void a2fxxxm3EthDisableIrq(NetInterface *interface) 00256 { 00257 //Disable Ethernet MAC interrupts 00258 NVIC_DisableIRQ(EthernetMAC_IRQn); 00259 //Disable Ethernet PHY interrupts 00260 interface->phyDriver->disableIrq(interface); 00261 } 00262 00263 00264 /** 00265 * @brief A2FxxxM3 Ethernet MAC interrupt service routine 00266 **/ 00267 00268 void EthernetMAC_IRQHandler(void) 00269 { 00270 bool_t flag; 00271 uint32_t status; 00272 00273 //Enter interrupt service routine 00274 osEnterIsr(); 00275 00276 //This flag will be set if a higher priority task must be woken 00277 flag = FALSE; 00278 00279 //Read interrupt status register 00280 status = MAC->CSR5; 00281 00282 //A packet has been transmitted? 00283 if(status & CSR5_TI_MASK) 00284 { 00285 //Clear TI interrupt flag 00286 MAC->CSR5 = CSR5_TI_MASK; 00287 00288 //Check whether the TX buffer is available for writing 00289 if(!(txCurDmaDesc->tdes0 & TDES0_OWN)) 00290 { 00291 //Notify the TCP/IP stack that the transmitter is ready to send 00292 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00293 } 00294 } 00295 00296 //A packet has been received? 00297 if(status & CSR5_RI_MASK) 00298 { 00299 //Disable RIE interrupt 00300 MAC->CSR7 &= ~CSR7_RIE_MASK; 00301 00302 //Set event flag 00303 nicDriverInterface->nicEvent = TRUE; 00304 //Notify the TCP/IP stack of the event 00305 flag |= osSetEventFromIsr(&netEvent); 00306 } 00307 00308 //Clear NIS interrupt flag 00309 MAC->CSR5 = CSR5_NIS_MASK; 00310 00311 //Leave interrupt service routine 00312 osExitIsr(flag); 00313 } 00314 00315 00316 /** 00317 * @brief A2FxxxM3 Ethernet MAC event handler 00318 * @param[in] interface Underlying network interface 00319 **/ 00320 00321 void a2fxxxm3EthEventHandler(NetInterface *interface) 00322 { 00323 error_t error; 00324 00325 //Packet received? 00326 if(MAC->CSR5 & CSR5_RI_MASK) 00327 { 00328 //Clear interrupt flag 00329 MAC->CSR5 = CSR5_RI_MASK; 00330 00331 //Process all pending packets 00332 do 00333 { 00334 //Read incoming packet 00335 error = a2fxxxm3EthReceivePacket(interface); 00336 00337 //No more data in the receive buffer? 00338 } while(error != ERROR_BUFFER_EMPTY); 00339 } 00340 00341 //Re-enable Ethernet interrupts 00342 MAC->CSR7 |= CSR7_NIE_MASK | CSR7_RIE_MASK | CSR7_TIE_MASK; 00343 } 00344 00345 00346 /** 00347 * @brief Send a setup frame 00348 * @param[in] interface Underlying network interface 00349 * @return Error code 00350 **/ 00351 00352 error_t a2fxxxm3EthSendSetup(NetInterface *interface) 00353 { 00354 A2fxxxm3HashTableSetupFrame *setupFrame; 00355 00356 //Make sure the current buffer is available for writing 00357 if(txCurDmaDesc->tdes0 & TDES0_OWN) 00358 return ERROR_FAILURE; 00359 00360 //Point to the buffer where to format the setup frame 00361 setupFrame = (A2fxxxm3HashTableSetupFrame *) txCurDmaDesc->tdes2; 00362 00363 //Clear contents 00364 memset(setupFrame, 0, sizeof(A2fxxxm3HashTableSetupFrame)); 00365 00366 //Set MAC address 00367 setupFrame->physicalAddr[0] = interface->macAddr.w[0]; 00368 setupFrame->physicalAddr[1] = interface->macAddr.w[1]; 00369 setupFrame->physicalAddr[2] = interface->macAddr.w[2]; 00370 00371 //Write the number of bytes to send 00372 txCurDmaDesc->tdes1 = sizeof(A2fxxxm3HashTableSetupFrame) & TDES1_TBS1_MASK; 00373 //The SET flag indicates that this is a setup frame descriptor 00374 txCurDmaDesc->tdes1 |= TDES1_SET | TDES1_TCH | TDES1_FT0; 00375 //Give the ownership of the descriptor to the DMA 00376 txCurDmaDesc->tdes0 |= TDES0_OWN; 00377 00378 //Instruct the DMA to poll the transmit descriptor list 00379 MAC->CSR1 = 1; 00380 00381 //Point to the next descriptor in the list 00382 txCurDmaDesc = (A2fxxxm3TxDmaDesc *) txCurDmaDesc->tdes3; 00383 00384 //Data successfully written 00385 return NO_ERROR; 00386 } 00387 00388 00389 /** 00390 * @brief Send a packet 00391 * @param[in] interface Underlying network interface 00392 * @param[in] buffer Multi-part buffer containing the data to send 00393 * @param[in] offset Offset to the first data byte 00394 * @return Error code 00395 **/ 00396 00397 error_t a2fxxxm3EthSendPacket(NetInterface *interface, 00398 const NetBuffer *buffer, size_t offset) 00399 { 00400 size_t length; 00401 00402 //Retrieve the length of the packet 00403 length = netBufferGetLength(buffer) - offset; 00404 00405 //Check the frame length 00406 if(length > A2FXXXM3_ETH_TX_BUFFER_SIZE) 00407 { 00408 //The transmitter can accept another packet 00409 osSetEvent(&interface->nicTxEvent); 00410 //Report an error 00411 return ERROR_INVALID_LENGTH; 00412 } 00413 00414 //Make sure the current buffer is available for writing 00415 if(txCurDmaDesc->tdes0 & TDES0_OWN) 00416 return ERROR_FAILURE; 00417 00418 //Copy user data to the transmit buffer 00419 netBufferRead((uint8_t *) txCurDmaDesc->tdes2, buffer, offset, length); 00420 00421 //Write the number of bytes to send 00422 txCurDmaDesc->tdes1 = length & TDES1_TBS1_MASK; 00423 //Set LS and FS flags as the data fits in a single buffer 00424 txCurDmaDesc->tdes1 |= TDES1_IC | TDES1_LS | TDES1_FS | TDES1_TCH; 00425 //Give the ownership of the descriptor to the DMA 00426 txCurDmaDesc->tdes0 |= TDES0_OWN; 00427 00428 //Instruct the DMA to poll the transmit descriptor list 00429 MAC->CSR1 = 1; 00430 00431 //Point to the next descriptor in the list 00432 txCurDmaDesc = (A2fxxxm3TxDmaDesc *) txCurDmaDesc->tdes3; 00433 00434 //Check whether the next buffer is available for writing 00435 if(!(txCurDmaDesc->tdes0 & TDES0_OWN)) 00436 { 00437 //The transmitter can accept another packet 00438 osSetEvent(&interface->nicTxEvent); 00439 } 00440 00441 //Data successfully written 00442 return NO_ERROR; 00443 } 00444 00445 00446 /** 00447 * @brief Receive a packet 00448 * @param[in] interface Underlying network interface 00449 * @return Error code 00450 **/ 00451 00452 error_t a2fxxxm3EthReceivePacket(NetInterface *interface) 00453 { 00454 error_t error; 00455 size_t n; 00456 00457 //The current buffer is available for reading? 00458 if(!(rxCurDmaDesc->rdes0 & RDES0_OWN)) 00459 { 00460 //FS and LS flags should be set 00461 if((rxCurDmaDesc->rdes0 & RDES0_FS) && (rxCurDmaDesc->rdes0 & RDES0_LS)) 00462 { 00463 //Make sure no error occurred 00464 if(!(rxCurDmaDesc->rdes0 & RDES0_ES)) 00465 { 00466 //Retrieve the length of the frame 00467 n = (rxCurDmaDesc->rdes0 >> RDES0_FL_OFFSET) & RDES0_FL_MASK; 00468 //Limit the number of data to read 00469 n = MIN(n, A2FXXXM3_ETH_RX_BUFFER_SIZE); 00470 00471 //Pass the packet to the upper layer 00472 nicProcessPacket(interface, (uint8_t *) rxCurDmaDesc->rdes2, n); 00473 00474 //Valid packet received 00475 error = NO_ERROR; 00476 } 00477 else 00478 { 00479 //The received packet contains an error 00480 error = ERROR_INVALID_PACKET; 00481 } 00482 } 00483 else 00484 { 00485 //The packet is not valid 00486 error = ERROR_INVALID_PACKET; 00487 } 00488 00489 //Give the ownership of the descriptor back to the DMA 00490 rxCurDmaDesc->rdes0 = RDES0_OWN; 00491 //Point to the next descriptor in the list 00492 rxCurDmaDesc = (A2fxxxm3RxDmaDesc *) rxCurDmaDesc->rdes3; 00493 } 00494 else 00495 { 00496 //No more data in the receive buffer 00497 error = ERROR_BUFFER_EMPTY; 00498 } 00499 00500 //Instruct the DMA to poll the receive descriptor list 00501 MAC->CSR2 = 1; 00502 00503 //Return status code 00504 return error; 00505 } 00506 00507 00508 /** 00509 * @brief Configure multicast MAC address filtering 00510 * @param[in] interface Underlying network interface 00511 * @return Error code 00512 **/ 00513 00514 error_t a2fxxxm3EthSetMulticastFilter(NetInterface *interface) 00515 { 00516 uint_t i; 00517 bool_t acceptMulticast; 00518 00519 //This flag will be set if multicast addresses should be accepted 00520 acceptMulticast = FALSE; 00521 00522 //The MAC filter table contains the multicast MAC addresses 00523 //to accept when receiving an Ethernet frame 00524 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00525 { 00526 //Valid entry? 00527 if(interface->macMulticastFilter[i].refCount > 0) 00528 { 00529 //Accept multicast addresses 00530 acceptMulticast = TRUE; 00531 //We are done 00532 break; 00533 } 00534 } 00535 00536 //Enable the reception of multicast frames if necessary 00537 if(acceptMulticast) 00538 MAC->CSR6 |= CSR6_PM_MASK; 00539 else 00540 MAC->CSR6 &= ~CSR6_PM_MASK; 00541 00542 //Successful processing 00543 return NO_ERROR; 00544 } 00545 00546 00547 /** 00548 * @brief Adjust MAC configuration parameters for proper operation 00549 * @param[in] interface Underlying network interface 00550 * @return Error code 00551 **/ 00552 00553 error_t a2fxxxm3EthUpdateMacConfig(NetInterface *interface) 00554 { 00555 //Stop transmission 00556 while(((MAC->CSR5 & CSR5_TS_MASK) >> CSR5_TS_SHIFT) != CSR5_TS_STOPPED) 00557 MAC->CSR6 &= ~CSR6_ST_MASK; 00558 00559 //Stop reception 00560 while(((MAC->CSR5 & CSR5_RS_MASK) >> CSR5_RS_SHIFT) != CSR5_RS_STOPPED) 00561 MAC->CSR6 &= ~CSR6_SR_MASK; 00562 00563 //10BASE-T or 100BASE-TX operation mode? 00564 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00565 MAC->CSR6 |= CSR6_TTM_MASK; 00566 else 00567 MAC->CSR6 &= ~CSR6_TTM_MASK; 00568 00569 //Half-duplex or full-duplex mode? 00570 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00571 MAC->CSR6 |= CSR6_FD_MASK; 00572 else 00573 MAC->CSR6 &= ~CSR6_FD_MASK; 00574 00575 //Restart transmission and reception 00576 MAC->CSR6 |= CSR6_ST_MASK | CSR6_SR_MASK; 00577 00578 //Successful processing 00579 return NO_ERROR; 00580 } 00581 00582 00583 /** 00584 * @brief Write PHY register 00585 * @param[in] phyAddr PHY address 00586 * @param[in] regAddr Register address 00587 * @param[in] data Register value 00588 **/ 00589 00590 void a2fxxxm3EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00591 { 00592 //Synchronization pattern 00593 a2fxxxm3EthWriteSmi(SMI_SYNC, 32); 00594 //Start of frame 00595 a2fxxxm3EthWriteSmi(SMI_START, 2); 00596 //Set up a write operation 00597 a2fxxxm3EthWriteSmi(SMI_WRITE, 2); 00598 //Write PHY address 00599 a2fxxxm3EthWriteSmi(phyAddr, 5); 00600 //Write register address 00601 a2fxxxm3EthWriteSmi(regAddr, 5); 00602 //Turnaround 00603 a2fxxxm3EthWriteSmi(SMI_TA, 2); 00604 //Write register value 00605 a2fxxxm3EthWriteSmi(data, 16); 00606 //Release MDIO 00607 a2fxxxm3EthReadSmi(1); 00608 } 00609 00610 00611 /** 00612 * @brief Read PHY register 00613 * @param[in] phyAddr PHY address 00614 * @param[in] regAddr Register address 00615 * @return Register value 00616 **/ 00617 00618 uint16_t a2fxxxm3EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00619 { 00620 uint16_t data; 00621 00622 //Synchronization pattern 00623 a2fxxxm3EthWriteSmi(SMI_SYNC, 32); 00624 //Start of frame 00625 a2fxxxm3EthWriteSmi(SMI_START, 2); 00626 //Set up a read operation 00627 a2fxxxm3EthWriteSmi(SMI_READ, 2); 00628 //Write PHY address 00629 a2fxxxm3EthWriteSmi(phyAddr, 5); 00630 //Write register address 00631 a2fxxxm3EthWriteSmi(regAddr, 5); 00632 //Turnaround to avoid contention 00633 a2fxxxm3EthReadSmi(1); 00634 //Read register value 00635 data = a2fxxxm3EthReadSmi(16); 00636 //Force the PHY to release the MDIO pin 00637 a2fxxxm3EthReadSmi(1); 00638 00639 //Return PHY register contents 00640 return data; 00641 } 00642 00643 00644 /** 00645 * @brief SMI write operation 00646 * @param[in] data Raw data to be written 00647 * @param[in] length Number of bits to be written 00648 **/ 00649 00650 void a2fxxxm3EthWriteSmi(uint32_t data, uint_t length) 00651 { 00652 //Skip the most significant bits since they are meaningless 00653 data <<= 32 - length; 00654 00655 //Configure MDIO as an output 00656 MAC->CSR9 |= CSR9_MDEN_MASK; 00657 00658 //Write the specified number of bits 00659 while(length--) 00660 { 00661 //Write MDIO 00662 if(data & 0x80000000) 00663 MAC->CSR9 |= CSR9_MDO_MASK; 00664 else 00665 MAC->CSR9 &= ~CSR9_MDO_MASK; 00666 00667 //Assert MDC 00668 usleep(1); 00669 MAC->CSR9 |= CSR9_MDC_MASK; 00670 //Deassert MDC 00671 usleep(1); 00672 MAC->CSR9 &= ~CSR9_MDC_MASK; 00673 00674 //Rotate data 00675 data <<= 1; 00676 } 00677 } 00678 00679 00680 /** 00681 * @brief SMI read operation 00682 * @param[in] length Number of bits to be read 00683 * @return Data resulting from the MDIO read operation 00684 **/ 00685 00686 uint32_t a2fxxxm3EthReadSmi(uint_t length) 00687 { 00688 uint32_t data = 0; 00689 00690 //Configure MDIO as an input 00691 MAC->CSR9 &= ~CSR9_MDEN_MASK; 00692 00693 //Read the specified number of bits 00694 while(length--) 00695 { 00696 //Rotate data 00697 data <<= 1; 00698 00699 //Assert MDC 00700 MAC->CSR9 |= CSR9_MDC_MASK; 00701 usleep(1); 00702 //Deassert MDC 00703 MAC->CSR9 &= ~CSR9_MDC_MASK; 00704 usleep(1); 00705 00706 //Check MDIO state 00707 if(MAC->CSR9 & CSR9_MDI_MASK) 00708 data |= 0x00000001; 00709 } 00710 00711 //Return the received data 00712 return data; 00713 } 00714 00715 00716 /** 00717 * @brief CRC calculation 00718 * @param[in] data Pointer to the data over which to calculate the CRC 00719 * @param[in] length Number of bytes to process 00720 * @return Resulting CRC value 00721 **/ 00722 00723 uint32_t a2fxxxm3EthCalcCrc(const void *data, size_t length) 00724 { 00725 uint_t i; 00726 uint_t j; 00727 00728 //Point to the data over which to calculate the CRC 00729 const uint8_t *p = (uint8_t *) data; 00730 //CRC preset value 00731 uint32_t crc = 0xFFFFFFFF; 00732 00733 //Loop through data 00734 for(i = 0; i < length; i++) 00735 { 00736 //Update CRC value 00737 crc ^= p[i]; 00738 00739 //The message is processed bit by bit 00740 for(j = 0; j < 8; j++) 00741 { 00742 //Update CRC value 00743 if(crc & 0x00000001) 00744 crc = (crc >> 1) ^ 0xEDB88320; 00745 else 00746 crc = crc >> 1; 00747 } 00748 } 00749 00750 //Return CRC value 00751 return crc; 00752 } 00753
Generated on Tue Jul 12 2022 17:10:12 by
