Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
enc28j60.c
Go to the documentation of this file.
00001 /** 00002 * @file enc28j60.c 00003 * @brief ENC28J60 Ethernet 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 "core/net.h" 00035 #include "drivers/enc28j60.h" 00036 #include "debug.h" 00037 00038 00039 /** 00040 * @brief ENC28J60 driver 00041 **/ 00042 00043 const NicDriver enc28j60Driver = 00044 { 00045 NIC_TYPE_ETHERNET, 00046 ETH_MTU, 00047 enc28j60Init, 00048 enc28j60Tick, 00049 enc28j60EnableIrq, 00050 enc28j60DisableIrq, 00051 enc28j60EventHandler, 00052 enc28j60SendPacket, 00053 enc28j60SetMulticastFilter, 00054 NULL, 00055 NULL, 00056 NULL, 00057 TRUE, 00058 TRUE, 00059 TRUE, 00060 FALSE 00061 }; 00062 00063 00064 /** 00065 * @brief ENC28J60 controller initialization 00066 * @param[in] interface Underlying network interface 00067 * @return Error code 00068 **/ 00069 00070 error_t enc28j60Init(NetInterface *interface) 00071 { 00072 uint8_t revisionId; 00073 Enc28j60Context *context; 00074 00075 //Debug message 00076 TRACE_INFO("Initializing ENC28J60 Ethernet controller...\r\n"); 00077 00078 //Initialize SPI 00079 interface->spiDriver->init(); 00080 //Initialize external interrupt line 00081 interface->extIntDriver->init(); 00082 00083 //Issue a system reset 00084 enc28j60SoftReset(interface); 00085 00086 //After issuing the reset command, wait at least 1ms in firmware 00087 //for the device to be ready 00088 sleep(10); 00089 00090 //Point to the driver context 00091 context = (Enc28j60Context *) interface->nicContext; 00092 00093 //Initialize driver specific variables 00094 context->currentBank = UINT16_MAX; 00095 context->nextPacket = ENC28J60_RX_BUFFER_START; 00096 00097 //Allocate RX buffer 00098 context->rxBuffer = memPoolAlloc(ETH_MAX_FRAME_SIZE); 00099 //Failed to allocate memory? 00100 if(context->rxBuffer == NULL) 00101 return ERROR_OUT_OF_MEMORY; 00102 00103 //Read silicon revision ID 00104 revisionId = enc28j60ReadReg(interface, ENC28J60_REG_EREVID); 00105 00106 //Debug message 00107 TRACE_INFO("ENC28J60 revision ID: 0x%02X\r\n", revisionId); 00108 00109 //Disable CLKOUT output 00110 enc28j60WriteReg(interface, ENC28J60_REG_ECOCON, 0x00); 00111 00112 //Set the MAC address 00113 enc28j60WriteReg(interface, ENC28J60_REG_MAADR1, interface->macAddr.b[0]); 00114 enc28j60WriteReg(interface, ENC28J60_REG_MAADR2, interface->macAddr.b[1]); 00115 enc28j60WriteReg(interface, ENC28J60_REG_MAADR3, interface->macAddr.b[2]); 00116 enc28j60WriteReg(interface, ENC28J60_REG_MAADR4, interface->macAddr.b[3]); 00117 enc28j60WriteReg(interface, ENC28J60_REG_MAADR5, interface->macAddr.b[4]); 00118 enc28j60WriteReg(interface, ENC28J60_REG_MAADR6, interface->macAddr.b[5]); 00119 00120 //Set receive buffer location 00121 enc28j60WriteReg(interface, ENC28J60_REG_ERXSTL, LSB(ENC28J60_RX_BUFFER_START)); 00122 enc28j60WriteReg(interface, ENC28J60_REG_ERXSTH, MSB(ENC28J60_RX_BUFFER_START)); 00123 enc28j60WriteReg(interface, ENC28J60_REG_ERXNDL, LSB(ENC28J60_RX_BUFFER_STOP)); 00124 enc28j60WriteReg(interface, ENC28J60_REG_ERXNDH, MSB(ENC28J60_RX_BUFFER_STOP)); 00125 00126 //The ERXRDPT register defines a location within the FIFO 00127 //where the receive hardware is forbidden to write to 00128 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(ENC28J60_RX_BUFFER_STOP)); 00129 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(ENC28J60_RX_BUFFER_STOP)); 00130 00131 //Configure the receive filters 00132 enc28j60WriteReg(interface, ENC28J60_REG_ERXFCON, ERXFCON_UCEN | 00133 ERXFCON_CRCEN | ERXFCON_HTEN | ERXFCON_BCEN); 00134 00135 //Initialize the hash table 00136 enc28j60WriteReg(interface, ENC28J60_REG_EHT0, 0x00); 00137 enc28j60WriteReg(interface, ENC28J60_REG_EHT1, 0x00); 00138 enc28j60WriteReg(interface, ENC28J60_REG_EHT2, 0x00); 00139 enc28j60WriteReg(interface, ENC28J60_REG_EHT3, 0x00); 00140 enc28j60WriteReg(interface, ENC28J60_REG_EHT4, 0x00); 00141 enc28j60WriteReg(interface, ENC28J60_REG_EHT5, 0x00); 00142 enc28j60WriteReg(interface, ENC28J60_REG_EHT6, 0x00); 00143 enc28j60WriteReg(interface, ENC28J60_REG_EHT7, 0x00); 00144 00145 //Pull the MAC out of reset 00146 enc28j60WriteReg(interface, ENC28J60_REG_MACON2, 0x00); 00147 00148 //Enable the MAC to receive frames 00149 enc28j60WriteReg(interface, ENC28J60_REG_MACON1, 00150 MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN); 00151 00152 //Enable automatic padding to at least 60 bytes, always append a valid CRC 00153 //and check frame length. MAC can operate in half-duplex or full-duplex mode 00154 #if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED) 00155 enc28j60WriteReg(interface, ENC28J60_REG_MACON3, MACON3_PADCFG(1) | 00156 MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX); 00157 #else 00158 enc28j60WriteReg(interface, ENC28J60_REG_MACON3, MACON3_PADCFG(1) | 00159 MACON3_TXCRCEN | MACON3_FRMLNEN); 00160 #endif 00161 00162 //When the medium is occupied, the MAC will wait indefinitely for it to 00163 //become free when attempting to transmit 00164 enc28j60WriteReg(interface, ENC28J60_REG_MACON4, MACON4_DEFER); 00165 00166 //Maximum frame length that can be received or transmitted (1518 bytes) 00167 enc28j60WriteReg(interface, ENC28J60_REG_MAMXFLL, LSB(1518)); 00168 enc28j60WriteReg(interface, ENC28J60_REG_MAMXFLH, MSB(1518)); 00169 00170 //Configure the back-to-back inter-packet gap register 00171 #if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED) 00172 enc28j60WriteReg(interface, ENC28J60_REG_MABBIPG, 0x15); 00173 #else 00174 enc28j60WriteReg(interface, ENC28J60_REG_MABBIPG, 0x12); 00175 #endif 00176 00177 //Configure the non-back-to-back inter-packet gap register 00178 enc28j60WriteReg(interface, ENC28J60_REG_MAIPGL, 0x12); 00179 enc28j60WriteReg(interface, ENC28J60_REG_MAIPGH, 0x0C); 00180 00181 //Collision window register 00182 enc28j60WriteReg(interface, ENC28J60_REG_MACLCON2, 63); 00183 00184 //Set the PHY to the proper duplex mode 00185 #if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED) 00186 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON1, PHCON1_PDPXMD); 00187 #else 00188 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON1, 0x0000); 00189 #endif 00190 00191 //Disable half-duplex loopback in PHY 00192 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHCON2, PHCON2_HDLDIS); 00193 00194 //LEDA displays link status and LEDB displays TX/RX activity 00195 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHLCON, 00196 PHLCON_LACFG(4) | PHLCON_LBCFG(7) | PHLCON_LFRQ(0) | PHLCON_STRCH); 00197 00198 //Clear interrupt flags 00199 enc28j60WriteReg(interface, ENC28J60_REG_EIR, 0x00); 00200 00201 //Configure interrupts as desired 00202 enc28j60WriteReg(interface, ENC28J60_REG_EIE, EIE_INTIE | 00203 EIE_PKTIE | EIE_LINKIE | EIE_TXIE | EIE_TXERIE); 00204 00205 //Configure PHY interrupts as desired 00206 enc28j60WritePhyReg(interface, ENC28J60_PHY_REG_PHIE, 00207 PHIE_PLNKIE | PHIE_PGEIE); 00208 00209 //Set RXEN to enable reception 00210 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_RXEN); 00211 00212 //Dump registers for debugging purpose 00213 enc28j60DumpReg(interface); 00214 enc28j60DumpPhyReg(interface); 00215 00216 //Accept any packets from the upper layer 00217 osSetEvent(&interface->nicTxEvent); 00218 00219 //Force the TCP/IP stack to poll the link state at startup 00220 interface->nicEvent = TRUE; 00221 //Notify the TCP/IP stack of the event 00222 osSetEvent(&netEvent); 00223 00224 //Successful initialization 00225 return NO_ERROR; 00226 } 00227 00228 00229 /** 00230 * @brief ENC28J60 timer handler 00231 * @param[in] interface Underlying network interface 00232 **/ 00233 00234 void enc28j60Tick(NetInterface *interface) 00235 { 00236 } 00237 00238 00239 /** 00240 * @brief Enable interrupts 00241 * @param[in] interface Underlying network interface 00242 **/ 00243 00244 void enc28j60EnableIrq(NetInterface *interface) 00245 { 00246 //Enable interrupts 00247 interface->extIntDriver->enableIrq(); 00248 } 00249 00250 00251 /** 00252 * @brief Disable interrupts 00253 * @param[in] interface Underlying network interface 00254 **/ 00255 00256 void enc28j60DisableIrq(NetInterface *interface) 00257 { 00258 //Disable interrupts 00259 interface->extIntDriver->disableIrq(); 00260 } 00261 00262 00263 /** 00264 * @brief ENC28J60 interrupt service routine 00265 * @param[in] interface Underlying network interface 00266 * @return TRUE if a higher priority task must be woken. Else FALSE is returned 00267 **/ 00268 00269 bool_t enc28j60IrqHandler(NetInterface *interface) 00270 { 00271 bool_t flag; 00272 uint8_t status; 00273 00274 //This flag will be set if a higher priority task must be woken 00275 flag = FALSE; 00276 00277 //Clear the INTIE bit, immediately after an interrupt event 00278 enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_INTIE); 00279 00280 //Read interrupt status register 00281 status = enc28j60ReadReg(interface, ENC28J60_REG_EIR); 00282 00283 //Link status change? 00284 if(status & EIR_LINKIF) 00285 { 00286 //Disable LINKIE interrupt 00287 enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_LINKIE); 00288 00289 //Set event flag 00290 interface->nicEvent = TRUE; 00291 //Notify the TCP/IP stack of the event 00292 flag |= osSetEventFromIsr(&netEvent); 00293 } 00294 00295 //Packet received? 00296 if(status & EIR_PKTIF) 00297 { 00298 //Disable PKTIE interrupt 00299 enc28j60ClearBit(interface, ENC28J60_REG_EIE, EIE_PKTIE); 00300 00301 //Set event flag 00302 interface->nicEvent = TRUE; 00303 //Notify the TCP/IP stack of the event 00304 flag |= osSetEventFromIsr(&netEvent); 00305 } 00306 00307 //Packet transmission complete? 00308 if(status & (EIR_TXIF | EIE_TXERIE)) 00309 { 00310 //Clear interrupt flags 00311 enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_TXIF | EIE_TXERIE); 00312 00313 //Notify the TCP/IP stack that the transmitter is ready to send 00314 flag |= osSetEventFromIsr(&interface->nicTxEvent); 00315 } 00316 00317 //Once the interrupt has been serviced, the INTIE bit 00318 //is set again to re-enable interrupts 00319 enc28j60SetBit(interface, ENC28J60_REG_EIE, EIE_INTIE); 00320 00321 //A higher priority task must be woken? 00322 return flag; 00323 } 00324 00325 00326 /** 00327 * @brief ENC28J60 event handler 00328 * @param[in] interface Underlying network interface 00329 **/ 00330 00331 void enc28j60EventHandler(NetInterface *interface) 00332 { 00333 error_t error; 00334 uint16_t status; 00335 uint16_t value; 00336 00337 //Read interrupt status register 00338 status = enc28j60ReadReg(interface, ENC28J60_REG_EIR); 00339 00340 //Check whether the link state has changed 00341 if(status & EIR_LINKIF) 00342 { 00343 //Clear PHY interrupts flags 00344 enc28j60ReadPhyReg(interface, ENC28J60_PHY_REG_PHIR); 00345 //Clear interrupt flag 00346 enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_LINKIF); 00347 //Read PHY status register 00348 value = enc28j60ReadPhyReg(interface, ENC28J60_PHY_REG_PHSTAT2); 00349 00350 //Check link state 00351 if(value & PHSTAT2_LSTAT) 00352 { 00353 //Link speed 00354 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00355 00356 #if (ENC28J60_FULL_DUPLEX_SUPPORT == ENABLED) 00357 //Full-duplex mode 00358 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00359 #else 00360 //Half-duplex mode 00361 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00362 #endif 00363 //Link is up 00364 interface->linkState = TRUE; 00365 } 00366 else 00367 { 00368 //Link is down 00369 interface->linkState = FALSE; 00370 } 00371 00372 //Process link state change event 00373 nicNotifyLinkChange(interface); 00374 } 00375 00376 //Check whether a packet has been received? 00377 if(status & EIR_PKTIF) 00378 { 00379 //Clear interrupt flag 00380 enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_PKTIF); 00381 00382 //Process all pending packets 00383 do 00384 { 00385 //Read incoming packet 00386 error = enc28j60ReceivePacket(interface); 00387 00388 //No more data in the receive buffer? 00389 } while(error != ERROR_BUFFER_EMPTY); 00390 } 00391 00392 //Re-enable LINKIE and PKTIE interrupts 00393 enc28j60SetBit(interface, ENC28J60_REG_EIE, EIE_LINKIE | EIE_PKTIE); 00394 } 00395 00396 00397 /** 00398 * @brief Send a packet 00399 * @param[in] interface Underlying network interface 00400 * @param[in] buffer Multi-part buffer containing the data to send 00401 * @param[in] offset Offset to the first data byte 00402 * @return Error code 00403 **/ 00404 00405 error_t enc28j60SendPacket(NetInterface *interface, 00406 const NetBuffer *buffer, size_t offset) 00407 { 00408 size_t length; 00409 00410 //Retrieve the length of the packet 00411 length = netBufferGetLength(buffer) - offset; 00412 00413 //Check the frame length 00414 if(length > 1536) 00415 { 00416 //The transmitter can accept another packet 00417 osSetEvent(&interface->nicTxEvent); 00418 //Report an error 00419 return ERROR_INVALID_LENGTH; 00420 } 00421 00422 //Make sure the link is up before transmitting the frame 00423 if(!interface->linkState) 00424 { 00425 //The transmitter can accept another packet 00426 osSetEventFromIsr(&interface->nicTxEvent); 00427 //Drop current packet 00428 return NO_ERROR; 00429 } 00430 00431 //It is recommended to reset the transmit logic before 00432 //attempting to transmit a packet 00433 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_TXRST); 00434 enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_TXRST); 00435 00436 //Interrupt flags should be cleared after the reset is completed 00437 enc28j60ClearBit(interface, ENC28J60_REG_EIR, EIR_TXIF | EIR_TXERIF); 00438 00439 //Set transmit buffer location 00440 enc28j60WriteReg(interface, ENC28J60_REG_ETXSTL, LSB(ENC28J60_TX_BUFFER_START)); 00441 enc28j60WriteReg(interface, ENC28J60_REG_ETXSTH, MSB(ENC28J60_TX_BUFFER_START)); 00442 00443 //Point to start of transmit buffer 00444 enc28j60WriteReg(interface, ENC28J60_REG_EWRPTL, LSB(ENC28J60_TX_BUFFER_START)); 00445 enc28j60WriteReg(interface, ENC28J60_REG_EWRPTH, MSB(ENC28J60_TX_BUFFER_START)); 00446 00447 //Copy the data to the transmit buffer 00448 enc28j60WriteBuffer(interface, buffer, offset); 00449 00450 //ETXND should point to the last byte in the data payload 00451 enc28j60WriteReg(interface, ENC28J60_REG_ETXNDL, LSB(ENC28J60_TX_BUFFER_START + length)); 00452 enc28j60WriteReg(interface, ENC28J60_REG_ETXNDH, MSB(ENC28J60_TX_BUFFER_START + length)); 00453 00454 //Start transmission 00455 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_TXRTS); 00456 00457 //Successful processing 00458 return NO_ERROR; 00459 } 00460 00461 00462 /** 00463 * @brief Receive a packet 00464 * @param[in] interface Underlying network interface 00465 * @return Error code 00466 **/ 00467 00468 error_t enc28j60ReceivePacket(NetInterface *interface) 00469 { 00470 error_t error; 00471 uint16_t n; 00472 uint16_t status; 00473 Enc28j60Context *context; 00474 00475 //Point to the driver context 00476 context = (Enc28j60Context *) interface->nicContext; 00477 00478 //Any packet pending in the receive buffer? 00479 if(enc28j60ReadReg(interface, ENC28J60_REG_EPKTCNT)) 00480 { 00481 //Point to the start of the received packet 00482 enc28j60WriteReg(interface, ENC28J60_REG_ERDPTL, LSB(context->nextPacket)); 00483 enc28j60WriteReg(interface, ENC28J60_REG_ERDPTH, MSB(context->nextPacket)); 00484 00485 //Read the first two bytes, which are the address of the next packet 00486 enc28j60ReadBuffer(interface, (uint8_t *) &context->nextPacket, sizeof(uint16_t)); 00487 //Get the length of the received frame in bytes 00488 enc28j60ReadBuffer(interface, (uint8_t *) &n, sizeof(uint16_t)); 00489 //Read the receive status vector (RSV) 00490 enc28j60ReadBuffer(interface, (uint8_t *) &status, sizeof(uint16_t)); 00491 00492 //Make sure no error occurred 00493 if(status & RSV_RECEIVED_OK) 00494 { 00495 //Limit the number of data to read 00496 n = MIN(n, ETH_MAX_FRAME_SIZE); 00497 //Read the Ethernet frame 00498 enc28j60ReadBuffer(interface, context->rxBuffer, n); 00499 //Valid packet received 00500 error = NO_ERROR; 00501 } 00502 else 00503 { 00504 //The received packet contains an error 00505 error = ERROR_INVALID_PACKET; 00506 } 00507 00508 //Advance the ERXRDPT pointer, taking care to wrap back at the 00509 //end of the received memory buffer 00510 if(context->nextPacket == ENC28J60_RX_BUFFER_START) 00511 { 00512 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(ENC28J60_RX_BUFFER_STOP)); 00513 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(ENC28J60_RX_BUFFER_STOP)); 00514 } 00515 else 00516 { 00517 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTL, LSB(context->nextPacket - 1)); 00518 enc28j60WriteReg(interface, ENC28J60_REG_ERXRDPTH, MSB(context->nextPacket - 1)); 00519 } 00520 00521 //Decrement the packet counter 00522 enc28j60SetBit(interface, ENC28J60_REG_ECON2, ECON2_PKTDEC); 00523 } 00524 else 00525 { 00526 //No more data in the receive buffer 00527 error = ERROR_BUFFER_EMPTY; 00528 } 00529 00530 //Check whether a valid packet has been received 00531 if(!error) 00532 { 00533 //Pass the packet to the upper layer 00534 nicProcessPacket(interface, context->rxBuffer, n); 00535 } 00536 00537 //Return status code 00538 return error; 00539 } 00540 00541 00542 /** 00543 * @brief Configure multicast MAC address filtering 00544 * @param[in] interface Underlying network interface 00545 * @return Error code 00546 **/ 00547 00548 error_t enc28j60SetMulticastFilter(NetInterface *interface) 00549 { 00550 uint_t i; 00551 uint_t k; 00552 uint32_t crc; 00553 uint8_t hashTable[8]; 00554 MacFilterEntry *entry; 00555 00556 //Debug message 00557 TRACE_DEBUG("Updating ENC28J60 hash table...\r\n"); 00558 00559 //Clear hash table 00560 memset(hashTable, 0, sizeof(hashTable)); 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 = enc28j60CalcCrc(&entry->addr, sizeof(MacAddr)); 00574 //Calculate the corresponding index in the table 00575 k = (crc >> 23) & 0x3F; 00576 //Update hash table contents 00577 hashTable[k / 8] |= (1 << (k % 8)); 00578 } 00579 } 00580 00581 //Write the hash table to the ENC28J60 controller 00582 enc28j60WriteReg(interface, ENC28J60_REG_EHT0, hashTable[0]); 00583 enc28j60WriteReg(interface, ENC28J60_REG_EHT1, hashTable[1]); 00584 enc28j60WriteReg(interface, ENC28J60_REG_EHT2, hashTable[2]); 00585 enc28j60WriteReg(interface, ENC28J60_REG_EHT3, hashTable[3]); 00586 enc28j60WriteReg(interface, ENC28J60_REG_EHT4, hashTable[4]); 00587 enc28j60WriteReg(interface, ENC28J60_REG_EHT5, hashTable[5]); 00588 enc28j60WriteReg(interface, ENC28J60_REG_EHT6, hashTable[6]); 00589 enc28j60WriteReg(interface, ENC28J60_REG_EHT7, hashTable[7]); 00590 00591 //Debug message 00592 TRACE_DEBUG(" EHT0 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT0)); 00593 TRACE_DEBUG(" EHT1 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT1)); 00594 TRACE_DEBUG(" EHT2 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT2)); 00595 TRACE_DEBUG(" EHT3 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT3)); 00596 TRACE_DEBUG(" EHT0 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT4)); 00597 TRACE_DEBUG(" EHT1 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT5)); 00598 TRACE_DEBUG(" EHT2 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT6)); 00599 TRACE_DEBUG(" EHT3 = %02" PRIX8 "\r\n", enc28j60ReadReg(interface, ENC28J60_REG_EHT7)); 00600 00601 //Successful processing 00602 return NO_ERROR; 00603 } 00604 00605 00606 /** 00607 * @brief ENC28J60 controller reset 00608 * @param[in] interface Underlying network interface 00609 **/ 00610 00611 void enc28j60SoftReset(NetInterface *interface) 00612 { 00613 //Pull the CS pin low 00614 interface->spiDriver->assertCs(); 00615 00616 //Write opcode 00617 interface->spiDriver->transfer(ENC28J60_CMD_SRC); 00618 00619 //Terminate the operation by raising the CS pin 00620 interface->spiDriver->deassertCs(); 00621 } 00622 00623 00624 /** 00625 * @brief Bank selection 00626 * @param[in] interface Underlying network interface 00627 * @param[in] address Register address 00628 **/ 00629 00630 void enc28j60SelectBank(NetInterface *interface, uint16_t address) 00631 { 00632 uint16_t bank; 00633 Enc28j60Context *context; 00634 00635 //Point to the driver context 00636 context = (Enc28j60Context *) interface->nicContext; 00637 00638 //Get the bank number from the specified address 00639 bank = address & REG_BANK_MASK; 00640 00641 //Rewrite the bank number only if a change is detected 00642 if(bank != context->currentBank) 00643 { 00644 //Select specified bank 00645 switch(bank) 00646 { 00647 case BANK_0: 00648 //Select bank 0 00649 enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1 | ECON1_BSEL0); 00650 break; 00651 case BANK_1: 00652 //Select bank 1 00653 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL0); 00654 enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1); 00655 break; 00656 case BANK_2: 00657 //Select bank 2 00658 enc28j60ClearBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL0); 00659 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1); 00660 break; 00661 case BANK_3: 00662 //Select bank 3 00663 enc28j60SetBit(interface, ENC28J60_REG_ECON1, ECON1_BSEL1 | ECON1_BSEL0); 00664 break; 00665 default: 00666 //Invalid bank 00667 break; 00668 } 00669 00670 //Save bank number 00671 context->currentBank = bank; 00672 } 00673 } 00674 00675 00676 /** 00677 * @brief Write ENC28J60 register 00678 * @param[in] interface Underlying network interface 00679 * @param[in] address Register address 00680 * @param[in] data Register value 00681 **/ 00682 00683 void enc28j60WriteReg(NetInterface *interface, uint16_t address, uint8_t data) 00684 { 00685 //Make sure the corresponding bank is selected 00686 enc28j60SelectBank(interface, address); 00687 00688 //Pull the CS pin low 00689 interface->spiDriver->assertCs(); 00690 00691 //Write opcode and register address 00692 interface->spiDriver->transfer(ENC28J60_CMD_WCR | (address & REG_ADDR_MASK)); 00693 //Write register value 00694 interface->spiDriver->transfer(data); 00695 00696 //Terminate the operation by raising the CS pin 00697 interface->spiDriver->deassertCs(); 00698 } 00699 00700 00701 /** 00702 * @brief Read ENC28J60 register 00703 * @param[in] interface Underlying network interface 00704 * @param[in] address Register address 00705 * @return Register value 00706 **/ 00707 00708 uint8_t enc28j60ReadReg(NetInterface *interface, uint16_t address) 00709 { 00710 uint16_t data; 00711 00712 //Make sure the corresponding bank is selected 00713 enc28j60SelectBank(interface, address); 00714 00715 //Pull the CS pin low 00716 interface->spiDriver->assertCs(); 00717 00718 //Write opcode and register address 00719 interface->spiDriver->transfer(ENC28J60_CMD_RCR | (address & REG_ADDR_MASK)); 00720 00721 //When reading MAC or MII registers, a dummy byte is first shifted out 00722 if((address & REG_TYPE_MASK) != ETH_REG_TYPE) 00723 interface->spiDriver->transfer(0x00); 00724 00725 //Read register contents 00726 data = interface->spiDriver->transfer(0x00); 00727 00728 //Terminate the operation by raising the CS pin 00729 interface->spiDriver->deassertCs(); 00730 00731 //Return register contents 00732 return data; 00733 } 00734 00735 00736 /** 00737 * @brief Write PHY register 00738 * @param[in] interface Underlying network interface 00739 * @param[in] address PHY register address 00740 * @param[in] data Register value 00741 **/ 00742 00743 void enc28j60WritePhyReg(NetInterface *interface, uint16_t address, uint16_t data) 00744 { 00745 //Write register address 00746 enc28j60WriteReg(interface, ENC28J60_REG_MIREGADR, address & REG_ADDR_MASK); 00747 00748 //Write the lower 8 bits 00749 enc28j60WriteReg(interface, ENC28J60_REG_MIWRL, LSB(data)); 00750 //Write the upper 8 bits 00751 enc28j60WriteReg(interface, ENC28J60_REG_MIWRH, MSB(data)); 00752 00753 //Wait until the PHY register has been written 00754 while(enc28j60ReadReg(interface, ENC28J60_REG_MISTAT) & MISTAT_BUSY); 00755 } 00756 00757 00758 /** 00759 * @brief Read PHY register 00760 * @param[in] interface Underlying network interface 00761 * @param[in] address PHY register address 00762 * @return Register value 00763 **/ 00764 00765 uint16_t enc28j60ReadPhyReg(NetInterface *interface, uint16_t address) 00766 { 00767 uint16_t data; 00768 00769 //Write register address 00770 enc28j60WriteReg(interface, ENC28J60_REG_MIREGADR, address & REG_ADDR_MASK); 00771 00772 //Start read operation 00773 enc28j60WriteReg(interface, ENC28J60_REG_MICMD, MICMD_MIIRD); 00774 //Wait for the read operation to complete 00775 while(enc28j60ReadReg(interface, ENC28J60_REG_MISTAT) & MISTAT_BUSY); 00776 //Clear command register 00777 enc28j60WriteReg(interface, ENC28J60_REG_MICMD, 0); 00778 00779 //Read the lower 8 bits 00780 data = enc28j60ReadReg(interface, ENC28J60_REG_MIRDL); 00781 //Read the upper 8 bits 00782 data |= enc28j60ReadReg(interface, ENC28J60_REG_MIRDH) << 8; 00783 00784 //Return register contents 00785 return data; 00786 } 00787 00788 00789 /** 00790 * @brief Write SRAM buffer 00791 * @param[in] interface Underlying network interface 00792 * @param[in] buffer Multi-part buffer containing the data to be written 00793 * @param[in] offset Offset to the first data byte 00794 **/ 00795 00796 void enc28j60WriteBuffer(NetInterface *interface, 00797 const NetBuffer *buffer, size_t offset) 00798 { 00799 uint_t i; 00800 size_t j; 00801 size_t n; 00802 uint8_t *p; 00803 00804 //Pull the CS pin low 00805 interface->spiDriver->assertCs(); 00806 00807 //Write opcode 00808 interface->spiDriver->transfer(ENC28J60_CMD_WBM); 00809 //Write per-packet control byte 00810 interface->spiDriver->transfer(0x00); 00811 00812 //Loop through data chunks 00813 for(i = 0; i < buffer->chunkCount; i++) 00814 { 00815 //Is there any data to copy from the current chunk? 00816 if(offset < buffer->chunk[i].length) 00817 { 00818 //Point to the first byte to be read 00819 p = (uint8_t *) buffer->chunk[i].address + offset; 00820 //Compute the number of bytes to copy at a time 00821 n = buffer->chunk[i].length - offset; 00822 00823 //Copy data to SRAM buffer 00824 for(j = 0; j < n; j++) 00825 interface->spiDriver->transfer(p[j]); 00826 00827 //Process the next block from the start 00828 offset = 0; 00829 } 00830 else 00831 { 00832 //Skip the current chunk 00833 offset -= buffer->chunk[i].length; 00834 } 00835 } 00836 00837 //Terminate the operation by raising the CS pin 00838 interface->spiDriver->deassertCs(); 00839 } 00840 00841 00842 /** 00843 * @brief Read SRAM buffer 00844 * @param[in] interface Underlying network interface 00845 * @param[in] data Buffer where to store the incoming data 00846 * @param[in] length Number of data to read 00847 **/ 00848 00849 void enc28j60ReadBuffer(NetInterface *interface, 00850 uint8_t *data, size_t length) 00851 { 00852 size_t i; 00853 00854 //Pull the CS pin low 00855 interface->spiDriver->assertCs(); 00856 00857 //Write opcode 00858 interface->spiDriver->transfer(ENC28J60_CMD_RBM); 00859 00860 //Copy data from SRAM buffer 00861 for(i = 0; i < length; i++) 00862 data[i] = interface->spiDriver->transfer(0x00); 00863 00864 //Terminate the operation by raising the CS pin 00865 interface->spiDriver->deassertCs(); 00866 } 00867 00868 00869 /** 00870 * @brief Set bit field 00871 * @param[in] interface Underlying network interface 00872 * @param[in] address Register address 00873 * @param[in] mask Bits to set in the target register 00874 **/ 00875 00876 void enc28j60SetBit(NetInterface *interface, uint16_t address, uint16_t mask) 00877 { 00878 //Pull the CS pin low 00879 interface->spiDriver->assertCs(); 00880 00881 //Write opcode and register address 00882 interface->spiDriver->transfer(ENC28J60_CMD_BFS | (address & REG_ADDR_MASK)); 00883 //Write bit mask 00884 interface->spiDriver->transfer(mask); 00885 00886 //Terminate the operation by raising the CS pin 00887 interface->spiDriver->deassertCs(); 00888 } 00889 00890 00891 /** 00892 * @brief Clear bit field 00893 * @param[in] interface Underlying network interface 00894 * @param[in] address Register address 00895 * @param[in] mask Bits to clear in the target register 00896 **/ 00897 00898 void enc28j60ClearBit(NetInterface *interface, uint16_t address, uint16_t mask) 00899 { 00900 //Pull the CS pin low 00901 interface->spiDriver->assertCs(); 00902 00903 //Write opcode and register address 00904 interface->spiDriver->transfer(ENC28J60_CMD_BFC | (address & REG_ADDR_MASK)); 00905 //Write bit mask 00906 interface->spiDriver->transfer(mask); 00907 00908 //Terminate the operation by raising the CS pin 00909 interface->spiDriver->deassertCs(); 00910 } 00911 00912 00913 /** 00914 * @brief CRC calculation using the polynomial 0x4C11DB7 00915 * @param[in] data Pointer to the data over which to calculate the CRC 00916 * @param[in] length Number of bytes to process 00917 * @return Resulting CRC value 00918 **/ 00919 00920 uint32_t enc28j60CalcCrc(const void *data, size_t length) 00921 { 00922 uint_t i; 00923 uint_t j; 00924 00925 //Point to the data over which to calculate the CRC 00926 const uint8_t *p = (uint8_t *) data; 00927 //CRC preset value 00928 uint32_t crc = 0xFFFFFFFF; 00929 00930 //Loop through data 00931 for(i = 0; i < length; i++) 00932 { 00933 //The message is processed bit by bit 00934 for(j = 0; j < 8; j++) 00935 { 00936 //Update CRC value 00937 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00938 crc = (crc << 1) ^ 0x04C11DB7; 00939 else 00940 crc = crc << 1; 00941 } 00942 } 00943 00944 //Return CRC value 00945 return crc; 00946 } 00947 00948 00949 /** 00950 * @brief Dump registers for debugging purpose 00951 * @param[in] interface Underlying network interface 00952 **/ 00953 00954 void enc28j60DumpReg(NetInterface *interface) 00955 { 00956 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) 00957 uint8_t i; 00958 uint8_t bank; 00959 uint16_t address; 00960 00961 //Display header 00962 TRACE_DEBUG(" Bank 0 Bank 1 Bank 2 Bank 3\r\n"); 00963 00964 //Loop through register addresses 00965 for(i = 0; i < 32; i++) 00966 { 00967 //Display register address 00968 TRACE_DEBUG("%02" PRIX8 ": ", i); 00969 00970 //Loop through bank numbers 00971 for(bank = 0; bank < 4; bank++) 00972 { 00973 //Format register address 00974 address = (bank << 8) | i; 00975 00976 //MAC and MII registers require a specific read sequence 00977 if(address >= 0x200 && address <= 0x219) 00978 address |= MAC_REG_TYPE; 00979 else if(address >= 0x300 && address <= 0x305) 00980 address |= MAC_REG_TYPE; 00981 else if(address == 0x30A) 00982 address |= MAC_REG_TYPE; 00983 00984 //Display register contents 00985 TRACE_DEBUG("0x%02" PRIX8 " ", enc28j60ReadReg(interface, address)); 00986 } 00987 00988 //Jump to the following line 00989 TRACE_DEBUG("\r\n"); 00990 } 00991 00992 //Terminate with a line feed 00993 TRACE_DEBUG("\r\n"); 00994 #endif 00995 } 00996 00997 00998 /** 00999 * @brief Dump PHY registers for debugging purpose 01000 * @param[in] interface Underlying network interface 01001 **/ 01002 01003 void enc28j60DumpPhyReg(NetInterface *interface) 01004 { 01005 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) 01006 uint8_t i; 01007 01008 //Loop through PHY registers 01009 for(i = 0; i < 32; i++) 01010 { 01011 //Display current PHY register 01012 TRACE_DEBUG("%02" PRIX8 ": 0x%04" PRIX16 "\r\n", i, enc28j60ReadPhyReg(interface, i)); 01013 } 01014 01015 //Terminate with a line feed 01016 TRACE_DEBUG("\r\n"); 01017 #endif 01018 } 01019
Generated on Tue Jul 12 2022 17:10:13 by
