Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
str912_eth.c
Go to the documentation of this file.
00001 /** 00002 * @file str912_eth.c 00003 * @brief STR9 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 "91x_lib.h" 00034 #include "core/net.h" 00035 #include "drivers/str912_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[STR912_ETH_TX_BUFFER_COUNT][STR912_ETH_TX_BUFFER_SIZE]; 00047 //Receive buffer 00048 #pragma data_alignment = 4 00049 static uint8_t rxBuffer[STR912_ETH_RX_BUFFER_COUNT][STR912_ETH_RX_BUFFER_SIZE]; 00050 //Transmit DMA descriptors 00051 #pragma data_alignment = 4 00052 static Str912TxDmaDesc txDmaDesc[STR912_ETH_TX_BUFFER_COUNT]; 00053 //Receive DMA descriptors 00054 #pragma data_alignment = 4 00055 static Str912RxDmaDesc rxDmaDesc[STR912_ETH_RX_BUFFER_COUNT]; 00056 00057 //Keil MDK-ARM or GCC compiler? 00058 #else 00059 00060 //Transmit buffer 00061 static uint8_t txBuffer[STR912_ETH_TX_BUFFER_COUNT][STR912_ETH_TX_BUFFER_SIZE] 00062 __attribute__((aligned(4))); 00063 //Receive buffer 00064 static uint8_t rxBuffer[STR912_ETH_RX_BUFFER_COUNT][STR912_ETH_RX_BUFFER_SIZE] 00065 __attribute__((aligned(4))); 00066 //Transmit DMA descriptors 00067 static Str912TxDmaDesc txDmaDesc[STR912_ETH_TX_BUFFER_COUNT] 00068 __attribute__((aligned(4))); 00069 //Receive DMA descriptors 00070 static Str912RxDmaDesc rxDmaDesc[STR912_ETH_RX_BUFFER_COUNT] 00071 __attribute__((aligned(4))); 00072 00073 #endif 00074 00075 //Pointer to the current TX DMA descriptor 00076 static Str912TxDmaDesc *txCurDmaDesc; 00077 //Pointer to the current RX DMA descriptor 00078 static Str912RxDmaDesc *rxCurDmaDesc; 00079 00080 00081 /** 00082 * @brief STR912 Ethernet MAC driver 00083 **/ 00084 00085 const NicDriver str912EthDriver = 00086 { 00087 NIC_TYPE_ETHERNET, 00088 ETH_MTU, 00089 str912EthInit, 00090 str912EthTick, 00091 str912EthEnableIrq, 00092 str912EthDisableIrq, 00093 str912EthEventHandler, 00094 str912EthSendPacket, 00095 str912EthSetMulticastFilter, 00096 str912EthUpdateMacConfig, 00097 str912EthWritePhyReg, 00098 str912EthReadPhyReg, 00099 TRUE, 00100 TRUE, 00101 TRUE, 00102 FALSE 00103 }; 00104 00105 00106 /** 00107 * @brief STR912 Ethernet MAC initialization 00108 * @param[in] interface Underlying network interface 00109 * @return Error code 00110 **/ 00111 00112 error_t str912EthInit(NetInterface *interface) 00113 { 00114 error_t error; 00115 00116 //Debug message 00117 TRACE_INFO("Initializing STR912 Ethernet MAC...\r\n"); 00118 00119 //Save underlying network interface 00120 nicDriverInterface = interface; 00121 00122 //GPIO configuration 00123 str912EthInitGpio(interface); 00124 00125 //Enable Ethernet MAC clock 00126 SCU_AHBPeriphClockConfig(__ENET, ENABLE); 00127 00128 //Reset Ethernet MAC peripheral 00129 SCU_AHBPeriphReset(__ENET, ENABLE); 00130 SCU_AHBPeriphReset(__ENET, DISABLE); 00131 00132 //MAC DMA software reset 00133 ENET_DMA->SCR |= ENET_SCR_SRESET; 00134 ENET_DMA->SCR &= ~ENET_SCR_SRESET; 00135 00136 //Use default MAC configuration 00137 ENET_MAC->MCR = ENET_MCR_AFM_1 | ENET_MCR_RVFF | 00138 ENET_MCR_BL_1 | ENET_MCR_DCE | ENET_MCR_RVBE; 00139 00140 //Adjust HCLK divider depending on system clock frequency 00141 if(SCU_GetHCLKFreqValue() > 50000) 00142 ENET_MAC->MCR |= ENET_MCR_PS_1; 00143 00144 //PHY transceiver initialization 00145 error = interface->phyDriver->init(interface); 00146 //Failed to initialize PHY transceiver? 00147 if(error) 00148 return error; 00149 00150 //Set the MAC address 00151 ENET_MAC->MAL = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16); 00152 ENET_MAC->MAH = interface->macAddr.w[2]; 00153 00154 //Initialize hash table 00155 ENET_MAC->MCLA = 0; 00156 ENET_MAC->MCHA = 0; 00157 00158 //DMA configuration 00159 //ENET_DMA->SCR = 0; 00160 00161 //Force a DMA abort 00162 ENET_DMA->TXSTR |= ENET_TXSTR_DMA_EN; 00163 ENET_DMA->RXSTR |= ENET_RXSTR_DMA_EN; 00164 00165 //Set descriptor fetch delay 00166 ENET_DMA->TXSTR = ENET_TXSTR_DFETCH_DLY_DEFAULT | ENET_TXSTR_UNDER_RUN; 00167 ENET_DMA->RXSTR = ENET_RXSTR_DFETCH_DLY_DEFAULT; 00168 00169 //Initialize DMA descriptor lists 00170 str912EthInitDmaDesc(interface); 00171 00172 //Clear interrupt flags 00173 ENET_DMA->ISR = ENET_ISR_TX_CURR_DONE | ENET_ISR_RX_CURR_DONE; 00174 //Configure DMA interrupts as desired 00175 ENET_DMA->IER = ENET_IER_TX_CURR_DONE_EN | ENET_IER_RX_CURR_DONE_EN; 00176 00177 //Configure Ethernet interrupt priority 00178 VIC_Config(ENET_ITLine, VIC_IRQ, STR912_ETH_IRQ_PRIORITY); 00179 00180 //Enable MAC transmission and reception 00181 ENET_MAC->MCR |= ENET_MCR_TE | ENET_MCR_RE; 00182 //Instruct the DMA to poll the receive descriptor list 00183 ENET_DMA->RXSTR |= ENET_RXSTR_START_FETCH; 00184 00185 //Accept any packets from the upper layer 00186 osSetEvent(&interface->nicTxEvent); 00187 00188 //Successful initialization 00189 return NO_ERROR; 00190 } 00191 00192 00193 //STR-E912 evaluation board? 00194 #if defined(USE_STR_E912) 00195 00196 /** 00197 * @brief GPIO configuration 00198 * @param[in] interface Underlying network interface 00199 **/ 00200 00201 void str912EthInitGpio(NetInterface *interface) 00202 { 00203 GPIO_InitTypeDef GPIO_InitStructure; 00204 00205 //Enable GPIO clocks 00206 SCU_APBPeriphClockConfig(__GPIO0, ENABLE); 00207 SCU_APBPeriphClockConfig(__GPIO1, ENABLE); 00208 SCU_APBPeriphClockConfig(__GPIO5, ENABLE); 00209 00210 //Enable MII_PHYCLK clock 00211 SCU_PHYCLKConfig(ENABLE); 00212 00213 //Configure MII_TX_CLK (P0.0), MII_RXD0 (P0.2), MII_RXD1 (P0.3), MII_RXD2 (P0.4), 00214 //MII_RXD3 (P0.5), MII_RX_CLK (P0.6) and MII_RX_DV (P0.7) 00215 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3 | 00216 GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; 00217 00218 GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; 00219 GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable; 00220 GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; 00221 GPIO_Init(GPIO0, &GPIO_InitStructure); 00222 00223 //Configure MII_RX_ER (P1.0), MII_COL (P1.5) and MII_CRS (P1.6) 00224 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_5 | GPIO_Pin_6; 00225 GPIO_InitStructure.GPIO_Direction = GPIO_PinInput; 00226 GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable; 00227 GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1; 00228 GPIO_Init(GPIO1, &GPIO_InitStructure); 00229 00230 //Configure MII_TXD0 (P1.1), MII_TXD1 (P1.2), MII_TXD2 (P1.3), 00231 //MII_TXD3 (P1.4) and MII_MDC (P1.7) 00232 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | 00233 GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7; 00234 00235 GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput; 00236 GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull; 00237 GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable; 00238 GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2; 00239 GPIO_Init(GPIO1, &GPIO_InitStructure); 00240 00241 //Configure MII_PHYCLK (P5.2) and MII_TX_EN (P5.3) 00242 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; 00243 GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput; 00244 GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull; 00245 GPIO_InitStructure.GPIO_IPInputConnected = GPIO_IPInputConnected_Disable; 00246 GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2; 00247 GPIO_Init(GPIO5, &GPIO_InitStructure); 00248 } 00249 00250 #endif 00251 00252 00253 /** 00254 * @brief Initialize DMA descriptor lists 00255 * @param[in] interface Underlying network interface 00256 **/ 00257 00258 void str912EthInitDmaDesc(NetInterface *interface) 00259 { 00260 uint_t i; 00261 00262 //Initialize TX DMA descriptor list 00263 for(i = 0; i < STR912_ETH_TX_BUFFER_COUNT; i++) 00264 { 00265 //Control word 00266 txDmaDesc[i].ctrl = ENET_TDES_CTRL_NXT_EN; 00267 //Transmit buffer address 00268 txDmaDesc[i].start = (uint32_t) txBuffer[i]; 00269 //Next descriptor address 00270 txDmaDesc[i].next = (uint32_t) &txDmaDesc[i + 1] | ENET_TDES_NEXT_NPOL_EN; 00271 //Status word 00272 txDmaDesc[i].status = 0; 00273 } 00274 00275 //The last descriptor is chained to the first entry 00276 txDmaDesc[i - 1].next = (uint32_t) &txDmaDesc[0] | ENET_TDES_NEXT_NPOL_EN; 00277 //Point to the very first descriptor 00278 txCurDmaDesc = &txDmaDesc[0]; 00279 00280 //Initialize RX DMA descriptor list 00281 for(i = 0; i < STR912_ETH_RX_BUFFER_COUNT; i++) 00282 { 00283 //Control word 00284 rxDmaDesc[i].ctrl = ENET_RDES_CTRL_NXT_EN | STR912_ETH_RX_BUFFER_SIZE; 00285 //Receive buffer address 00286 rxDmaDesc[i].start = (uint32_t) rxBuffer[i]; 00287 //Next descriptor address 00288 rxDmaDesc[i].next = (uint32_t) &rxDmaDesc[i + 1] | ENET_RDES_NEXT_NPOL_EN; 00289 //Status word 00290 rxDmaDesc[i].status = ENET_RDES_STATUS_VALID; 00291 } 00292 00293 //The last descriptor is chained to the first entry 00294 rxDmaDesc[i - 1].next = (uint32_t) &rxDmaDesc[0] | ENET_RDES_NEXT_NPOL_EN; 00295 //Point to the very first descriptor 00296 rxCurDmaDesc = &rxDmaDesc[0]; 00297 00298 //Start location of the TX descriptor list 00299 ENET_DMA->TXNDAR = (uint32_t) txDmaDesc | ENET_TDES_NEXT_NPOL_EN; 00300 //Start location of the RX descriptor list 00301 ENET_DMA->RXNDAR = (uint32_t) rxDmaDesc | ENET_RDES_NEXT_NPOL_EN; 00302 } 00303 00304 00305 /** 00306 * @brief STR912 Ethernet MAC timer handler 00307 * 00308 * This routine is periodically called by the TCP/IP stack to 00309 * handle periodic operations such as polling the link state 00310 * 00311 * @param[in] interface Underlying network interface 00312 **/ 00313 00314 void str912EthTick(NetInterface *interface) 00315 { 00316 //Handle periodic operations 00317 interface->phyDriver->tick(interface); 00318 } 00319 00320 00321 /** 00322 * @brief Enable interrupts 00323 * @param[in] interface Underlying network interface 00324 **/ 00325 00326 void str912EthEnableIrq(NetInterface *interface) 00327 { 00328 //Enable Ethernet MAC interrupts 00329 VIC_ITCmd(ENET_ITLine, ENABLE); 00330 //Enable Ethernet PHY interrupts 00331 interface->phyDriver->enableIrq(interface); 00332 } 00333 00334 00335 /** 00336 * @brief Disable interrupts 00337 * @param[in] interface Underlying network interface 00338 **/ 00339 00340 void str912EthDisableIrq(NetInterface *interface) 00341 { 00342 //Disable Ethernet MAC interrupts 00343 VIC_ITCmd(ENET_ITLine, DISABLE); 00344 //Disable Ethernet PHY interrupts 00345 interface->phyDriver->disableIrq(interface); 00346 } 00347 00348 00349 /** 00350 * @brief STR912 Ethernet MAC interrupt service routine 00351 **/ 00352 00353 void ENET_IRQHandler(void) 00354 { 00355 bool_t flag; 00356 uint32_t status; 00357 00358 //Enter interrupt service routine 00359 osEnterIsr(); 00360 00361 //This flag will be set if a higher priority task must be woken 00362 flag = FALSE; 00363 00364 //Read DMA status register 00365 status = ENET_DMA->ISR; 00366 00367 //A packet has been transmitted? 00368 if(status & ENET_ISR_TX_CURR_DONE) 00369 { 00370 //Clear TX_CURR_DONE interrupt flag 00371 ENET_DMA->ISR = ENET_ISR_TX_CURR_DONE; 00372 00373 //Check whether the TX buffer is available for writing 00374 if(!(txCurDmaDesc->status & ENET_TDES_STATUS_VALID)) 00375 { 00376 //Notify the TCP/IP stack that the transmitter is ready to send 00377 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00378 } 00379 } 00380 00381 //A packet has been received? 00382 if(status & ENET_ISR_RX_CURR_DONE) 00383 { 00384 //Disable RX_CURR_DONE interrupt 00385 ENET_DMA->IER &= ~ENET_IER_RX_CURR_DONE_EN; 00386 00387 //Set event flag 00388 nicDriverInterface->nicEvent = TRUE; 00389 //Notify the TCP/IP stack of the event 00390 flag |= osSetEventFromIsr(&netEvent); 00391 } 00392 00393 //Leave interrupt service routine 00394 osExitIsr(flag); 00395 } 00396 00397 00398 /** 00399 * @brief STR912 Ethernet MAC event handler 00400 * @param[in] interface Underlying network interface 00401 **/ 00402 00403 void str912EthEventHandler(NetInterface *interface) 00404 { 00405 error_t error; 00406 00407 //Packet received? 00408 if(ENET_DMA->ISR & ENET_ISR_RX_CURR_DONE) 00409 { 00410 //Clear interrupt flag 00411 ENET_DMA->ISR = ENET_ISR_RX_CURR_DONE; 00412 00413 //Process all pending packets 00414 do 00415 { 00416 //Read incoming packet 00417 error = str912EthReceivePacket(interface); 00418 00419 //No more data in the receive buffer? 00420 } while(error != ERROR_BUFFER_EMPTY); 00421 } 00422 00423 //Re-enable DMA interrupts 00424 ENET_DMA->IER = ENET_IER_TX_CURR_DONE_EN | ENET_IER_RX_CURR_DONE_EN; 00425 } 00426 00427 00428 /** 00429 * @brief Send a packet 00430 * @param[in] interface Underlying network interface 00431 * @param[in] buffer Multi-part buffer containing the data to send 00432 * @param[in] offset Offset to the first data byte 00433 * @return Error code 00434 **/ 00435 00436 error_t str912EthSendPacket(NetInterface *interface, 00437 const NetBuffer *buffer, size_t offset) 00438 { 00439 size_t length; 00440 00441 //Retrieve the length of the packet 00442 length = netBufferGetLength(buffer) - offset; 00443 00444 //Check the frame length 00445 if(length > STR912_ETH_TX_BUFFER_SIZE) 00446 { 00447 //The transmitter can accept another packet 00448 osSetEvent(&interface->nicTxEvent); 00449 //Report an error 00450 return ERROR_INVALID_LENGTH; 00451 } 00452 00453 //Make sure the current buffer is available for writing 00454 if(txCurDmaDesc->status & ENET_TDES_STATUS_VALID) 00455 return ERROR_FAILURE; 00456 00457 //Copy user data to the transmit buffer 00458 netBufferRead((uint8_t *) (txCurDmaDesc->start & ENET_TDES_START_ADDR), 00459 buffer, offset, length); 00460 00461 //Write the number of bytes to send 00462 txCurDmaDesc->ctrl = ENET_TDES_CTRL_NXT_EN | length; 00463 //Give the ownership of the descriptor to the DMA 00464 txCurDmaDesc->status = ENET_TDES_STATUS_VALID; 00465 00466 //Instruct the DMA to poll the transmit descriptor list 00467 ENET_DMA->TXSTR |= ENET_TXSTR_START_FETCH; 00468 00469 //Point to the next descriptor in the list 00470 txCurDmaDesc = (Str912TxDmaDesc *) (txCurDmaDesc->next & ENET_TDES_NEXT_ADDR); 00471 00472 //Check whether the next buffer is available for writing 00473 if(!(txCurDmaDesc->status & ENET_TDES_STATUS_VALID)) 00474 { 00475 //The transmitter can accept another packet 00476 osSetEvent(&interface->nicTxEvent); 00477 } 00478 00479 //Data successfully written 00480 return NO_ERROR; 00481 } 00482 00483 00484 /** 00485 * @brief Receive a packet 00486 * @param[in] interface Underlying network interface 00487 * @return Error code 00488 **/ 00489 00490 error_t str912EthReceivePacket(NetInterface *interface) 00491 { 00492 error_t error; 00493 size_t n; 00494 uint8_t *p; 00495 00496 //The current buffer is available for reading? 00497 if(!(rxCurDmaDesc->status & ENET_RDES_STATUS_VALID)) 00498 { 00499 //Make sure no error occurred 00500 if(!(rxCurDmaDesc->status & ENET_RDES_STATUS_ERROR)) 00501 { 00502 //Point to the received frame 00503 p = (uint8_t *) (rxCurDmaDesc->start & ENET_RDES_START_ADDR); 00504 00505 //Retrieve the length of the frame 00506 n = rxCurDmaDesc->status & ENET_RDES_STATUS_FL; 00507 //Limit the number of data to read 00508 n = MIN(n, STR912_ETH_RX_BUFFER_SIZE); 00509 00510 //Pass the packet to the upper layer 00511 nicProcessPacket(interface, p, n); 00512 00513 //Valid packet received 00514 error = NO_ERROR; 00515 } 00516 else 00517 { 00518 //The received packet contains an error 00519 error = ERROR_INVALID_PACKET; 00520 } 00521 00522 //Give the ownership of the descriptor back to the DMA 00523 rxCurDmaDesc->status = ENET_RDES_STATUS_VALID; 00524 //Point to the next descriptor in the list 00525 rxCurDmaDesc = (Str912RxDmaDesc *) (rxCurDmaDesc->next & ENET_RDES_NEXT_ADDR); 00526 } 00527 else 00528 { 00529 //No more data in the receive buffer 00530 error = ERROR_BUFFER_EMPTY; 00531 } 00532 00533 //Instruct the DMA to poll the receive descriptor list 00534 ENET_DMA->RXSTR |= ENET_RXSTR_START_FETCH; 00535 00536 //Return status code 00537 return error; 00538 } 00539 00540 00541 /** 00542 * @brief Configure multicast MAC address filtering 00543 * @param[in] interface Underlying network interface 00544 * @return Error code 00545 **/ 00546 00547 error_t str912EthSetMulticastFilter(NetInterface *interface) 00548 { 00549 uint_t i; 00550 uint_t k; 00551 uint32_t crc; 00552 uint32_t hashTable[2]; 00553 MacFilterEntry *entry; 00554 00555 //Debug message 00556 TRACE_DEBUG("Updating STR912 hash table...\r\n"); 00557 00558 //Clear hash table 00559 hashTable[0] = 0; 00560 hashTable[1] = 0; 00561 00562 //The MAC filter table contains the multicast MAC addresses 00563 //to accept when receiving an Ethernet frame 00564 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00565 { 00566 //Point to the current entry 00567 entry = &interface->macMulticastFilter[i]; 00568 00569 //Valid entry? 00570 if(entry->refCount > 0) 00571 { 00572 //Compute CRC over the current MAC address 00573 crc = str912EthCalcCrc(&entry->addr, sizeof(MacAddr)); 00574 00575 //The upper 6 bits in the CRC register are used to index the 00576 //contents of the hash table 00577 k = (crc >> 26) & 0x3F; 00578 00579 //Update hash table contents 00580 hashTable[k / 32] |= (1 << (k % 32)); 00581 } 00582 } 00583 00584 //Write the hash table 00585 ENET_MAC->MCLA = hashTable[0]; 00586 ENET_MAC->MCHA = hashTable[1]; 00587 00588 //Debug message 00589 TRACE_DEBUG(" ENET_MCLA = %08" PRIX32 "\r\n", ENET_MAC->MCLA); 00590 TRACE_DEBUG(" ENET_MCHA = %08" PRIX32 "\r\n", ENET_MAC->MCHA); 00591 00592 //Successful processing 00593 return NO_ERROR; 00594 } 00595 00596 00597 /** 00598 * @brief Adjust MAC configuration parameters for proper operation 00599 * @param[in] interface Underlying network interface 00600 * @return Error code 00601 **/ 00602 00603 error_t str912EthUpdateMacConfig(NetInterface *interface) 00604 { 00605 uint32_t config; 00606 00607 //Read current MAC configuration 00608 config = ENET_MAC->MCR; 00609 00610 //Half-duplex or full-duplex mode? 00611 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00612 { 00613 //Full-duplex mode 00614 config |= ENET_MCR_FDM; 00615 //Enable the reception path during transmission 00616 config &= ~ENET_MCR_DRO; 00617 } 00618 else 00619 { 00620 //Half-duplex mode 00621 config &= ~ENET_MCR_FDM; 00622 //Disable the reception path during transmission 00623 config |= ENET_MCR_DRO; 00624 } 00625 00626 //Update MAC configuration register 00627 ENET_MAC->MCR = config; 00628 00629 //Successful processing 00630 return NO_ERROR; 00631 } 00632 00633 00634 /** 00635 * @brief Write PHY register 00636 * @param[in] phyAddr PHY address 00637 * @param[in] regAddr Register address 00638 * @param[in] data Register value 00639 **/ 00640 00641 void str912EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00642 { 00643 uint32_t value; 00644 00645 //Set up a write operation 00646 value = ENET_MIIA_WR | ENET_MIIA_BUSY; 00647 //PHY address 00648 value |= (phyAddr << 11) & ENET_MIIA_PADDR; 00649 //Register address 00650 value |= (regAddr << 6) & ENET_MIIA_RADDR; 00651 00652 //Data to be written in the PHY register 00653 ENET_MAC->MIID = data & ENET_MIID_RDATA; 00654 00655 //Start a write operation 00656 ENET_MAC->MIIA = value; 00657 //Wait for the write to complete 00658 while(ENET_MAC->MIIA & ENET_MIIA_BUSY); 00659 } 00660 00661 00662 /** 00663 * @brief Read PHY register 00664 * @param[in] phyAddr PHY address 00665 * @param[in] regAddr Register address 00666 * @return Register value 00667 **/ 00668 00669 uint16_t str912EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00670 { 00671 uint32_t value; 00672 00673 //Set up a read operation 00674 value = ENET_MIIA_BUSY; 00675 //PHY address 00676 value |= (phyAddr << 11) & ENET_MIIA_PADDR; 00677 //Register address 00678 value |= (regAddr << 6) & ENET_MIIA_RADDR; 00679 00680 //Start a read operation 00681 ENET_MAC->MIIA = value; 00682 //Wait for the read to complete 00683 while(ENET_MAC->MIIA & ENET_MIIA_BUSY); 00684 00685 //Return PHY register contents 00686 return ENET_MAC->MIID & ENET_MIID_RDATA; 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 str912EthCalcCrc(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:17 by
