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