Embed:
(wiki syntax)
Show/hide line numbers
enc624j600.c
Go to the documentation of this file.
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
