Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
samv71_eth.c
00001 /** 00002 * @file samv71_eth.c 00003 * @brief SAMV71 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 <limits.h> 00034 #include "samv71.h" 00035 #include "core/net.h" 00036 #include "drivers/samv71_eth.h" 00037 #include "debug.h" 00038 00039 //Underlying network interface 00040 static NetInterface *nicDriverInterface; 00041 00042 //IAR EWARM compiler? 00043 #if defined(__ICCARM__) 00044 00045 //TX buffer 00046 #pragma data_alignment = 8 00047 #pragma location = ".ram_no_cache" 00048 static uint8_t txBuffer[SAMV71_ETH_TX_BUFFER_COUNT][SAMV71_ETH_TX_BUFFER_SIZE]; 00049 //RX buffer 00050 #pragma data_alignment = 8 00051 #pragma location = ".ram_no_cache" 00052 static uint8_t rxBuffer[SAMV71_ETH_RX_BUFFER_COUNT][SAMV71_ETH_RX_BUFFER_SIZE]; 00053 //TX buffer descriptors 00054 #pragma data_alignment = 4 00055 #pragma location = ".ram_no_cache" 00056 static Samv71TxBufferDesc txBufferDesc[SAMV71_ETH_TX_BUFFER_COUNT]; 00057 //RX buffer descriptors 00058 #pragma data_alignment = 4 00059 #pragma location = ".ram_no_cache" 00060 static Samv71RxBufferDesc rxBufferDesc[SAMV71_ETH_RX_BUFFER_COUNT]; 00061 00062 //Dummy TX buffer 00063 #pragma data_alignment = 8 00064 #pragma location = ".ram_no_cache" 00065 static uint8_t dummyTxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE]; 00066 //Dummy RX buffer 00067 #pragma data_alignment = 8 00068 #pragma location = ".ram_no_cache" 00069 static uint8_t dummyRxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE]; 00070 //Dummy TX buffer descriptors 00071 #pragma data_alignment = 4 00072 #pragma location = ".ram_no_cache" 00073 static Samv71TxBufferDesc dummyTxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT]; 00074 //Dummy RX buffer descriptors 00075 #pragma data_alignment = 4 00076 #pragma location = ".ram_no_cache" 00077 static Samv71RxBufferDesc dummyRxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT]; 00078 00079 //Keil MDK-ARM or GCC compiler? 00080 #else 00081 00082 //TX buffer 00083 static uint8_t txBuffer[SAMV71_ETH_TX_BUFFER_COUNT][SAMV71_ETH_TX_BUFFER_SIZE] 00084 __attribute__((aligned(8), __section__(".ram_no_cache"))); 00085 //RX buffer 00086 static uint8_t rxBuffer[SAMV71_ETH_RX_BUFFER_COUNT][SAMV71_ETH_RX_BUFFER_SIZE] 00087 __attribute__((aligned(8), __section__(".ram_no_cache"))); 00088 //TX buffer descriptors 00089 static Samv71TxBufferDesc txBufferDesc[SAMV71_ETH_TX_BUFFER_COUNT] 00090 __attribute__((aligned(4), __section__(".ram_no_cache"))); 00091 //RX buffer descriptors 00092 static Samv71RxBufferDesc rxBufferDesc[SAMV71_ETH_RX_BUFFER_COUNT] 00093 __attribute__((aligned(4), __section__(".ram_no_cache"))); 00094 00095 //Dummy TX buffer 00096 static uint8_t dummyTxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE] 00097 __attribute__((aligned(8), __section__(".ram_no_cache"))); 00098 //Dummy RX buffer 00099 static uint8_t dummyRxBuffer[SAMV71_ETH_DUMMY_BUFFER_COUNT][SAMV71_ETH_DUMMY_BUFFER_SIZE] 00100 __attribute__((aligned(8), __section__(".ram_no_cache"))); 00101 //Dummy TX buffer descriptors 00102 static Samv71TxBufferDesc dummyTxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT] 00103 __attribute__((aligned(4), __section__(".ram_no_cache"))); 00104 //Dummy RX buffer descriptors 00105 static Samv71RxBufferDesc dummyRxBufferDesc[SAMV71_ETH_DUMMY_BUFFER_COUNT] 00106 __attribute__((aligned(4), __section__(".ram_no_cache"))); 00107 00108 #endif 00109 00110 //TX buffer index 00111 static uint_t txBufferIndex; 00112 //RX buffer index 00113 static uint_t rxBufferIndex; 00114 00115 00116 /** 00117 * @brief SAMV71 Ethernet MAC driver 00118 **/ 00119 00120 const NicDriver samv71EthDriver = 00121 { 00122 NIC_TYPE_ETHERNET, 00123 ETH_MTU, 00124 samv71EthInit, 00125 samv71EthTick, 00126 samv71EthEnableIrq, 00127 samv71EthDisableIrq, 00128 samv71EthEventHandler, 00129 samv71EthSendPacket, 00130 samv71EthSetMulticastFilter, 00131 samv71EthUpdateMacConfig, 00132 samv71EthWritePhyReg, 00133 samv71EthReadPhyReg, 00134 TRUE, 00135 TRUE, 00136 TRUE, 00137 FALSE 00138 }; 00139 00140 00141 /** 00142 * @brief SAMV71 Ethernet MAC initialization 00143 * @param[in] interface Underlying network interface 00144 * @return Error code 00145 **/ 00146 00147 error_t samv71EthInit(NetInterface *interface) 00148 { 00149 error_t error; 00150 volatile uint32_t status; 00151 00152 //Debug message 00153 TRACE_INFO("Initializing SAMV71 Ethernet MAC...\r\n"); 00154 00155 //Save underlying network interface 00156 nicDriverInterface = interface; 00157 00158 //Enable GMAC peripheral clock 00159 PMC->PMC_PCER1 = (1 << (ID_GMAC - 32)); 00160 00161 //GPIO configuration 00162 samv71EthInitGpio(interface); 00163 00164 //Configure MDC clock speed 00165 GMAC->GMAC_NCFGR = GMAC_NCFGR_CLK_MCK_96; 00166 //Enable management port (MDC and MDIO) 00167 GMAC->GMAC_NCR |= GMAC_NCR_MPE; 00168 00169 //PHY transceiver initialization 00170 error = interface->phyDriver->init(interface); 00171 //Failed to initialize PHY transceiver? 00172 if(error) 00173 return error; 00174 00175 //Set the MAC address 00176 GMAC->GMAC_SA[0].GMAC_SAB = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16); 00177 GMAC->GMAC_SA[0].GMAC_SAT = interface->macAddr.w[2]; 00178 00179 //Configure the receive filter 00180 GMAC->GMAC_NCFGR |= GMAC_NCFGR_UNIHEN | GMAC_NCFGR_MTIHEN; 00181 00182 //DMA configuration 00183 GMAC->GMAC_DCFGR = GMAC_DCFGR_DRBS(SAMV71_ETH_RX_BUFFER_SIZE / 64) | 00184 GMAC_DCFGR_TXPBMS | GMAC_DCFGR_RXBMS_FULL | GMAC_DCFGR_FBLDO_INCR4; 00185 00186 GMAC->GMAC_RBSRPQ[0] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64); 00187 GMAC->GMAC_RBSRPQ[1] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64); 00188 GMAC->GMAC_RBSRPQ[2] = GMAC_RBSRPQ_RBS(SAMV71_ETH_DUMMY_BUFFER_SIZE / 64); 00189 00190 //Initialize hash table 00191 GMAC->GMAC_HRB = 0; 00192 GMAC->GMAC_HRT = 0; 00193 00194 //Initialize buffer descriptors 00195 samv71EthInitBufferDesc(interface); 00196 00197 //Clear transmit status register 00198 GMAC->GMAC_TSR = GMAC_TSR_HRESP | GMAC_TSR_TXCOMP | GMAC_TSR_TFC | 00199 GMAC_TSR_TXGO | GMAC_TSR_RLE | GMAC_TSR_COL | GMAC_TSR_UBR; 00200 //Clear receive status register 00201 GMAC->GMAC_RSR = GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA; 00202 00203 //First disable all GMAC interrupts 00204 GMAC->GMAC_IDR = 0xFFFFFFFF; 00205 GMAC->GMAC_IDRPQ[0] = 0xFFFFFFFF; 00206 GMAC->GMAC_IDRPQ[1] = 0xFFFFFFFF; 00207 GMAC->GMAC_IDRPQ[2] = 0xFFFFFFFF; 00208 00209 //Only the desired ones are enabled 00210 GMAC->GMAC_IER = GMAC_IER_HRESP | GMAC_IER_ROVR | GMAC_IER_TCOMP | GMAC_IER_TFC | 00211 GMAC_IER_RLEX | GMAC_IER_TUR | GMAC_IER_RXUBR | GMAC_IER_RCOMP; 00212 00213 //Read GMAC ISR register to clear any pending interrupt 00214 status = GMAC->GMAC_ISR; 00215 00216 //Set priority grouping (3 bits for pre-emption priority, no bits for subpriority) 00217 NVIC_SetPriorityGrouping(SAMV71_ETH_IRQ_PRIORITY_GROUPING); 00218 00219 //Configure GMAC interrupt priority 00220 NVIC_SetPriority(GMAC_IRQn, NVIC_EncodePriority(SAMV71_ETH_IRQ_PRIORITY_GROUPING, 00221 SAMV71_ETH_IRQ_GROUP_PRIORITY, SAMV71_ETH_IRQ_SUB_PRIORITY)); 00222 00223 //Enable the GMAC to transmit and receive data 00224 GMAC->GMAC_NCR |= GMAC_NCR_TXEN | GMAC_NCR_RXEN; 00225 00226 //Accept any packets from the upper layer 00227 osSetEvent(&interface->nicTxEvent); 00228 00229 //Successful initialization 00230 return NO_ERROR; 00231 } 00232 00233 00234 //SAMV71-Xplained-Ultra evaluation board? 00235 #if defined(USE_SAMV71_XPLAINED_ULTRA) 00236 00237 /** 00238 * @brief GPIO configuration 00239 * @param[in] interface Underlying network interface 00240 **/ 00241 00242 void samv71EthInitGpio(NetInterface *interface) 00243 { 00244 //Enable PIO peripheral clocks 00245 PMC->PMC_PCER0 = (1 << ID_PIOC) | (1 << ID_PIOD); 00246 00247 //Disable pull-up resistors on RMII pins 00248 PIOD->PIO_PUDR = GMAC_RMII_MASK; 00249 //Disable interrupts-on-change 00250 PIOD->PIO_IDR = GMAC_RMII_MASK; 00251 //Assign RMII pins to peripheral A function 00252 PIOD->PIO_ABCDSR[0] &= ~GMAC_RMII_MASK; 00253 PIOD->PIO_ABCDSR[1] &= ~GMAC_RMII_MASK; 00254 //Disable the PIO from controlling the corresponding pins 00255 PIOD->PIO_PDR = GMAC_RMII_MASK; 00256 00257 //Select RMII operation mode 00258 GMAC->GMAC_UR &= ~GMAC_UR_RMII; 00259 00260 //Configure PHY_RESET as an output 00261 PIOC->PIO_PER = PIO_PC10; 00262 PIOC->PIO_OER = PIO_PC10; 00263 00264 //Reset PHY transceiver 00265 PIOC->PIO_CODR = PIO_PC10; 00266 sleep(10); 00267 00268 //Take the PHY transceiver out of reset 00269 PIOC->PIO_SODR = PIO_PC10; 00270 sleep(10); 00271 } 00272 00273 #endif 00274 00275 00276 /** 00277 * @brief Initialize buffer descriptors 00278 * @param[in] interface Underlying network interface 00279 **/ 00280 00281 void samv71EthInitBufferDesc(NetInterface *interface) 00282 { 00283 uint_t i; 00284 uint32_t address; 00285 00286 //Initialize TX buffer descriptors 00287 for(i = 0; i < SAMV71_ETH_TX_BUFFER_COUNT; i++) 00288 { 00289 //Calculate the address of the current TX buffer 00290 address = (uint32_t) txBuffer[i]; 00291 //Write the address to the descriptor entry 00292 txBufferDesc[i].address = address; 00293 //Initialize status field 00294 txBufferDesc[i].status = GMAC_TX_USED; 00295 } 00296 00297 //Mark the last descriptor entry with the wrap flag 00298 txBufferDesc[i - 1].status |= GMAC_TX_WRAP; 00299 //Initialize TX buffer index 00300 txBufferIndex = 0; 00301 00302 //Initialize RX buffer descriptors 00303 for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++) 00304 { 00305 //Calculate the address of the current RX buffer 00306 address = (uint32_t) rxBuffer[i]; 00307 //Write the address to the descriptor entry 00308 rxBufferDesc[i].address = address & GMAC_RX_ADDRESS; 00309 //Clear status field 00310 rxBufferDesc[i].status = 0; 00311 } 00312 00313 //Mark the last descriptor entry with the wrap flag 00314 rxBufferDesc[i - 1].address |= GMAC_RX_WRAP; 00315 //Initialize RX buffer index 00316 rxBufferIndex = 0; 00317 00318 //Initialize dummy TX buffer descriptors 00319 for(i = 0; i < SAMV71_ETH_DUMMY_BUFFER_COUNT; i++) 00320 { 00321 //Calculate the address of the current TX buffer 00322 address = (uint32_t) dummyTxBuffer[i]; 00323 //Write the address to the descriptor entry 00324 dummyTxBufferDesc[i].address = address; 00325 //Initialize status field 00326 dummyTxBufferDesc[i].status = GMAC_TX_USED; 00327 } 00328 00329 //Mark the last descriptor entry with the wrap flag 00330 dummyTxBufferDesc[i - 1].status |= GMAC_TX_WRAP; 00331 00332 //Initialize dummy RX buffer descriptors 00333 for(i = 0; i < SAMV71_ETH_DUMMY_BUFFER_COUNT; i++) 00334 { 00335 //Calculate the address of the current RX buffer 00336 address = (uint32_t) dummyRxBuffer[i]; 00337 //Write the address to the descriptor entry 00338 dummyRxBufferDesc[i].address = (address & GMAC_RX_ADDRESS) | GMAC_RX_OWNERSHIP; 00339 //Clear status field 00340 dummyRxBufferDesc[i].status = 0; 00341 } 00342 00343 //Mark the last descriptor entry with the wrap flag 00344 dummyRxBufferDesc[i - 1].address |= GMAC_RX_WRAP; 00345 00346 //Start location of the TX descriptor list 00347 GMAC->GMAC_TBQB = (uint32_t) txBufferDesc; 00348 GMAC->GMAC_TBQBAPQ[0] = (uint32_t) dummyTxBufferDesc; 00349 GMAC->GMAC_TBQBAPQ[1] = (uint32_t) dummyTxBufferDesc; 00350 GMAC->GMAC_TBQBAPQ[2] = (uint32_t) dummyTxBufferDesc; 00351 00352 //Start location of the RX descriptor list 00353 GMAC->GMAC_RBQB = (uint32_t) rxBufferDesc; 00354 GMAC->GMAC_RBQBAPQ[0] = (uint32_t) dummyRxBufferDesc; 00355 GMAC->GMAC_RBQBAPQ[1] = (uint32_t) dummyRxBufferDesc; 00356 GMAC->GMAC_RBQBAPQ[2] = (uint32_t) dummyRxBufferDesc; 00357 } 00358 00359 00360 /** 00361 * @brief SAMV71 Ethernet MAC timer handler 00362 * 00363 * This routine is periodically called by the TCP/IP stack to 00364 * handle periodic operations such as polling the link state 00365 * 00366 * @param[in] interface Underlying network interface 00367 **/ 00368 00369 void samv71EthTick(NetInterface *interface) 00370 { 00371 //Handle periodic operations 00372 interface->phyDriver->tick(interface); 00373 } 00374 00375 00376 /** 00377 * @brief Enable interrupts 00378 * @param[in] interface Underlying network interface 00379 **/ 00380 00381 void samv71EthEnableIrq(NetInterface *interface) 00382 { 00383 //Enable Ethernet MAC interrupts 00384 NVIC_EnableIRQ(GMAC_IRQn); 00385 //Enable Ethernet PHY interrupts 00386 interface->phyDriver->enableIrq(interface); 00387 } 00388 00389 00390 /** 00391 * @brief Disable interrupts 00392 * @param[in] interface Underlying network interface 00393 **/ 00394 00395 void samv71EthDisableIrq(NetInterface *interface) 00396 { 00397 //Disable Ethernet MAC interrupts 00398 NVIC_DisableIRQ(GMAC_IRQn); 00399 //Disable Ethernet PHY interrupts 00400 interface->phyDriver->disableIrq(interface); 00401 } 00402 00403 00404 /** 00405 * @brief SAMV71 Ethernet MAC interrupt service routine 00406 **/ 00407 00408 void GMAC_Handler(void) 00409 { 00410 bool_t flag; 00411 volatile uint32_t isr; 00412 volatile uint32_t tsr; 00413 volatile uint32_t rsr; 00414 00415 //Enter interrupt service routine 00416 osEnterIsr(); 00417 00418 //This flag will be set if a higher priority task must be woken 00419 flag = FALSE; 00420 00421 //Each time the software reads GMAC_ISR, it has to check the 00422 //contents of GMAC_TSR, GMAC_RSR and GMAC_NSR 00423 isr = GMAC->GMAC_ISRPQ[0]; 00424 isr = GMAC->GMAC_ISRPQ[1]; 00425 isr = GMAC->GMAC_ISRPQ[2]; 00426 isr = GMAC->GMAC_ISR; 00427 tsr = GMAC->GMAC_TSR; 00428 rsr = GMAC->GMAC_RSR; 00429 00430 //A packet has been transmitted? 00431 if(tsr & (GMAC_TSR_HRESP | GMAC_TSR_TXCOMP | GMAC_TSR_TFC | 00432 GMAC_TSR_TXGO | GMAC_TSR_RLE | GMAC_TSR_COL | GMAC_TSR_UBR)) 00433 { 00434 //Only clear TSR flags that are currently set 00435 GMAC->GMAC_TSR = tsr; 00436 00437 //Check whether the TX buffer is available for writing 00438 if(txBufferDesc[txBufferIndex].status & GMAC_TX_USED) 00439 { 00440 //Notify the TCP/IP stack that the transmitter is ready to send 00441 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00442 } 00443 } 00444 00445 //A packet has been received? 00446 if(rsr & (GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA)) 00447 { 00448 //Set event flag 00449 nicDriverInterface->nicEvent = TRUE; 00450 //Notify the TCP/IP stack of the event 00451 flag |= osSetEventFromIsr(&netEvent); 00452 } 00453 00454 //Leave interrupt service routine 00455 osExitIsr(flag); 00456 } 00457 00458 00459 /** 00460 * @brief SAMV71 Ethernet MAC event handler 00461 * @param[in] interface Underlying network interface 00462 **/ 00463 00464 void samv71EthEventHandler(NetInterface *interface) 00465 { 00466 error_t error; 00467 uint32_t rsr; 00468 00469 //Read receive status 00470 rsr = GMAC->GMAC_RSR; 00471 00472 //Packet received? 00473 if(rsr & (GMAC_RSR_HNO | GMAC_RSR_RXOVR | GMAC_RSR_REC | GMAC_RSR_BNA)) 00474 { 00475 //Only clear RSR flags that are currently set 00476 GMAC->GMAC_RSR = rsr; 00477 00478 //Process all pending packets 00479 do 00480 { 00481 //Read incoming packet 00482 error = samv71EthReceivePacket(interface); 00483 00484 //No more data in the receive buffer? 00485 } while(error != ERROR_BUFFER_EMPTY); 00486 } 00487 } 00488 00489 00490 /** 00491 * @brief Send a packet 00492 * @param[in] interface Underlying network interface 00493 * @param[in] buffer Multi-part buffer containing the data to send 00494 * @param[in] offset Offset to the first data byte 00495 * @return Error code 00496 **/ 00497 00498 error_t samv71EthSendPacket(NetInterface *interface, 00499 const NetBuffer *buffer, size_t offset) 00500 { 00501 static uint8_t temp[SAMV71_ETH_TX_BUFFER_SIZE]; 00502 size_t length; 00503 00504 //Retrieve the length of the packet 00505 length = netBufferGetLength(buffer) - offset; 00506 00507 //Check the frame length 00508 if(length > SAMV71_ETH_TX_BUFFER_SIZE) 00509 { 00510 //The transmitter can accept another packet 00511 osSetEvent(&interface->nicTxEvent); 00512 //Report an error 00513 return ERROR_INVALID_LENGTH; 00514 } 00515 00516 //Make sure the current buffer is available for writing 00517 if(!(txBufferDesc[txBufferIndex].status & GMAC_TX_USED)) 00518 return ERROR_FAILURE; 00519 00520 //Copy user data to the transmit buffer 00521 netBufferRead(temp, buffer, offset, length); 00522 memcpy(txBuffer[txBufferIndex], temp, (length + 3) & ~3UL); 00523 00524 //Set the necessary flags in the descriptor entry 00525 if(txBufferIndex < (SAMV71_ETH_TX_BUFFER_COUNT - 1)) 00526 { 00527 //Write the status word 00528 txBufferDesc[txBufferIndex].status = 00529 GMAC_TX_LAST | (length & GMAC_TX_LENGTH); 00530 00531 //Point to the next buffer 00532 txBufferIndex++; 00533 } 00534 else 00535 { 00536 //Write the status word 00537 txBufferDesc[txBufferIndex].status = GMAC_TX_WRAP | 00538 GMAC_TX_LAST | (length & GMAC_TX_LENGTH); 00539 00540 //Wrap around 00541 txBufferIndex = 0; 00542 } 00543 00544 //Data synchronization barrier 00545 __DSB(); 00546 00547 //Set the TSTART bit to initiate transmission 00548 GMAC->GMAC_NCR |= GMAC_NCR_TSTART; 00549 00550 //Check whether the next buffer is available for writing 00551 if(txBufferDesc[txBufferIndex].status & GMAC_TX_USED) 00552 { 00553 //The transmitter can accept another packet 00554 osSetEvent(&interface->nicTxEvent); 00555 } 00556 00557 //Successful processing 00558 return NO_ERROR; 00559 } 00560 00561 00562 /** 00563 * @brief Receive a packet 00564 * @param[in] interface Underlying network interface 00565 * @return Error code 00566 **/ 00567 00568 error_t samv71EthReceivePacket(NetInterface *interface) 00569 { 00570 static uint8_t temp[ETH_MAX_FRAME_SIZE]; 00571 error_t error; 00572 uint_t i; 00573 uint_t j; 00574 uint_t sofIndex; 00575 uint_t eofIndex; 00576 size_t n; 00577 size_t size; 00578 size_t length; 00579 00580 //Initialize SOF and EOF indices 00581 sofIndex = UINT_MAX; 00582 eofIndex = UINT_MAX; 00583 00584 //Search for SOF and EOF flags 00585 for(i = 0; i < SAMV71_ETH_RX_BUFFER_COUNT; i++) 00586 { 00587 //Point to the current entry 00588 j = rxBufferIndex + i; 00589 00590 //Wrap around to the beginning of the buffer if necessary 00591 if(j >= SAMV71_ETH_RX_BUFFER_COUNT) 00592 j -= SAMV71_ETH_RX_BUFFER_COUNT; 00593 00594 //No more entries to process? 00595 if(!(rxBufferDesc[j].address & GMAC_RX_OWNERSHIP)) 00596 { 00597 //Stop processing 00598 break; 00599 } 00600 //A valid SOF has been found? 00601 if(rxBufferDesc[j].status & GMAC_RX_SOF) 00602 { 00603 //Save the position of the SOF 00604 sofIndex = i; 00605 } 00606 //A valid EOF has been found? 00607 if((rxBufferDesc[j].status & GMAC_RX_EOF) && sofIndex != UINT_MAX) 00608 { 00609 //Save the position of the EOF 00610 eofIndex = i; 00611 //Retrieve the length of the frame 00612 size = rxBufferDesc[j].status & GMAC_RX_LENGTH; 00613 //Limit the number of data to read 00614 size = MIN(size, ETH_MAX_FRAME_SIZE); 00615 //Stop processing since we have reached the end of the frame 00616 break; 00617 } 00618 } 00619 00620 //Determine the number of entries to process 00621 if(eofIndex != UINT_MAX) 00622 j = eofIndex + 1; 00623 else if(sofIndex != UINT_MAX) 00624 j = sofIndex; 00625 else 00626 j = i; 00627 00628 //Total number of bytes that have been copied from the receive buffer 00629 length = 0; 00630 00631 //Process incoming frame 00632 for(i = 0; i < j; i++) 00633 { 00634 //Any data to copy from current buffer? 00635 if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex) 00636 { 00637 //Calculate the number of bytes to read at a time 00638 n = MIN(size, SAMV71_ETH_RX_BUFFER_SIZE); 00639 //Copy data from receive buffer 00640 memcpy(temp + length, rxBuffer[rxBufferIndex], (n + 3) & ~3UL); 00641 //Update byte counters 00642 length += n; 00643 size -= n; 00644 } 00645 00646 //Mark the current buffer as free 00647 rxBufferDesc[rxBufferIndex].address &= ~GMAC_RX_OWNERSHIP; 00648 00649 //Point to the following entry 00650 rxBufferIndex++; 00651 00652 //Wrap around to the beginning of the buffer if necessary 00653 if(rxBufferIndex >= SAMV71_ETH_RX_BUFFER_COUNT) 00654 rxBufferIndex = 0; 00655 } 00656 00657 //Any packet to process? 00658 if(length > 0) 00659 { 00660 //Pass the packet to the upper layer 00661 nicProcessPacket(interface, temp, length); 00662 //Valid packet received 00663 error = NO_ERROR; 00664 } 00665 else 00666 { 00667 //No more data in the receive buffer 00668 error = ERROR_BUFFER_EMPTY; 00669 } 00670 00671 //Return status code 00672 return error; 00673 } 00674 00675 00676 /** 00677 * @brief Configure multicast MAC address filtering 00678 * @param[in] interface Underlying network interface 00679 * @return Error code 00680 **/ 00681 00682 error_t samv71EthSetMulticastFilter(NetInterface *interface) 00683 { 00684 uint_t i; 00685 uint_t k; 00686 uint8_t *p; 00687 uint32_t hashTable[2]; 00688 MacFilterEntry *entry; 00689 00690 //Debug message 00691 TRACE_DEBUG("Updating SAMV71 hash table...\r\n"); 00692 00693 //Clear hash table 00694 hashTable[0] = 0; 00695 hashTable[1] = 0; 00696 00697 //The MAC filter table contains the multicast MAC addresses 00698 //to accept when receiving an Ethernet frame 00699 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00700 { 00701 //Point to the current entry 00702 entry = &interface->macMulticastFilter[i]; 00703 00704 //Valid entry? 00705 if(entry->refCount > 0) 00706 { 00707 //Point to the MAC address 00708 p = entry->addr.b; 00709 00710 //Apply the hash function 00711 k = (p[0] >> 6) ^ p[0]; 00712 k ^= (p[1] >> 4) ^ (p[1] << 2); 00713 k ^= (p[2] >> 2) ^ (p[2] << 4); 00714 k ^= (p[3] >> 6) ^ p[3]; 00715 k ^= (p[4] >> 4) ^ (p[4] << 2); 00716 k ^= (p[5] >> 2) ^ (p[5] << 4); 00717 00718 //The hash value is reduced to a 6-bit index 00719 k &= 0x3F; 00720 00721 //Update hash table contents 00722 hashTable[k / 32] |= (1 << (k % 32)); 00723 } 00724 } 00725 00726 //Write the hash table 00727 GMAC->GMAC_HRB = hashTable[0]; 00728 GMAC->GMAC_HRT = hashTable[1]; 00729 00730 //Debug message 00731 TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", GMAC->GMAC_HRB); 00732 TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", GMAC->GMAC_HRT); 00733 00734 //Successful processing 00735 return NO_ERROR; 00736 } 00737 00738 00739 /** 00740 * @brief Adjust MAC configuration parameters for proper operation 00741 * @param[in] interface Underlying network interface 00742 * @return Error code 00743 **/ 00744 00745 error_t samv71EthUpdateMacConfig(NetInterface *interface) 00746 { 00747 uint32_t config; 00748 00749 //Read network configuration register 00750 config = GMAC->GMAC_NCFGR; 00751 00752 //10BASE-T or 100BASE-TX operation mode? 00753 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00754 config |= GMAC_NCFGR_SPD; 00755 else 00756 config &= ~GMAC_NCFGR_SPD; 00757 00758 //Half-duplex or full-duplex mode? 00759 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00760 config |= GMAC_NCFGR_FD; 00761 else 00762 config &= ~GMAC_NCFGR_FD; 00763 00764 //Write configuration value back to NCFGR register 00765 GMAC->GMAC_NCFGR = config; 00766 00767 //Successful processing 00768 return NO_ERROR; 00769 } 00770 00771 00772 /** 00773 * @brief Write PHY register 00774 * @param[in] phyAddr PHY address 00775 * @param[in] regAddr Register address 00776 * @param[in] data Register value 00777 **/ 00778 00779 void samv71EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00780 { 00781 uint32_t value; 00782 00783 //Set up a write operation 00784 value = GMAC_MAN_CLTTO | GMAC_MAN_OP(1) | GMAC_MAN_WTN(2); 00785 //PHY address 00786 value |= GMAC_MAN_PHYA(phyAddr); 00787 //Register address 00788 value |= GMAC_MAN_REGA(regAddr); 00789 //Register value 00790 value |= GMAC_MAN_DATA(data); 00791 00792 //Start a write operation 00793 GMAC->GMAC_MAN = value; 00794 //Wait for the write to complete 00795 while(!(GMAC->GMAC_NSR & GMAC_NSR_IDLE)); 00796 } 00797 00798 00799 /** 00800 * @brief Read PHY register 00801 * @param[in] phyAddr PHY address 00802 * @param[in] regAddr Register address 00803 * @return Register value 00804 **/ 00805 00806 uint16_t samv71EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00807 { 00808 uint32_t value; 00809 00810 //Set up a read operation 00811 value = GMAC_MAN_CLTTO | GMAC_MAN_OP(2) | GMAC_MAN_WTN(2); 00812 //PHY address 00813 value |= GMAC_MAN_PHYA(phyAddr); 00814 //Register address 00815 value |= GMAC_MAN_REGA(regAddr); 00816 00817 //Start a read operation 00818 GMAC->GMAC_MAN = value; 00819 //Wait for the read to complete 00820 while(!(GMAC->GMAC_NSR & GMAC_NSR_IDLE)); 00821 00822 //Return PHY register contents 00823 return GMAC->GMAC_MAN & GMAC_MAN_DATA_Msk; 00824 } 00825
Generated on Tue Jul 12 2022 17:10:16 by
1.7.2