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.
sam9263_eth.c
00001 /** 00002 * @file sam9263_eth.c 00003 * @brief AT91SAM9263 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 "at91sam9263.h" 00035 #include "core/net.h" 00036 #include "drivers/sam9263_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 static uint8_t txBuffer[SAM9263_ETH_TX_BUFFER_COUNT][SAM9263_ETH_TX_BUFFER_SIZE]; 00048 //RX buffer 00049 #pragma data_alignment = 8 00050 static uint8_t rxBuffer[SAM9263_ETH_RX_BUFFER_COUNT][SAM9263_ETH_RX_BUFFER_SIZE]; 00051 //TX buffer descriptors 00052 #pragma data_alignment = 4 00053 static Sam9263TxBufferDesc txBufferDesc[SAM9263_ETH_TX_BUFFER_COUNT]; 00054 //RX buffer descriptors 00055 #pragma data_alignment = 4 00056 static Sam9263RxBufferDesc rxBufferDesc[SAM9263_ETH_RX_BUFFER_COUNT]; 00057 00058 //Keil MDK-ARM or GCC compiler? 00059 #else 00060 00061 //TX buffer 00062 static uint8_t txBuffer[SAM9263_ETH_TX_BUFFER_COUNT][SAM9263_ETH_TX_BUFFER_SIZE] 00063 __attribute__((aligned(8))); 00064 //RX buffer 00065 static uint8_t rxBuffer[SAM9263_ETH_RX_BUFFER_COUNT][SAM9263_ETH_RX_BUFFER_SIZE] 00066 __attribute__((aligned(8))); 00067 //TX buffer descriptors 00068 static Sam9263TxBufferDesc txBufferDesc[SAM9263_ETH_TX_BUFFER_COUNT] 00069 __attribute__((aligned(4))); 00070 //RX buffer descriptors 00071 static Sam9263RxBufferDesc rxBufferDesc[SAM9263_ETH_RX_BUFFER_COUNT] 00072 __attribute__((aligned(4))); 00073 00074 #endif 00075 00076 //TX buffer index 00077 static uint_t txBufferIndex; 00078 //RX buffer index 00079 static uint_t rxBufferIndex; 00080 00081 00082 /** 00083 * @brief SAM9263 Ethernet MAC driver 00084 **/ 00085 00086 const NicDriver sam9263EthDriver = 00087 { 00088 NIC_TYPE_ETHERNET, 00089 ETH_MTU, 00090 sam9263EthInit, 00091 sam9263EthTick, 00092 sam9263EthEnableIrq, 00093 sam9263EthDisableIrq, 00094 sam9263EthEventHandler, 00095 sam9263EthSendPacket, 00096 sam9263EthSetMulticastFilter, 00097 sam9263EthUpdateMacConfig, 00098 sam9263EthWritePhyReg, 00099 sam9263EthReadPhyReg, 00100 TRUE, 00101 TRUE, 00102 TRUE, 00103 FALSE 00104 }; 00105 00106 00107 /** 00108 * @brief SAM9263 Ethernet MAC initialization 00109 * @param[in] interface Underlying network interface 00110 * @return Error code 00111 **/ 00112 00113 error_t sam9263EthInit(NetInterface *interface) 00114 { 00115 error_t error; 00116 volatile uint32_t status; 00117 00118 //Debug message 00119 TRACE_INFO("Initializing SAM9263 Ethernet MAC...\r\n"); 00120 00121 //Save underlying network interface 00122 nicDriverInterface = interface; 00123 00124 //Enable EMAC peripheral clock 00125 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_EMAC); 00126 00127 //GPIO configuration 00128 sam9263EthInitGpio(interface); 00129 00130 //Configure MDC clock speed 00131 AT91C_BASE_EMAC->EMAC_NCFGR = AT91C_EMAC_CLK_HCLK_64; 00132 //Enable management port (MDC and MDIO) 00133 AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE; 00134 00135 //PHY transceiver initialization 00136 error = interface->phyDriver->init(interface); 00137 //Failed to initialize PHY transceiver? 00138 if(error) 00139 return error; 00140 00141 //Set the MAC address 00142 AT91C_BASE_EMAC->EMAC_SA1L = interface->macAddr.w[0] | (interface->macAddr.w[1] << 16); 00143 AT91C_BASE_EMAC->EMAC_SA1H = interface->macAddr.w[2]; 00144 00145 //Configure the receive filter 00146 AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_UNI | AT91C_EMAC_MTI; 00147 00148 //Initialize hash table 00149 AT91C_BASE_EMAC->EMAC_HRB = 0; 00150 AT91C_BASE_EMAC->EMAC_HRT = 0; 00151 00152 //Initialize buffer descriptors 00153 sam9263EthInitBufferDesc(interface); 00154 00155 //Clear transmit status register 00156 AT91C_BASE_EMAC->EMAC_TSR = AT91C_EMAC_UND | AT91C_EMAC_COMP | AT91C_EMAC_BEX | 00157 AT91C_EMAC_TGO | AT91C_EMAC_RLES | AT91C_EMAC_COL | AT91C_EMAC_UBR; 00158 //Clear receive status register 00159 AT91C_BASE_EMAC->EMAC_RSR = AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA; 00160 00161 //First disable all EMAC interrupts 00162 AT91C_BASE_EMAC->EMAC_IDR = 0xFFFFFFFF; 00163 //Only the desired ones are enabled 00164 AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_ROVR | AT91C_EMAC_TCOMP | AT91C_EMAC_TXERR | 00165 AT91C_EMAC_RLEX | AT91C_EMAC_TUNDR | AT91C_EMAC_RXUBR | AT91C_EMAC_RCOMP; 00166 00167 //Read EMAC ISR register to clear any pending interrupt 00168 status = AT91C_BASE_EMAC->EMAC_ISR; 00169 00170 //Configure interrupt controller 00171 AT91C_BASE_AIC->AIC_SMR[AT91C_ID_EMAC] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST; 00172 AT91C_BASE_AIC->AIC_SVR[AT91C_ID_EMAC] = (uint32_t) emacIrqWrapper; 00173 00174 //Clear EMAC interrupt flag 00175 AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_EMAC); 00176 00177 //Enable the EMAC to transmit and receive data 00178 AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TE | AT91C_EMAC_RE; 00179 00180 //Accept any packets from the upper layer 00181 osSetEvent(&interface->nicTxEvent); 00182 00183 //Successful initialization 00184 return NO_ERROR; 00185 } 00186 00187 00188 //SAM9263-EK evaluation board? 00189 #if defined(USE_SAM9263_EK) 00190 00191 /** 00192 * @brief GPIO configuration 00193 * @param[in] interface Underlying network interface 00194 **/ 00195 00196 void sam9263EthInitGpio(NetInterface *interface) 00197 { 00198 //Enable PIO peripheral clocks 00199 AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_PIOA) | (1 << AT91C_ID_PIOCDE); 00200 00201 //Disable pull-up resistors on RMII pins 00202 AT91C_BASE_PIOC->PIO_PPUDR = AT91C_EMAC_RMII_MASK_C; 00203 AT91C_BASE_PIOE->PIO_PPUDR = AT91C_EMAC_RMII_MASK_E; 00204 //Disable interrupts-on-change 00205 AT91C_BASE_PIOC->PIO_IDR = AT91C_EMAC_RMII_MASK_C; 00206 AT91C_BASE_PIOE->PIO_IDR = AT91C_EMAC_RMII_MASK_E; 00207 //Assign RMII pins to to the relevant peripheral function 00208 AT91C_BASE_PIOC->PIO_BSR = AT91C_EMAC_RMII_MASK_C; 00209 AT91C_BASE_PIOE->PIO_ASR = AT91C_EMAC_RMII_MASK_E; 00210 //Disable the PIO from controlling the corresponding pins 00211 AT91C_BASE_PIOC->PIO_PDR = AT91C_EMAC_RMII_MASK_C; 00212 AT91C_BASE_PIOE->PIO_PDR = AT91C_EMAC_RMII_MASK_E; 00213 00214 //Select RMII operation mode and enable transceiver clock 00215 AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_CLKEN | AT91C_EMAC_RMII; 00216 } 00217 00218 #endif 00219 00220 00221 /** 00222 * @brief Initialize buffer descriptors 00223 * @param[in] interface Underlying network interface 00224 **/ 00225 00226 void sam9263EthInitBufferDesc(NetInterface *interface) 00227 { 00228 uint_t i; 00229 uint32_t address; 00230 00231 //Initialize TX buffer descriptors 00232 for(i = 0; i < SAM9263_ETH_TX_BUFFER_COUNT; i++) 00233 { 00234 //Calculate the address of the current TX buffer 00235 address = (uint32_t) txBuffer[i]; 00236 //Write the address to the descriptor entry 00237 txBufferDesc[i].address = address; 00238 //Initialize status field 00239 txBufferDesc[i].status = AT91C_EMAC_TX_USED; 00240 } 00241 00242 //Mark the last descriptor entry with the wrap flag 00243 txBufferDesc[i - 1].status |= AT91C_EMAC_TX_WRAP; 00244 //Initialize TX buffer index 00245 txBufferIndex = 0; 00246 00247 //Initialize RX buffer descriptors 00248 for(i = 0; i < SAM9263_ETH_RX_BUFFER_COUNT; i++) 00249 { 00250 //Calculate the address of the current RX buffer 00251 address = (uint32_t) rxBuffer[i]; 00252 //Write the address to the descriptor entry 00253 rxBufferDesc[i].address = address & AT91C_EMAC_RX_ADDRESS; 00254 //Clear status field 00255 rxBufferDesc[i].status = 0; 00256 } 00257 00258 //Mark the last descriptor entry with the wrap flag 00259 rxBufferDesc[i - 1].address |= AT91C_EMAC_RX_WRAP; 00260 //Initialize RX buffer index 00261 rxBufferIndex = 0; 00262 00263 //Start location of the TX descriptor list 00264 AT91C_BASE_EMAC->EMAC_TBQP = (uint32_t) txBufferDesc; 00265 //Start location of the RX descriptor list 00266 AT91C_BASE_EMAC->EMAC_RBQP = (uint32_t) rxBufferDesc; 00267 } 00268 00269 00270 /** 00271 * @brief SAM9263 Ethernet MAC timer handler 00272 * 00273 * This routine is periodically called by the TCP/IP stack to 00274 * handle periodic operations such as polling the link state 00275 * 00276 * @param[in] interface Underlying network interface 00277 **/ 00278 00279 void sam9263EthTick(NetInterface *interface) 00280 { 00281 //Handle periodic operations 00282 interface->phyDriver->tick(interface); 00283 } 00284 00285 00286 /** 00287 * @brief Enable interrupts 00288 * @param[in] interface Underlying network interface 00289 **/ 00290 00291 void sam9263EthEnableIrq(NetInterface *interface) 00292 { 00293 //Enable Ethernet MAC interrupts 00294 AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_EMAC); 00295 //Enable Ethernet PHY interrupts 00296 interface->phyDriver->enableIrq(interface); 00297 } 00298 00299 00300 /** 00301 * @brief Disable interrupts 00302 * @param[in] interface Underlying network interface 00303 **/ 00304 00305 void sam9263EthDisableIrq(NetInterface *interface) 00306 { 00307 //Disable Ethernet MAC interrupts 00308 AT91C_BASE_AIC->AIC_IDCR = (1 << AT91C_ID_EMAC); 00309 //Disable Ethernet PHY interrupts 00310 interface->phyDriver->disableIrq(interface); 00311 } 00312 00313 00314 /** 00315 * @brief SAM9263 Ethernet MAC interrupt service routine 00316 **/ 00317 00318 void sam9263EthIrqHandler(void) 00319 { 00320 bool_t flag; 00321 volatile uint32_t isr; 00322 volatile uint32_t tsr; 00323 volatile uint32_t rsr; 00324 00325 //Enter interrupt service routine 00326 osEnterIsr(); 00327 00328 //This flag will be set if a higher priority task must be woken 00329 flag = FALSE; 00330 00331 //Each time the software reads EMAC_ISR, it has to check the 00332 //contents of EMAC_TSR, EMAC_RSR and EMAC_NSR 00333 isr = AT91C_BASE_EMAC->EMAC_ISR; 00334 tsr = AT91C_BASE_EMAC->EMAC_TSR; 00335 rsr = AT91C_BASE_EMAC->EMAC_RSR; 00336 00337 //A packet has been transmitted? 00338 if(tsr & (AT91C_EMAC_UND | AT91C_EMAC_COMP | AT91C_EMAC_BEX | 00339 AT91C_EMAC_TGO | AT91C_EMAC_RLES | AT91C_EMAC_COL | AT91C_EMAC_UBR)) 00340 { 00341 //Only clear TSR flags that are currently set 00342 AT91C_BASE_EMAC->EMAC_TSR = tsr; 00343 00344 //Check whether the TX buffer is available for writing 00345 if(txBufferDesc[txBufferIndex].status & AT91C_EMAC_TX_USED) 00346 { 00347 //Notify the TCP/IP stack that the transmitter is ready to send 00348 flag |= osSetEventFromIsr(&nicDriverInterface->nicTxEvent); 00349 } 00350 } 00351 00352 //A packet has been received? 00353 if(rsr & (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA)) 00354 { 00355 //Set event flag 00356 nicDriverInterface->nicEvent = TRUE; 00357 //Notify the TCP/IP stack of the event 00358 flag |= osSetEventFromIsr(&netEvent); 00359 } 00360 00361 //Write AIC_EOICR register before exiting 00362 AT91C_BASE_AIC->AIC_EOICR = 0; 00363 00364 //Leave interrupt service routine 00365 osExitIsr(flag); 00366 } 00367 00368 00369 /** 00370 * @brief SAM9263 Ethernet MAC event handler 00371 * @param[in] interface Underlying network interface 00372 **/ 00373 00374 void sam9263EthEventHandler(NetInterface *interface) 00375 { 00376 error_t error; 00377 uint32_t rsr; 00378 00379 //Read receive status 00380 rsr = AT91C_BASE_EMAC->EMAC_RSR; 00381 00382 //Packet received? 00383 if(rsr & (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA)) 00384 { 00385 //Only clear RSR flags that are currently set 00386 AT91C_BASE_EMAC->EMAC_RSR = rsr; 00387 00388 //Process all pending packets 00389 do 00390 { 00391 //Read incoming packet 00392 error = sam9263EthReceivePacket(interface); 00393 00394 //No more data in the receive buffer? 00395 } while(error != ERROR_BUFFER_EMPTY); 00396 } 00397 } 00398 00399 00400 /** 00401 * @brief Send a packet 00402 * @param[in] interface Underlying network interface 00403 * @param[in] buffer Multi-part buffer containing the data to send 00404 * @param[in] offset Offset to the first data byte 00405 * @return Error code 00406 **/ 00407 00408 error_t sam9263EthSendPacket(NetInterface *interface, 00409 const NetBuffer *buffer, size_t offset) 00410 { 00411 size_t length; 00412 00413 //Retrieve the length of the packet 00414 length = netBufferGetLength(buffer) - offset; 00415 00416 //Check the frame length 00417 if(length > SAM9263_ETH_TX_BUFFER_SIZE) 00418 { 00419 //The transmitter can accept another packet 00420 osSetEvent(&interface->nicTxEvent); 00421 //Report an error 00422 return ERROR_INVALID_LENGTH; 00423 } 00424 00425 //Make sure the current buffer is available for writing 00426 if(!(txBufferDesc[txBufferIndex].status & AT91C_EMAC_TX_USED)) 00427 return ERROR_FAILURE; 00428 00429 //Copy user data to the transmit buffer 00430 netBufferRead(txBuffer[txBufferIndex], buffer, offset, length); 00431 00432 //Set the necessary flags in the descriptor entry 00433 if(txBufferIndex < (SAM9263_ETH_TX_BUFFER_COUNT - 1)) 00434 { 00435 //Write the status word 00436 txBufferDesc[txBufferIndex].status = 00437 AT91C_EMAC_TX_LAST | (length & AT91C_EMAC_TX_LENGTH); 00438 00439 //Point to the next buffer 00440 txBufferIndex++; 00441 } 00442 else 00443 { 00444 //Write the status word 00445 txBufferDesc[txBufferIndex].status = AT91C_EMAC_TX_WRAP | 00446 AT91C_EMAC_TX_LAST | (length & AT91C_EMAC_TX_LENGTH); 00447 00448 //Wrap around 00449 txBufferIndex = 0; 00450 } 00451 00452 //Set the TSTART bit to initiate transmission 00453 AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART; 00454 00455 //Check whether the next buffer is available for writing 00456 if(txBufferDesc[txBufferIndex].status & AT91C_EMAC_TX_USED) 00457 { 00458 //The transmitter can accept another packet 00459 osSetEvent(&interface->nicTxEvent); 00460 } 00461 00462 //Successful processing 00463 return NO_ERROR; 00464 } 00465 00466 00467 /** 00468 * @brief Receive a packet 00469 * @param[in] interface Underlying network interface 00470 * @return Error code 00471 **/ 00472 00473 error_t sam9263EthReceivePacket(NetInterface *interface) 00474 { 00475 static uint8_t temp[ETH_MAX_FRAME_SIZE]; 00476 error_t error; 00477 uint_t i; 00478 uint_t j; 00479 uint_t sofIndex; 00480 uint_t eofIndex; 00481 size_t n; 00482 size_t size; 00483 size_t length; 00484 00485 //Initialize SOF and EOF indices 00486 sofIndex = UINT_MAX; 00487 eofIndex = UINT_MAX; 00488 00489 //Search for SOF and EOF flags 00490 for(i = 0; i < SAM9263_ETH_RX_BUFFER_COUNT; i++) 00491 { 00492 //Point to the current entry 00493 j = rxBufferIndex + i; 00494 00495 //Wrap around to the beginning of the buffer if necessary 00496 if(j >= SAM9263_ETH_RX_BUFFER_COUNT) 00497 j -= SAM9263_ETH_RX_BUFFER_COUNT; 00498 00499 //No more entries to process? 00500 if(!(rxBufferDesc[j].address & EMAC_RX_OWNERSHIP)) 00501 { 00502 //Stop processing 00503 break; 00504 } 00505 //A valid SOF has been found? 00506 if(rxBufferDesc[j].status & EMAC_RX_SOF) 00507 { 00508 //Save the position of the SOF 00509 sofIndex = i; 00510 } 00511 //A valid EOF has been found? 00512 if((rxBufferDesc[j].status & EMAC_RX_EOF) && sofIndex != UINT_MAX) 00513 { 00514 //Save the position of the EOF 00515 eofIndex = i; 00516 //Retrieve the length of the frame 00517 size = rxBufferDesc[j].status & EMAC_RX_LENGTH; 00518 //Limit the number of data to read 00519 size = MIN(size, ETH_MAX_FRAME_SIZE); 00520 //Stop processing since we have reached the end of the frame 00521 break; 00522 } 00523 } 00524 00525 //Determine the number of entries to process 00526 if(eofIndex != UINT_MAX) 00527 j = eofIndex + 1; 00528 else if(sofIndex != UINT_MAX) 00529 j = sofIndex; 00530 else 00531 j = i; 00532 00533 //Total number of bytes that have been copied from the receive buffer 00534 length = 0; 00535 00536 //Process incoming frame 00537 for(i = 0; i < j; i++) 00538 { 00539 //Any data to copy from current buffer? 00540 if(eofIndex != UINT_MAX && i >= sofIndex && i <= eofIndex) 00541 { 00542 //Calculate the number of bytes to read at a time 00543 n = MIN(size, SAM9263_ETH_RX_BUFFER_SIZE); 00544 //Copy data from receive buffer 00545 memcpy(temp + length, rxBuffer[rxBufferIndex], n); 00546 //Update byte counters 00547 length += n; 00548 size -= n; 00549 } 00550 00551 //Mark the current buffer as free 00552 rxBufferDesc[rxBufferIndex].address &= ~EMAC_RX_OWNERSHIP; 00553 00554 //Point to the following entry 00555 rxBufferIndex++; 00556 00557 //Wrap around to the beginning of the buffer if necessary 00558 if(rxBufferIndex >= SAM9263_ETH_RX_BUFFER_COUNT) 00559 rxBufferIndex = 0; 00560 } 00561 00562 //Any packet to process? 00563 if(length > 0) 00564 { 00565 //Pass the packet to the upper layer 00566 nicProcessPacket(interface, temp, length); 00567 //Valid packet received 00568 error = NO_ERROR; 00569 } 00570 else 00571 { 00572 //No more data in the receive buffer 00573 error = ERROR_BUFFER_EMPTY; 00574 } 00575 00576 //Return status code 00577 return error; 00578 } 00579 00580 00581 /** 00582 * @brief Configure multicast MAC address filtering 00583 * @param[in] interface Underlying network interface 00584 * @return Error code 00585 **/ 00586 00587 error_t sam9263EthSetMulticastFilter(NetInterface *interface) 00588 { 00589 uint_t i; 00590 uint_t k; 00591 uint8_t *p; 00592 uint32_t hashTable[2]; 00593 MacFilterEntry *entry; 00594 00595 //Debug message 00596 TRACE_DEBUG("Updating SAM9263 hash table...\r\n"); 00597 00598 //Clear hash table 00599 hashTable[0] = 0; 00600 hashTable[1] = 0; 00601 00602 //The MAC filter table contains the multicast MAC addresses 00603 //to accept when receiving an Ethernet frame 00604 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00605 { 00606 //Point to the current entry 00607 entry = &interface->macMulticastFilter[i]; 00608 00609 //Valid entry? 00610 if(entry->refCount > 0) 00611 { 00612 //Point to the MAC address 00613 p = entry->addr.b; 00614 00615 //Apply the hash function 00616 k = (p[0] >> 6) ^ p[0]; 00617 k ^= (p[1] >> 4) ^ (p[1] << 2); 00618 k ^= (p[2] >> 2) ^ (p[2] << 4); 00619 k ^= (p[3] >> 6) ^ p[3]; 00620 k ^= (p[4] >> 4) ^ (p[4] << 2); 00621 k ^= (p[5] >> 2) ^ (p[5] << 4); 00622 00623 //The hash value is reduced to a 6-bit index 00624 k &= 0x3F; 00625 00626 //Update hash table contents 00627 hashTable[k / 32] |= (1 << (k % 32)); 00628 } 00629 } 00630 00631 //Write the hash table 00632 AT91C_BASE_EMAC->EMAC_HRB = hashTable[0]; 00633 AT91C_BASE_EMAC->EMAC_HRT = hashTable[1]; 00634 00635 //Debug message 00636 TRACE_DEBUG(" HRB = %08" PRIX32 "\r\n", AT91C_BASE_EMAC->EMAC_HRB); 00637 TRACE_DEBUG(" HRT = %08" PRIX32 "\r\n", AT91C_BASE_EMAC->EMAC_HRT); 00638 00639 //Successful processing 00640 return NO_ERROR; 00641 } 00642 00643 00644 /** 00645 * @brief Adjust MAC configuration parameters for proper operation 00646 * @param[in] interface Underlying network interface 00647 * @return Error code 00648 **/ 00649 00650 error_t sam9263EthUpdateMacConfig(NetInterface *interface) 00651 { 00652 uint32_t config; 00653 00654 //Read network configuration register 00655 config = AT91C_BASE_EMAC->EMAC_NCFGR; 00656 00657 //10BASE-T or 100BASE-TX operation mode? 00658 if(interface->linkSpeed == NIC_LINK_SPEED_100MBPS) 00659 config |= AT91C_EMAC_SPD; 00660 else 00661 config &= ~AT91C_EMAC_SPD; 00662 00663 //Half-duplex or full-duplex mode? 00664 if(interface->duplexMode == NIC_FULL_DUPLEX_MODE) 00665 config |= AT91C_EMAC_FD; 00666 else 00667 config &= ~AT91C_EMAC_FD; 00668 00669 //Write configuration value back to NCFGR register 00670 AT91C_BASE_EMAC->EMAC_NCFGR = config; 00671 00672 //Successful processing 00673 return NO_ERROR; 00674 } 00675 00676 00677 /** 00678 * @brief Write PHY register 00679 * @param[in] phyAddr PHY address 00680 * @param[in] regAddr Register address 00681 * @param[in] data Register value 00682 **/ 00683 00684 void sam9263EthWritePhyReg(uint8_t phyAddr, uint8_t regAddr, uint16_t data) 00685 { 00686 uint32_t value; 00687 00688 //Set up a write operation 00689 value = AT91C_EMAC_SOF_01 | AT91C_EMAC_RW_01 | AT91C_EMAC_CODE_10; 00690 //PHY address 00691 value |= (phyAddr << 23) & AT91C_EMAC_PHYA; 00692 //Register address 00693 value |= (regAddr << 18) & AT91C_EMAC_REGA; 00694 //Register value 00695 value |= data & AT91C_EMAC_DATA; 00696 00697 //Start a write operation 00698 AT91C_BASE_EMAC->EMAC_MAN = value; 00699 //Wait for the write to complete 00700 while(!(AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE)); 00701 } 00702 00703 00704 /** 00705 * @brief Read PHY register 00706 * @param[in] phyAddr PHY address 00707 * @param[in] regAddr Register address 00708 * @return Register value 00709 **/ 00710 00711 uint16_t sam9263EthReadPhyReg(uint8_t phyAddr, uint8_t regAddr) 00712 { 00713 uint32_t value; 00714 00715 //Set up a read operation 00716 value = AT91C_EMAC_SOF_01 | AT91C_EMAC_RW_10 | AT91C_EMAC_CODE_10; 00717 //PHY address 00718 value |= (phyAddr << 23) & AT91C_EMAC_PHYA; 00719 //Register address 00720 value |= (regAddr << 18) & AT91C_EMAC_REGA; 00721 00722 //Start a read operation 00723 AT91C_BASE_EMAC->EMAC_MAN = value; 00724 //Wait for the read to complete 00725 while(!(AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE)); 00726 00727 //Return PHY register contents 00728 return AT91C_BASE_EMAC->EMAC_MAN & AT91C_EMAC_DATA; 00729 } 00730
Generated on Tue Jul 12 2022 17:10:16 by
1.7.2