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.
enc624j600.c
00001 /** 00002 * @file enc624j600.c 00003 * @brief ENC624J600/ENC424J600 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 "core/net.h" 00034 #include "drivers/enc624j600.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief ENC624J600 driver 00040 **/ 00041 00042 const NicDriver enc624j600Driver = 00043 { 00044 NIC_TYPE_ETHERNET, 00045 ETH_MTU, 00046 enc624j600Init, 00047 enc624j600Tick, 00048 enc624j600EnableIrq, 00049 enc624j600DisableIrq, 00050 enc624j600EventHandler, 00051 enc624j600SendPacket, 00052 enc624j600SetMulticastFilter, 00053 NULL, 00054 NULL, 00055 NULL, 00056 TRUE, 00057 TRUE, 00058 TRUE, 00059 FALSE 00060 }; 00061 00062 00063 /** 00064 * @brief ENC624J600 controller initialization 00065 * @param[in] interface Underlying network interface 00066 * @return Error code 00067 **/ 00068 00069 error_t enc624j600Init(NetInterface *interface) 00070 { 00071 Enc624j600Context *context; 00072 00073 //Debug message 00074 TRACE_INFO("Initializing ENC624J600 Ethernet controller...\r\n"); 00075 00076 //Initialize SPI 00077 interface->spiDriver->init(); 00078 //Initialize external interrupt line 00079 interface->extIntDriver->init(); 00080 00081 //Point to the driver context 00082 context = (Enc624j600Context *) interface->nicContext; 00083 00084 //Initialize driver specific variables 00085 context->nextPacket = ENC624J600_RX_BUFFER_START; 00086 00087 //Allocate RX buffer 00088 context->rxBuffer = memPoolAlloc(ETH_MAX_FRAME_SIZE); 00089 //Failed to allocate memory? 00090 if(context->rxBuffer == NULL) 00091 return ERROR_OUT_OF_MEMORY; 00092 00093 //Issue a system reset 00094 enc624j600SoftReset(interface); 00095 00096 //Disable CLKOUT output 00097 enc624j600WriteReg(interface, ENC624J600_REG_ECON2, ECON2_ETHEN | ECON2_STRCH); 00098 00099 //Optionally set the station MAC address 00100 if(macCompAddr(&interface->macAddr, &MAC_UNSPECIFIED_ADDR)) 00101 { 00102 //Use the factory preprogrammed station address 00103 interface->macAddr.w[0] = enc624j600ReadReg(interface, ENC624J600_REG_MAADR1); 00104 interface->macAddr.w[1] = enc624j600ReadReg(interface, ENC624J600_REG_MAADR2); 00105 interface->macAddr.w[2] = enc624j600ReadReg(interface, ENC624J600_REG_MAADR3); 00106 00107 //Generate the 64-bit interface identifier 00108 macAddrToEui64(&interface->macAddr, &interface->eui64); 00109 } 00110 else 00111 { 00112 //Override the factory preprogrammed address 00113 enc624j600WriteReg(interface, ENC624J600_REG_MAADR1, interface->macAddr.w[0]); 00114 enc624j600WriteReg(interface, ENC624J600_REG_MAADR2, interface->macAddr.w[1]); 00115 enc624j600WriteReg(interface, ENC624J600_REG_MAADR3, interface->macAddr.w[2]); 00116 } 00117 00118 //Set receive buffer location 00119 enc624j600WriteReg(interface, ENC624J600_REG_ERXST, ENC624J600_RX_BUFFER_START); 00120 //Program the tail pointer ERXTAIL to the last even address of the buffer 00121 enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, ENC624J600_RX_BUFFER_STOP); 00122 00123 //Configure the receive filters 00124 enc624j600WriteReg(interface, ENC624J600_REG_ERXFCON, ERXFCON_HTEN | 00125 ERXFCON_CRCEN | ERXFCON_RUNTEN | ERXFCON_UCEN | ERXFCON_BCEN); 00126 00127 //Initialize the hash table 00128 enc624j600WriteReg(interface, ENC624J600_REG_EHT1, 0x0000); 00129 enc624j600WriteReg(interface, ENC624J600_REG_EHT2, 0x0000); 00130 enc624j600WriteReg(interface, ENC624J600_REG_EHT3, 0x0000); 00131 enc624j600WriteReg(interface, ENC624J600_REG_EHT4, 0x0000); 00132 00133 //All short frames will be zero-padded to 60 bytes and a valid CRC is then appended 00134 enc624j600WriteReg(interface, ENC624J600_REG_MACON2, 00135 MACON2_DEFER | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1); 00136 00137 //Program the MAMXFL register with the maximum frame length to be accepted 00138 enc624j600WriteReg(interface, ENC624J600_REG_MAMXFL, 1518); 00139 00140 //PHY initialization 00141 enc624j600WritePhyReg(interface, ENC624J600_PHY_REG_PHANA, PHANA_ADPAUS0 | 00142 PHANA_AD100FD | PHANA_AD100 | PHANA_AD10FD | PHANA_AD10 | PHANA_ADIEEE0); 00143 00144 //Clear interrupt flags 00145 enc624j600WriteReg(interface, ENC624J600_REG_EIR, 0x0000); 00146 00147 //Configure interrupts as desired 00148 enc624j600WriteReg(interface, ENC624J600_REG_EIE, EIE_INTIE | 00149 EIE_LINKIE | EIE_PKTIE | EIE_TXIE | EIE_TXABTIE); 00150 00151 //Set RXEN to enable reception 00152 enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_RXEN); 00153 00154 //Dump registers for debugging purpose 00155 enc624j600DumpReg(interface); 00156 enc624j600DumpPhyReg(interface); 00157 00158 //Accept any packets from the upper layer 00159 osSetEvent(&interface->nicTxEvent); 00160 00161 //Force the TCP/IP stack to poll the link state at startup 00162 interface->nicEvent = TRUE; 00163 //Notify the TCP/IP stack of the event 00164 osSetEvent(&netEvent); 00165 00166 //Successful initialization 00167 return NO_ERROR; 00168 } 00169 00170 00171 /** 00172 * @brief ENC624J600 timer handler 00173 * @param[in] interface Underlying network interface 00174 **/ 00175 00176 void enc624j600Tick(NetInterface *interface) 00177 { 00178 } 00179 00180 00181 /** 00182 * @brief Enable interrupts 00183 * @param[in] interface Underlying network interface 00184 **/ 00185 00186 void enc624j600EnableIrq(NetInterface *interface) 00187 { 00188 //Enable interrupts 00189 interface->extIntDriver->enableIrq(); 00190 } 00191 00192 00193 /** 00194 * @brief Disable interrupts 00195 * @param[in] interface Underlying network interface 00196 **/ 00197 00198 void enc624j600DisableIrq(NetInterface *interface) 00199 { 00200 //Disable interrupts 00201 interface->extIntDriver->disableIrq(); 00202 } 00203 00204 00205 /** 00206 * @brief ENC624J600 interrupt service routine 00207 * @param[in] interface Underlying network interface 00208 * @return TRUE if a higher priority task must be woken. Else FALSE is returned 00209 **/ 00210 00211 bool_t enc624j600IrqHandler(NetInterface *interface) 00212 { 00213 bool_t flag; 00214 uint16_t status; 00215 00216 //This flag will be set if a higher priority task must be woken 00217 flag = FALSE; 00218 00219 //Clear the INTIE bit, immediately after an interrupt event 00220 enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_INTIE); 00221 00222 //Read interrupt status register 00223 status = enc624j600ReadReg(interface, ENC624J600_REG_EIR); 00224 00225 //Link status change? 00226 if(status & EIR_LINKIF) 00227 { 00228 //Disable LINKIE interrupt 00229 enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_LINKIE); 00230 00231 //Set event flag 00232 interface->nicEvent = TRUE; 00233 //Notify the TCP/IP stack of the event 00234 flag |= osSetEventFromIsr(&netEvent); 00235 } 00236 00237 //Packet received? 00238 if(status & EIR_PKTIF) 00239 { 00240 //Disable PKTIE interrupt 00241 enc624j600ClearBit(interface, ENC624J600_REG_EIE, EIE_PKTIE); 00242 00243 //Set event flag 00244 interface->nicEvent = TRUE; 00245 //Notify the TCP/IP stack of the event 00246 flag |= osSetEventFromIsr(&netEvent); 00247 } 00248 00249 //Packet transmission complete? 00250 if(status & (EIR_TXIF | EIR_TXABTIF)) 00251 { 00252 //Clear interrupt flags 00253 enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_TXIF | EIR_TXABTIF); 00254 00255 //Notify the TCP/IP stack that the transmitter is ready to send 00256 flag |= osSetEventFromIsr(&interface->nicTxEvent); 00257 } 00258 00259 //Once the interrupt has been serviced, the INTIE bit 00260 //is set again to re-enable interrupts 00261 enc624j600SetBit(interface, ENC624J600_REG_EIE, EIE_INTIE); 00262 00263 //A higher priority task must be woken? 00264 return flag; 00265 } 00266 00267 00268 /** 00269 * @brief ENC624J600 event handler 00270 * @param[in] interface Underlying network interface 00271 **/ 00272 00273 void enc624j600EventHandler(NetInterface *interface) 00274 { 00275 error_t error; 00276 uint16_t status; 00277 uint16_t value; 00278 00279 //Read interrupt status register 00280 status = enc624j600ReadReg(interface, ENC624J600_REG_EIR); 00281 00282 //Check whether the link state has changed 00283 if(status & EIR_LINKIF) 00284 { 00285 //Clear interrupt flag 00286 enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_LINKIF); 00287 //Read Ethernet status register 00288 value = enc624j600ReadReg(interface, ENC624J600_REG_ESTAT); 00289 00290 //Check link state 00291 if(value & ESTAT_PHYLNK) 00292 { 00293 //Read PHY status register 3 00294 value = enc624j600ReadPhyReg(interface, ENC624J600_PHY_REG_PHSTAT3); 00295 00296 //Get current speed 00297 if(value & PHSTAT3_SPDDPX1) 00298 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00299 else 00300 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00301 00302 //Determine the new duplex mode 00303 if(value & PHSTAT3_SPDDPX2) 00304 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00305 else 00306 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00307 00308 //Link is up 00309 interface->linkState = TRUE; 00310 00311 //Update MAC configuration parameters for proper operation 00312 enc624j600UpdateMacConfig(interface); 00313 } 00314 else 00315 { 00316 //Link is down 00317 interface->linkState = FALSE; 00318 } 00319 00320 //Process link state change event 00321 nicNotifyLinkChange(interface); 00322 } 00323 00324 //Check whether a packet has been received? 00325 if(status & EIR_PKTIF) 00326 { 00327 //Clear interrupt flag 00328 enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_PKTIF); 00329 00330 //Process all pending packets 00331 do 00332 { 00333 //Read incoming packet 00334 error = enc624j600ReceivePacket(interface); 00335 00336 //No more data in the receive buffer? 00337 } while(error != ERROR_BUFFER_EMPTY); 00338 } 00339 00340 //Re-enable LINKIE and PKTIE interrupts 00341 enc624j600SetBit(interface, ENC624J600_REG_EIE, EIE_LINKIE | EIE_PKTIE); 00342 } 00343 00344 00345 /** 00346 * @brief Send a packet 00347 * @param[in] interface Underlying network interface 00348 * @param[in] buffer Multi-part buffer containing the data to send 00349 * @param[in] offset Offset to the first data byte 00350 * @return Error code 00351 **/ 00352 00353 error_t enc624j600SendPacket(NetInterface *interface, 00354 const NetBuffer *buffer, size_t offset) 00355 { 00356 size_t length; 00357 00358 //Retrieve the length of the packet 00359 length = netBufferGetLength(buffer) - offset; 00360 00361 //Check the frame length 00362 if(length > 1536) 00363 { 00364 //The transmitter can accept another packet 00365 osSetEvent(&interface->nicTxEvent); 00366 //Report an error 00367 return ERROR_INVALID_LENGTH; 00368 } 00369 00370 //Make sure the link is up before transmitting the frame 00371 if(!interface->linkState) 00372 { 00373 //The transmitter can accept another packet 00374 osSetEventFromIsr(&interface->nicTxEvent); 00375 //Drop current packet 00376 return NO_ERROR; 00377 } 00378 00379 //Ensure that the transmitter is ready to send 00380 if(enc624j600ReadReg(interface, ENC624J600_REG_ECON1) & ECON1_TXRTS) 00381 return ERROR_FAILURE; 00382 00383 //Point to the SRAM buffer 00384 enc624j600WriteReg(interface, ENC624J600_REG_EGPWRPT, ENC624J600_TX_BUFFER_START); 00385 //Copy the packet to the SRAM buffer 00386 enc624j600WriteBuffer(interface, ENC624J600_CMD_WGPDATA, buffer, offset); 00387 00388 //Program ETXST to the start address of the packet 00389 enc624j600WriteReg(interface, ENC624J600_REG_ETXST, ENC624J600_TX_BUFFER_START); 00390 //Program ETXLEN with the length of data copied to the memory 00391 enc624j600WriteReg(interface, ENC624J600_REG_ETXLEN, length); 00392 00393 //Clear TXIF and TXABTIF interrupt flags 00394 enc624j600ClearBit(interface, ENC624J600_REG_EIR, EIR_TXIF | EIR_TXABTIF); 00395 //Set the TXRTS bit to initiate transmission 00396 enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_TXRTS); 00397 00398 //Successful processing 00399 return NO_ERROR; 00400 } 00401 00402 00403 /** 00404 * @brief Receive a packet 00405 * @param[in] interface Underlying network interface 00406 * @return Error code 00407 **/ 00408 00409 error_t enc624j600ReceivePacket(NetInterface *interface) 00410 { 00411 error_t error; 00412 uint16_t n; 00413 uint32_t status; 00414 Enc624j600Context *context; 00415 00416 //Point to the driver context 00417 context = (Enc624j600Context *) interface->nicContext; 00418 00419 //Verify that a packet is waiting by ensuring that PKTCNT is non-zero 00420 if(enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_PKTCNT) 00421 { 00422 //Point to the next packet 00423 enc624j600WriteReg(interface, ENC624J600_REG_ERXRDPT, context->nextPacket); 00424 00425 //Read the first two bytes, which are the address of the next packet 00426 enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA, 00427 (uint8_t *) &context->nextPacket, sizeof(uint16_t)); 00428 00429 //Get the length of the received frame in bytes 00430 enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA, 00431 (uint8_t *) &n, sizeof(uint16_t)); 00432 00433 //Read the receive status vector (RSV) 00434 enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA, 00435 (uint8_t *) &status, sizeof(uint32_t)); 00436 00437 //Make sure no error occurred 00438 if(status & RSV_RECEIVED_OK) 00439 { 00440 //Limit the number of data to read 00441 n = MIN(n, ETH_MAX_FRAME_SIZE); 00442 //Read the Ethernet frame 00443 enc624j600ReadBuffer(interface, ENC624J600_CMD_RRXDATA, context->rxBuffer, n); 00444 //Valid packet received 00445 error = NO_ERROR; 00446 } 00447 else 00448 { 00449 //The received packet contains an error 00450 error = ERROR_INVALID_PACKET; 00451 } 00452 00453 //Update the ERXTAIL pointer value to the point where the packet 00454 //has been processed, taking care to wrap back at the end of the 00455 //received memory buffer 00456 if(context->nextPacket == ENC624J600_RX_BUFFER_START) 00457 enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, ENC624J600_RX_BUFFER_STOP); 00458 else 00459 enc624j600WriteReg(interface, ENC624J600_REG_ERXTAIL, context->nextPacket - 2); 00460 00461 //Set PKTDEC to decrement the PKTCNT bits 00462 enc624j600SetBit(interface, ENC624J600_REG_ECON1, ECON1_PKTDEC); 00463 } 00464 else 00465 { 00466 //No more data in the receive buffer 00467 error = ERROR_BUFFER_EMPTY; 00468 } 00469 00470 //Check whether a valid packet has been received 00471 if(!error) 00472 { 00473 //Pass the packet to the upper layer 00474 nicProcessPacket(interface, context->rxBuffer, n); 00475 } 00476 00477 //Return status code 00478 return error; 00479 } 00480 00481 00482 /** 00483 * @brief Configure multicast MAC address filtering 00484 * @param[in] interface Underlying network interface 00485 * @return Error code 00486 **/ 00487 00488 error_t enc624j600SetMulticastFilter(NetInterface *interface) 00489 { 00490 uint_t i; 00491 uint_t k; 00492 uint32_t crc; 00493 uint16_t hashTable[4]; 00494 MacFilterEntry *entry; 00495 00496 //Debug message 00497 TRACE_DEBUG("Updating ENC624J600 hash table...\r\n"); 00498 00499 //Clear hash table 00500 memset(hashTable, 0, sizeof(hashTable)); 00501 00502 //The MAC filter table contains the multicast MAC addresses 00503 //to accept when receiving an Ethernet frame 00504 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00505 { 00506 //Point to the current entry 00507 entry = &interface->macMulticastFilter[i]; 00508 00509 //Valid entry? 00510 if(entry->refCount > 0) 00511 { 00512 //Compute CRC over the current MAC address 00513 crc = enc624j600CalcCrc(&entry->addr, sizeof(MacAddr)); 00514 //Calculate the corresponding index in the table 00515 k = (crc >> 23) & 0x3F; 00516 //Update hash table contents 00517 hashTable[k / 16] |= (1 << (k % 16)); 00518 } 00519 } 00520 00521 //Write the hash table to the ENC624J600 controller 00522 enc624j600WriteReg(interface, ENC624J600_REG_EHT1, hashTable[0]); 00523 enc624j600WriteReg(interface, ENC624J600_REG_EHT2, hashTable[1]); 00524 enc624j600WriteReg(interface, ENC624J600_REG_EHT3, hashTable[2]); 00525 enc624j600WriteReg(interface, ENC624J600_REG_EHT4, hashTable[3]); 00526 00527 //Debug message 00528 TRACE_DEBUG(" EHT1 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT1)); 00529 TRACE_DEBUG(" EHT2 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT2)); 00530 TRACE_DEBUG(" EHT3 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT3)); 00531 TRACE_DEBUG(" EHT4 = %04" PRIX16 "\r\n", enc624j600ReadReg(interface, ENC624J600_REG_EHT4)); 00532 00533 //Successful processing 00534 return NO_ERROR; 00535 } 00536 00537 00538 /** 00539 * @brief Adjust MAC configuration parameters for proper operation 00540 * @param[in] interface Underlying network interface 00541 **/ 00542 00543 void enc624j600UpdateMacConfig(NetInterface *interface) 00544 { 00545 uint16_t duplexMode; 00546 00547 //Determine the new duplex mode by reading the PHYDPX bit 00548 duplexMode = enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_PHYDPX; 00549 00550 //Full-duplex mode? 00551 if(duplexMode) 00552 { 00553 //Configure the FULDPX bit to match the current duplex mode 00554 enc624j600WriteReg(interface, ENC624J600_REG_MACON2, MACON2_DEFER | 00555 MACON2_PADCFG2 | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1 | MACON2_FULDPX); 00556 //Configure the Back-to-Back Inter-Packet Gap register 00557 enc624j600WriteReg(interface, ENC624J600_REG_MABBIPG, 0x15); 00558 } 00559 //Half-duplex mode? 00560 else 00561 { 00562 //Configure the FULDPX bit to match the current duplex mode 00563 enc624j600WriteReg(interface, ENC624J600_REG_MACON2, MACON2_DEFER | 00564 MACON2_PADCFG2 | MACON2_PADCFG0 | MACON2_TXCRCEN | MACON2_R1); 00565 //Configure the Back-to-Back Inter-Packet Gap register 00566 enc624j600WriteReg(interface, ENC624J600_REG_MABBIPG, 0x12); 00567 } 00568 } 00569 00570 00571 /** 00572 * @brief Reset ENC624J600 controller 00573 * @param[in] interface Underlying network interface 00574 * @return Error code 00575 **/ 00576 00577 error_t enc624j600SoftReset(NetInterface *interface) 00578 { 00579 //Wait for the SPI interface to be ready 00580 do 00581 { 00582 //Write 0x1234 to EUDAST 00583 enc624j600WriteReg(interface, ENC624J600_REG_EUDAST, 0x1234); 00584 //Read back register and check contents 00585 } while(enc624j600ReadReg(interface, ENC624J600_REG_EUDAST) != 0x1234); 00586 00587 //Poll CLKRDY and wait for it to become set 00588 while(!(enc624j600ReadReg(interface, ENC624J600_REG_ESTAT) & ESTAT_CLKRDY)); 00589 00590 //Issue a system reset command by setting ETHRST 00591 enc624j600SetBit(interface, ENC624J600_REG_ECON2, ECON2_ETHRST); 00592 //Wait at least 25us for the reset to take place 00593 sleep(1); 00594 00595 //Read EUDAST to confirm that the system reset took place. 00596 //EUDAST should have reverted back to its reset default 00597 if(enc624j600ReadReg(interface, ENC624J600_REG_EUDAST) != 0x0000) 00598 return ERROR_FAILURE; 00599 00600 //Wait at least 256us for the PHY registers and PHY 00601 //status bits to become available 00602 sleep(1); 00603 00604 //The controller is now ready to accept further commands 00605 return NO_ERROR; 00606 } 00607 00608 00609 /** 00610 * @brief Write ENC624J600 register 00611 * @param[in] interface Underlying network interface 00612 * @param[in] address Register address 00613 * @param[in] data Register value 00614 **/ 00615 00616 void enc624j600WriteReg(NetInterface *interface, uint8_t address, uint16_t data) 00617 { 00618 //Pull the CS pin low 00619 interface->spiDriver->assertCs(); 00620 00621 //Write opcode 00622 interface->spiDriver->transfer(ENC624J600_CMD_WCRU); 00623 //Write register address 00624 interface->spiDriver->transfer(address); 00625 //Write register value 00626 interface->spiDriver->transfer(LSB(data)); 00627 interface->spiDriver->transfer(MSB(data)); 00628 00629 //Terminate the operation by raising the CS pin 00630 interface->spiDriver->deassertCs(); 00631 } 00632 00633 00634 /** 00635 * @brief Read ENC624J600 register 00636 * @param[in] interface Underlying network interface 00637 * @param[in] address Register address 00638 * @return Register value 00639 **/ 00640 00641 uint16_t enc624j600ReadReg(NetInterface *interface, uint8_t address) 00642 { 00643 uint16_t data; 00644 00645 //Pull the CS pin low 00646 interface->spiDriver->assertCs(); 00647 00648 //Write opcode 00649 interface->spiDriver->transfer(ENC624J600_CMD_RCRU); 00650 //Write register address 00651 interface->spiDriver->transfer(address); 00652 //Read the lower 8 bits of data 00653 data = interface->spiDriver->transfer(0x00); 00654 //Read the upper 8 bits of data 00655 data |= interface->spiDriver->transfer(0x00) << 8; 00656 00657 //Terminate the operation by raising the CS pin 00658 interface->spiDriver->deassertCs(); 00659 00660 //Return register contents 00661 return data; 00662 } 00663 00664 00665 /** 00666 * @brief Write PHY register 00667 * @param[in] interface Underlying network interface 00668 * @param[in] address PHY register address 00669 * @param[in] data Register value 00670 **/ 00671 00672 void enc624j600WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data) 00673 { 00674 //Write the address of the PHY register to write to 00675 enc624j600WriteReg(interface, ENC624J600_REG_MIREGADR, MIREGADR_R8 | address); 00676 //Write the 16 bits of data into the MIWR register 00677 enc624j600WriteReg(interface, ENC624J600_REG_MIWR, data); 00678 00679 //Wait until the PHY register has been written 00680 while(enc624j600ReadReg(interface, ENC624J600_REG_MISTAT) & MISTAT_BUSY); 00681 } 00682 00683 00684 /** 00685 * @brief Read PHY register 00686 * @param[in] interface Underlying network interface 00687 * @param[in] address PHY register address 00688 * @return Register value 00689 **/ 00690 00691 uint16_t enc624j600ReadPhyReg(NetInterface *interface, uint8_t address) 00692 { 00693 //Write the address of the PHY register to read from 00694 enc624j600WriteReg(interface, ENC624J600_REG_MIREGADR, MIREGADR_R8 | address); 00695 //Start read operation 00696 enc624j600WriteReg(interface, ENC624J600_REG_MICMD, MICMD_MIIRD); 00697 00698 //Wait at least 25.6us before polling the BUSY bit 00699 usleep(100); 00700 //Wait for the read operation to complete 00701 while(enc624j600ReadReg(interface, ENC624J600_REG_MISTAT) & MISTAT_BUSY); 00702 00703 //Clear command register 00704 enc624j600WriteReg(interface, ENC624J600_REG_MICMD, 0x00); 00705 00706 //Return register contents 00707 return enc624j600ReadReg(interface, ENC624J600_REG_MIRD); 00708 } 00709 00710 00711 /** 00712 * @brief Write SRAM buffer 00713 * @param[in] interface Underlying network interface 00714 * @param[in] opcode SRAM buffer operation 00715 * @param[in] buffer Multi-part buffer containing the data to be written 00716 * @param[in] offset Offset to the first data byte 00717 **/ 00718 00719 void enc624j600WriteBuffer(NetInterface *interface, 00720 uint8_t opcode, const NetBuffer *buffer, size_t offset) 00721 { 00722 uint_t i; 00723 size_t j; 00724 size_t n; 00725 uint8_t *p; 00726 00727 //Pull the CS pin low 00728 interface->spiDriver->assertCs(); 00729 00730 //Write opcode 00731 interface->spiDriver->transfer(opcode); 00732 00733 //Loop through data chunks 00734 for(i = 0; i < buffer->chunkCount; i++) 00735 { 00736 //Is there any data to copy from the current chunk? 00737 if(offset < buffer->chunk[i].length) 00738 { 00739 //Point to the first byte to be read 00740 p = (uint8_t *) buffer->chunk[i].address + offset; 00741 //Compute the number of bytes to copy at a time 00742 n = buffer->chunk[i].length - offset; 00743 00744 //Copy data to SRAM buffer 00745 for(j = 0; j < n; j++) 00746 interface->spiDriver->transfer(p[j]); 00747 00748 //Process the next block from the start 00749 offset = 0; 00750 } 00751 else 00752 { 00753 //Skip the current chunk 00754 offset -= buffer->chunk[i].length; 00755 } 00756 } 00757 00758 //Terminate the operation by raising the CS pin 00759 interface->spiDriver->deassertCs(); 00760 } 00761 00762 00763 /** 00764 * @brief Read SRAM buffer 00765 * @param[in] interface Underlying network interface 00766 * @param[in] opcode SRAM buffer operation 00767 * @param[in] data Buffer where to store the incoming data 00768 * @param[in] length Number of data to read 00769 **/ 00770 00771 void enc624j600ReadBuffer(NetInterface *interface, 00772 uint8_t opcode, uint8_t *data, size_t length) 00773 { 00774 size_t i; 00775 00776 //Pull the CS pin low 00777 interface->spiDriver->assertCs(); 00778 00779 //Write opcode 00780 interface->spiDriver->transfer(opcode); 00781 00782 //Copy data from SRAM buffer 00783 for(i = 0; i < length; i++) 00784 data[i] = interface->spiDriver->transfer(0x00); 00785 00786 //Terminate the operation by raising the CS pin 00787 interface->spiDriver->deassertCs(); 00788 } 00789 00790 00791 /** 00792 * @brief Set bit field 00793 * @param[in] interface Underlying network interface 00794 * @param[in] address Register address 00795 * @param[in] mask Bits to set in the target register 00796 **/ 00797 00798 void enc624j600SetBit(NetInterface *interface, uint8_t address, uint16_t mask) 00799 { 00800 //Pull the CS pin low 00801 interface->spiDriver->assertCs(); 00802 00803 //Write opcode 00804 interface->spiDriver->transfer(ENC624J600_CMD_BFSU); 00805 //Write register address 00806 interface->spiDriver->transfer(address); 00807 //Write bit mask 00808 interface->spiDriver->transfer(LSB(mask)); 00809 interface->spiDriver->transfer(MSB(mask)); 00810 00811 //Terminate the operation by raising the CS pin 00812 interface->spiDriver->deassertCs(); 00813 } 00814 00815 00816 /** 00817 * @brief Clear bit field 00818 * @param[in] interface Underlying network interface 00819 * @param[in] address Register address 00820 * @param[in] mask Bits to clear in the target register 00821 **/ 00822 00823 void enc624j600ClearBit(NetInterface *interface, uint8_t address, uint16_t mask) 00824 { 00825 //Pull the CS pin low 00826 interface->spiDriver->assertCs(); 00827 00828 //Write opcode 00829 interface->spiDriver->transfer(ENC624J600_CMD_BFCU); 00830 //Write register address 00831 interface->spiDriver->transfer(address); 00832 //Write bit mask 00833 interface->spiDriver->transfer(LSB(mask)); 00834 interface->spiDriver->transfer(MSB(mask)); 00835 00836 //Terminate the operation by raising the CS pin 00837 interface->spiDriver->deassertCs(); 00838 } 00839 00840 00841 /** 00842 * @brief CRC calculation using the polynomial 0x4C11DB7 00843 * @param[in] data Pointer to the data over which to calculate the CRC 00844 * @param[in] length Number of bytes to process 00845 * @return Resulting CRC value 00846 **/ 00847 00848 uint32_t enc624j600CalcCrc(const void *data, size_t length) 00849 { 00850 uint_t i; 00851 uint_t j; 00852 00853 //Point to the data over which to calculate the CRC 00854 const uint8_t *p = (uint8_t *) data; 00855 //CRC preset value 00856 uint32_t crc = 0xFFFFFFFF; 00857 00858 //Loop through data 00859 for(i = 0; i < length; i++) 00860 { 00861 //The message is processed bit by bit 00862 for(j = 0; j < 8; j++) 00863 { 00864 //Update CRC value 00865 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00866 crc = (crc << 1) ^ 0x04C11DB7; 00867 else 00868 crc = crc << 1; 00869 } 00870 } 00871 00872 //Return CRC value 00873 return crc; 00874 } 00875 00876 00877 /** 00878 * @brief Dump registers for debugging purpose 00879 * @param[in] interface Underlying network interface 00880 **/ 00881 00882 void enc624j600DumpReg(NetInterface *interface) 00883 { 00884 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) 00885 uint8_t i; 00886 uint8_t bank; 00887 uint16_t address; 00888 00889 //Display header 00890 TRACE_DEBUG(" Bank 0 Bank 1 Bank 2 Bank 3 Unbanked\r\n"); 00891 00892 //Loop through register addresses 00893 for(i = 0; i < 32; i += 2) 00894 { 00895 //Display register address 00896 TRACE_DEBUG("%02" PRIX8 ": ", i); 00897 00898 //Loop through bank numbers 00899 for(bank = 0; bank < 5; bank++) 00900 { 00901 //Format register address 00902 address = 0x7E00 | (bank << 5) | i; 00903 //Display register contents 00904 TRACE_DEBUG("0x%04" PRIX16 " ", enc624j600ReadReg(interface, address)); 00905 } 00906 00907 //Jump to the following line 00908 TRACE_DEBUG("\r\n"); 00909 } 00910 00911 //Terminate with a line feed 00912 TRACE_DEBUG("\r\n"); 00913 #endif 00914 } 00915 00916 00917 /** 00918 * @brief Dump PHY registers for debugging purpose 00919 * @param[in] interface Underlying network interface 00920 **/ 00921 00922 void enc624j600DumpPhyReg(NetInterface *interface) 00923 { 00924 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) 00925 uint8_t i; 00926 00927 //Loop through PHY registers 00928 for(i = 0; i < 32; i++) 00929 { 00930 //Display current PHY register 00931 TRACE_DEBUG("%02" PRIX8 ": 0x%04" PRIX16 "\r\n", i, enc624j600ReadPhyReg(interface, i)); 00932 } 00933 00934 //Terminate with a line feed 00935 TRACE_DEBUG("\r\n"); 00936 #endif 00937 } 00938
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2