Webserver+3d print
Embed:
(wiki syntax)
Show/hide line numbers
ksz8851.c
Go to the documentation of this file.
00001 /** 00002 * @file ksz8851.c 00003 * @brief KSZ8851 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/ksz8851.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief KSZ8851 driver 00040 **/ 00041 00042 const NicDriver ksz8851Driver = 00043 { 00044 NIC_TYPE_ETHERNET, 00045 ETH_MTU, 00046 ksz8851Init, 00047 ksz8851Tick, 00048 ksz8851EnableIrq, 00049 ksz8851DisableIrq, 00050 ksz8851EventHandler, 00051 ksz8851SendPacket, 00052 ksz8851SetMulticastFilter, 00053 NULL, 00054 NULL, 00055 NULL, 00056 TRUE, 00057 TRUE, 00058 TRUE, 00059 FALSE 00060 }; 00061 00062 00063 /** 00064 * @brief KSZ8851 controller initialization 00065 * @param[in] interface Underlying network interface 00066 * @return Error code 00067 **/ 00068 00069 error_t ksz8851Init(NetInterface *interface) 00070 { 00071 //Point to the driver context 00072 Ksz8851Context *context = (Ksz8851Context *) interface->nicContext; 00073 00074 //Debug message 00075 TRACE_INFO("Initializing KSZ8851 Ethernet controller...\r\n"); 00076 00077 #if (KSZ8851_SPI_SUPPORT == ENABLED) 00078 //Initialize SPI 00079 interface->spiDriver->init(); 00080 #endif 00081 00082 //Initialize external interrupt line 00083 interface->extIntDriver->init(); 00084 00085 //Debug message 00086 TRACE_DEBUG("CIDER=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_CIDER)); 00087 TRACE_DEBUG("PHY1ILR=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_PHY1ILR)); 00088 TRACE_DEBUG("PHY1IHR=0x%04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_PHY1IHR)); 00089 00090 //Check device ID and revision ID 00091 if(ksz8851ReadReg(interface, KSZ8851_REG_CIDER) != KSZ8851_REV_A3_ID) 00092 return ERROR_WRONG_IDENTIFIER; 00093 00094 //Dump registers for debugging purpose 00095 ksz8851DumpReg(interface); 00096 00097 //Initialize driver specific variables 00098 context->frameId = 0; 00099 00100 //Allocate TX and RX buffers 00101 context->txBuffer = memPoolAlloc(ETH_MAX_FRAME_SIZE); 00102 context->rxBuffer = memPoolAlloc(ETH_MAX_FRAME_SIZE); 00103 00104 //Failed to allocate memory? 00105 if(context->txBuffer == NULL || context->rxBuffer == NULL) 00106 { 00107 //Clean up side effects 00108 memPoolFree(context->txBuffer); 00109 memPoolFree(context->rxBuffer); 00110 00111 //Report an error 00112 return ERROR_OUT_OF_MEMORY; 00113 } 00114 00115 //Initialize MAC address 00116 ksz8851WriteReg(interface, KSZ8851_REG_MARH, htons(interface->macAddr.w[0])); 00117 ksz8851WriteReg(interface, KSZ8851_REG_MARM, htons(interface->macAddr.w[1])); 00118 ksz8851WriteReg(interface, KSZ8851_REG_MARL, htons(interface->macAddr.w[2])); 00119 00120 //Packets shorter than 64 bytes are padded and the CRC is automatically generated 00121 ksz8851WriteReg(interface, KSZ8851_REG_TXCR, TXCR_TXFCE | TXCR_TXPE | TXCR_TXCE); 00122 //Automatically increment TX data pointer 00123 ksz8851WriteReg(interface, KSZ8851_REG_TXFDPR, TXFDPR_TXFPAI); 00124 00125 //Configure address filtering 00126 ksz8851WriteReg(interface, KSZ8851_REG_RXCR1, 00127 RXCR1_RXPAFMA | RXCR1_RXFCE | RXCR1_RXBE | RXCR1_RXME | RXCR1_RXUE); 00128 00129 //No checksum verification 00130 ksz8851WriteReg(interface, KSZ8851_REG_RXCR2, 00131 RXCR2_SRDBL2 | RXCR2_IUFFP | RXCR2_RXIUFCEZ); 00132 00133 //Enable automatic RXQ frame buffer dequeue 00134 ksz8851WriteReg(interface, KSZ8851_REG_RXQCR, RXQCR_RXFCTE | RXQCR_ADRFE); 00135 //Automatically increment RX data pointer 00136 ksz8851WriteReg(interface, KSZ8851_REG_RXFDPR, RXFDPR_RXFPAI); 00137 //Configure receive frame count threshold 00138 ksz8851WriteReg(interface, KSZ8851_REG_RXFCTR, 1); 00139 00140 //Force link in half-duplex if auto-negotiation failed 00141 ksz8851ClearBit(interface, KSZ8851_REG_P1CR, P1CR_FORCE_DUPLEX); 00142 //Restart auto-negotiation 00143 ksz8851SetBit(interface, KSZ8851_REG_P1CR, P1CR_RESTART_AN); 00144 00145 //Clear interrupt flags 00146 ksz8851SetBit(interface, KSZ8851_REG_ISR, ISR_LCIS | ISR_TXIS | 00147 ISR_RXIS | ISR_RXOIS | ISR_TXPSIS | ISR_RXPSIS | ISR_TXSAIS | 00148 ISR_RXWFDIS | ISR_RXMPDIS | ISR_LDIS | ISR_EDIS | ISR_SPIBEIS); 00149 00150 //Configure interrupts as desired 00151 ksz8851SetBit(interface, KSZ8851_REG_IER, IER_LCIE | IER_TXIE | IER_RXIE); 00152 00153 //Enable TX operation 00154 ksz8851SetBit(interface, KSZ8851_REG_TXCR, TXCR_TXE); 00155 //Enable RX operation 00156 ksz8851SetBit(interface, KSZ8851_REG_RXCR1, RXCR1_RXE); 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 KSZ8851 timer handler 00173 * @param[in] interface Underlying network interface 00174 **/ 00175 00176 void ksz8851Tick(NetInterface *interface) 00177 { 00178 } 00179 00180 00181 /** 00182 * @brief Enable interrupts 00183 * @param[in] interface Underlying network interface 00184 **/ 00185 00186 void ksz8851EnableIrq(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 ksz8851DisableIrq(NetInterface *interface) 00199 { 00200 //Disable interrupts 00201 interface->extIntDriver->disableIrq(); 00202 } 00203 00204 00205 /** 00206 * @brief KSZ8851 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 ksz8851IrqHandler(NetInterface *interface) 00212 { 00213 bool_t flag; 00214 uint16_t ier; 00215 uint16_t isr; 00216 00217 //This flag will be set if a higher priority task must be woken 00218 flag = FALSE; 00219 00220 //Save IER register value 00221 ier = ksz8851ReadReg(interface, KSZ8851_REG_IER); 00222 //Disable interrupts to release the interrupt line 00223 ksz8851WriteReg(interface, KSZ8851_REG_IER, 0); 00224 00225 //Read interrupt status register 00226 isr = ksz8851ReadReg(interface, KSZ8851_REG_ISR); 00227 00228 //Link status change? 00229 if(isr & ISR_LCIS) 00230 { 00231 //Disable LCIE interrupt 00232 ier &= ~IER_LCIE; 00233 00234 //Set event flag 00235 interface->nicEvent = TRUE; 00236 //Notify the TCP/IP stack of the event 00237 flag |= osSetEventFromIsr(&netEvent); 00238 } 00239 00240 //Packet transmission complete? 00241 if(isr & ISR_TXIS) 00242 { 00243 //Clear interrupt flag 00244 ksz8851WriteReg(interface, KSZ8851_REG_ISR, ISR_TXIS); 00245 00246 //Notify the TCP/IP stack that the transmitter is ready to send 00247 flag |= osSetEventFromIsr(&interface->nicTxEvent); 00248 } 00249 00250 //Packet received? 00251 if(isr & ISR_RXIS) 00252 { 00253 //Disable RXIE interrupt 00254 ier &= ~IER_RXIE; 00255 00256 //Set event flag 00257 interface->nicEvent = TRUE; 00258 //Notify the TCP/IP stack of the event 00259 flag |= osSetEventFromIsr(&netEvent); 00260 } 00261 00262 //Re-enable interrupts once the interrupt has been serviced 00263 ksz8851WriteReg(interface, KSZ8851_REG_IER, ier); 00264 00265 //A higher priority task must be woken? 00266 return flag; 00267 } 00268 00269 00270 /** 00271 * @brief KSZ8851 event handler 00272 * @param[in] interface Underlying network interface 00273 **/ 00274 00275 void ksz8851EventHandler(NetInterface *interface) 00276 { 00277 uint16_t status; 00278 uint_t frameCount; 00279 00280 //Read interrupt status register 00281 status = ksz8851ReadReg(interface, KSZ8851_REG_ISR); 00282 00283 //Check whether the link status has changed? 00284 if(status & ISR_LCIS) 00285 { 00286 //Clear interrupt flag 00287 ksz8851WriteReg(interface, KSZ8851_REG_ISR, ISR_LCIS); 00288 //Read PHY status register 00289 status = ksz8851ReadReg(interface, KSZ8851_REG_P1SR); 00290 00291 //Check link state 00292 if(status & P1SR_LINK_GOOD) 00293 { 00294 //Get current speed 00295 if(status & P1SR_OPERATION_SPEED) 00296 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00297 else 00298 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00299 00300 //Determine the new duplex mode 00301 if(status & P1SR_OPERATION_DUPLEX) 00302 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00303 else 00304 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00305 00306 //Link is up 00307 interface->linkState = TRUE; 00308 } 00309 else 00310 { 00311 //Link is down 00312 interface->linkState = FALSE; 00313 } 00314 00315 //Process link state change event 00316 nicNotifyLinkChange(interface); 00317 } 00318 00319 //Check whether a packet has been received? 00320 if(status & ISR_RXIS) 00321 { 00322 //Clear interrupt flag 00323 ksz8851WriteReg(interface, KSZ8851_REG_ISR, ISR_RXIS); 00324 //Get the total number of frames that are pending in the buffer 00325 frameCount = MSB(ksz8851ReadReg(interface, KSZ8851_REG_RXFCTR)); 00326 00327 //Process all pending packets 00328 while(frameCount > 0) 00329 { 00330 //Read incoming packet 00331 ksz8851ReceivePacket(interface); 00332 //Decrement frame counter 00333 frameCount--; 00334 } 00335 } 00336 00337 //Re-enable LCIE and RXIE interrupts 00338 ksz8851SetBit(interface, KSZ8851_REG_IER, IER_LCIE | IER_RXIE); 00339 } 00340 00341 00342 /** 00343 * @brief Send a packet 00344 * @param[in] interface Underlying network interface 00345 * @param[in] buffer Multi-part buffer containing the data to send 00346 * @param[in] offset Offset to the first data byte 00347 * @return Error code 00348 **/ 00349 00350 error_t ksz8851SendPacket(NetInterface *interface, 00351 const NetBuffer *buffer, size_t offset) 00352 { 00353 size_t n; 00354 size_t length; 00355 Ksz8851TxHeader header; 00356 Ksz8851Context *context; 00357 00358 //Point to the driver context 00359 context = (Ksz8851Context *) interface->nicContext; 00360 00361 //Retrieve the length of the packet 00362 length = netBufferGetLength(buffer) - offset; 00363 00364 //Check the frame length 00365 if(length > ETH_MAX_FRAME_SIZE) 00366 { 00367 //The transmitter can accept another packet 00368 osSetEvent(&interface->nicTxEvent); 00369 //Report an error 00370 return ERROR_INVALID_LENGTH; 00371 } 00372 00373 //Get the amount of free memory available in the TX FIFO 00374 n = ksz8851ReadReg(interface, KSZ8851_REG_TXMIR) & TXMIR_TXMA_MASK; 00375 00376 //Make sure enough memory is available 00377 if((length + 8) > n) 00378 return ERROR_FAILURE; 00379 00380 //Copy user data 00381 netBufferRead(context->txBuffer, buffer, offset, length); 00382 00383 //Format control word 00384 header.controlWord = TX_CTRL_TXIC | (context->frameId++ & TX_CTRL_TXFID); 00385 //Total number of bytes to be transmitted 00386 header.byteCount = length; 00387 00388 //Enable TXQ write access 00389 ksz8851SetBit(interface, KSZ8851_REG_RXQCR, RXQCR_SDA); 00390 //Write TX packet header 00391 ksz8851WriteFifo(interface, (uint8_t *) &header, sizeof(Ksz8851TxHeader)); 00392 //Write data 00393 ksz8851WriteFifo(interface, context->txBuffer, length); 00394 //End TXQ write access 00395 ksz8851ClearBit(interface, KSZ8851_REG_RXQCR, RXQCR_SDA); 00396 00397 //Start transmission 00398 ksz8851SetBit(interface, KSZ8851_REG_TXQCR, TXQCR_METFE); 00399 00400 //Successful processing 00401 return NO_ERROR; 00402 } 00403 00404 00405 /** 00406 * @brief Receive a packet 00407 * @param[in] interface Underlying network interface 00408 * @return Error code 00409 **/ 00410 00411 error_t ksz8851ReceivePacket(NetInterface *interface) 00412 { 00413 size_t n; 00414 uint16_t status; 00415 Ksz8851Context *context; 00416 00417 //Point to the driver context 00418 context = (Ksz8851Context *) interface->nicContext; 00419 00420 //Read received frame status from RXFHSR 00421 status = ksz8851ReadReg(interface, KSZ8851_REG_RXFHSR); 00422 00423 //Make sure the frame is valid 00424 if(status & RXFHSR_RXFV) 00425 { 00426 //Check error flags 00427 if(!(status & (RXFHSR_RXMR | RXFHSR_RXFTL | RXFHSR_RXRF | RXFHSR_RXCE))) 00428 { 00429 //Read received frame byte size from RXFHBCR 00430 n = ksz8851ReadReg(interface, KSZ8851_REG_RXFHBCR) & RXFHBCR_RXBC_MASK; 00431 00432 //Ensure the frame size is acceptable 00433 if(n > 0 && n <= ETH_MAX_FRAME_SIZE) 00434 { 00435 //Reset QMU RXQ frame pointer to zero 00436 ksz8851WriteReg(interface, KSZ8851_REG_RXFDPR, RXFDPR_RXFPAI); 00437 //Enable RXQ read access 00438 ksz8851SetBit(interface, KSZ8851_REG_RXQCR, RXQCR_SDA); 00439 //Read data 00440 ksz8851ReadFifo(interface, context->rxBuffer, n); 00441 //End RXQ read access 00442 ksz8851ClearBit(interface, KSZ8851_REG_RXQCR, RXQCR_SDA); 00443 00444 //Pass the packet to the upper layer 00445 nicProcessPacket(interface, context->rxBuffer, n); 00446 //Valid packet received 00447 return NO_ERROR; 00448 } 00449 } 00450 } 00451 00452 //Release the current error frame from RXQ 00453 ksz8851SetBit(interface, KSZ8851_REG_RXQCR, RXQCR_RRXEF); 00454 //Report an error 00455 return ERROR_INVALID_PACKET; 00456 } 00457 00458 00459 /** 00460 * @brief Configure multicast MAC address filtering 00461 * @param[in] interface Underlying network interface 00462 * @return Error code 00463 **/ 00464 00465 error_t ksz8851SetMulticastFilter(NetInterface *interface) 00466 { 00467 uint_t i; 00468 uint_t k; 00469 uint32_t crc; 00470 uint16_t hashTable[4]; 00471 MacFilterEntry *entry; 00472 00473 //Debug message 00474 TRACE_DEBUG("Updating KSZ8851 hash table...\r\n"); 00475 00476 //Clear hash table 00477 memset(hashTable, 0, sizeof(hashTable)); 00478 00479 //The MAC filter table contains the multicast MAC addresses 00480 //to accept when receiving an Ethernet frame 00481 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00482 { 00483 //Point to the current entry 00484 entry = &interface->macMulticastFilter[i]; 00485 00486 //Valid entry? 00487 if(entry->refCount > 0) 00488 { 00489 //Compute CRC over the current MAC address 00490 crc = ksz8851CalcCrc(&entry->addr, sizeof(MacAddr)); 00491 //Calculate the corresponding index in the table 00492 k = (crc >> 26) & 0x3F; 00493 //Update hash table contents 00494 hashTable[k / 16] |= (1 << (k % 16)); 00495 } 00496 } 00497 00498 //Write the hash table to the KSZ8851 controller 00499 ksz8851WriteReg(interface, KSZ8851_REG_MAHTR0, hashTable[0]); 00500 ksz8851WriteReg(interface, KSZ8851_REG_MAHTR1, hashTable[1]); 00501 ksz8851WriteReg(interface, KSZ8851_REG_MAHTR2, hashTable[2]); 00502 ksz8851WriteReg(interface, KSZ8851_REG_MAHTR3, hashTable[3]); 00503 00504 //Debug message 00505 TRACE_DEBUG(" MAHTR0 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_MAHTR0)); 00506 TRACE_DEBUG(" MAHTR1 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_MAHTR1)); 00507 TRACE_DEBUG(" MAHTR2 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_MAHTR2)); 00508 TRACE_DEBUG(" MAHTR3 = %04" PRIX16 "\r\n", ksz8851ReadReg(interface, KSZ8851_REG_MAHTR3)); 00509 00510 //Successful processing 00511 return NO_ERROR; 00512 } 00513 00514 00515 /** 00516 * @brief Write KSZ8851 register 00517 * @param[in] interface Underlying network interface 00518 * @param[in] address Register address 00519 * @param[in] data Register value 00520 **/ 00521 00522 void ksz8851WriteReg(NetInterface *interface, uint8_t address, uint16_t data) 00523 { 00524 #if (KSZ8851_SPI_SUPPORT == ENABLED) 00525 uint8_t command; 00526 00527 //Form the write command 00528 if(address & 0x02) 00529 command = KSZ8851_CMD_WR_REG | KSZ8851_CMD_B3 | KSZ8851_CMD_B2; 00530 else 00531 command = KSZ8851_CMD_WR_REG | KSZ8851_CMD_B1 | KSZ8851_CMD_B0; 00532 00533 //Pull the CS pin low 00534 interface->spiDriver->assertCs(); 00535 00536 //Command phase 00537 interface->spiDriver->transfer(command | (address >> 6)); 00538 interface->spiDriver->transfer(address << 2); 00539 00540 //Data phase 00541 interface->spiDriver->transfer(LSB(data)); 00542 interface->spiDriver->transfer(MSB(data)); 00543 00544 //Terminate the operation by raising the CS pin 00545 interface->spiDriver->deassertCs(); 00546 #else 00547 //Set register address 00548 if(address & 0x02) 00549 KSZ8851_CMD_REG = KSZ8851_CMD_B3 | KSZ8851_CMD_B2 | address; 00550 else 00551 KSZ8851_CMD_REG = KSZ8851_CMD_B1 | KSZ8851_CMD_B0 | address; 00552 00553 //Write register value 00554 KSZ8851_DATA_REG = data; 00555 #endif 00556 } 00557 00558 00559 /** 00560 * @brief Read KSZ8851 register 00561 * @param[in] interface Underlying network interface 00562 * @param[in] address Register address 00563 * @return Register value 00564 **/ 00565 00566 uint16_t ksz8851ReadReg(NetInterface *interface, uint8_t address) 00567 { 00568 #if (KSZ8851_SPI_SUPPORT == ENABLED) 00569 uint8_t command; 00570 uint16_t data; 00571 00572 //Form the read command 00573 if(address & 0x02) 00574 command = KSZ8851_CMD_RD_REG | KSZ8851_CMD_B3 | KSZ8851_CMD_B2; 00575 else 00576 command = KSZ8851_CMD_RD_REG | KSZ8851_CMD_B1 | KSZ8851_CMD_B0; 00577 00578 //Pull the CS pin low 00579 interface->spiDriver->assertCs(); 00580 00581 //Command phase 00582 interface->spiDriver->transfer(command | (address >> 6)); 00583 interface->spiDriver->transfer(address << 2); 00584 00585 //Data phase (lower 8 bits) 00586 data = interface->spiDriver->transfer(0x00); 00587 //Data phase (upper 8 bits) 00588 data |= interface->spiDriver->transfer(0x00) << 8; 00589 00590 //Terminate the operation by raising the CS pin 00591 interface->spiDriver->deassertCs(); 00592 00593 //Return register value 00594 return data; 00595 #else 00596 //Set register address 00597 if(address & 0x02) 00598 KSZ8851_CMD_REG = KSZ8851_CMD_B3 | KSZ8851_CMD_B2 | address; 00599 else 00600 KSZ8851_CMD_REG = KSZ8851_CMD_B1 | KSZ8851_CMD_B0 | address; 00601 00602 //Return register value 00603 return KSZ8851_DATA_REG; 00604 #endif 00605 } 00606 00607 00608 /** 00609 * @brief Write TX FIFO 00610 * @param[in] interface Underlying network interface 00611 * @param[in] data Pointer to the data being written 00612 * @param[in] length Number of data to write 00613 **/ 00614 00615 void ksz8851WriteFifo(NetInterface *interface, const uint8_t *data, size_t length) 00616 { 00617 #if (KSZ8851_SPI_SUPPORT == ENABLED) 00618 uint_t i; 00619 00620 //Pull the CS pin low 00621 interface->spiDriver->assertCs(); 00622 00623 //Command phase 00624 interface->spiDriver->transfer(KSZ8851_CMD_WR_FIFO); 00625 00626 //Data phase 00627 for(i = 0; i < length; i++) 00628 interface->spiDriver->transfer(data[i]); 00629 00630 //Maintain alignment to 4-byte boundaries 00631 for(; i % 4; i++) 00632 interface->spiDriver->transfer(0x00); 00633 00634 //Terminate the operation by raising the CS pin 00635 interface->spiDriver->deassertCs(); 00636 #else 00637 uint_t i; 00638 00639 //Data phase 00640 for(i = 0; i < length; i+=2) 00641 KSZ8851_DATA_REG = data[i] | data[i+1]<<8; 00642 00643 //Maintain alignment to 4-byte boundaries 00644 for(; i % 4; i+=2) 00645 KSZ8851_DATA_REG = 0x0000; 00646 #endif 00647 } 00648 00649 00650 /** 00651 * @brief Read RX FIFO 00652 * @param[in] interface Underlying network interface 00653 * @param[in] data Buffer where to store the incoming data 00654 * @param[in] length Number of data to read 00655 **/ 00656 00657 void ksz8851ReadFifo(NetInterface *interface, uint8_t *data, size_t length) 00658 { 00659 #if (KSZ8851_SPI_SUPPORT == ENABLED) 00660 uint_t i; 00661 00662 //Pull the CS pin low 00663 interface->spiDriver->assertCs(); 00664 00665 //Command phase 00666 interface->spiDriver->transfer(KSZ8851_CMD_RD_FIFO); 00667 00668 //The first 4 bytes are dummy data and must be discarded 00669 for(i = 0; i < 4; i++) 00670 interface->spiDriver->transfer(0x00); 00671 00672 //Ignore RX packet header 00673 for(i = 0; i < 4; i++) 00674 interface->spiDriver->transfer(0x00); 00675 00676 //Data phase 00677 for(i = 0; i < length; i++) 00678 data[i] = interface->spiDriver->transfer(0x00); 00679 00680 //Maintain alignment to 4-byte boundaries 00681 for(; i % 4; i++) 00682 interface->spiDriver->transfer(0x00); 00683 00684 //Terminate the operation by raising the CS pin 00685 interface->spiDriver->deassertCs(); 00686 #else 00687 uint_t i; 00688 uint16_t temp; 00689 00690 //The first 2 bytes are dummy data and must be discarded 00691 temp = KSZ8851_DATA_REG; 00692 00693 //Ignore RX packet header 00694 temp = KSZ8851_DATA_REG; 00695 temp = KSZ8851_DATA_REG; 00696 00697 //Data phase 00698 for(i = 0; i < length; i+=2) 00699 { 00700 temp = KSZ8851_DATA_REG; 00701 data [i] = temp & 0xFF; 00702 data [i+1] = (temp>>8) & 0xFF; 00703 } 00704 00705 //Maintain alignment to 4-byte boundaries 00706 for(; i % 4; i+=2) 00707 temp = KSZ8851_DATA_REG; 00708 #endif 00709 } 00710 00711 00712 /** 00713 * @brief Set bit field 00714 * @param[in] interface Underlying network interface 00715 * @param[in] address Register address 00716 * @param[in] mask Bits to set in the target register 00717 **/ 00718 00719 void ksz8851SetBit(NetInterface *interface, uint8_t address, uint16_t mask) 00720 { 00721 uint16_t value; 00722 00723 //Read current register value 00724 value = ksz8851ReadReg(interface, address); 00725 //Set specified bits 00726 ksz8851WriteReg(interface, address, value | mask); 00727 } 00728 00729 00730 /** 00731 * @brief Clear bit field 00732 * @param[in] interface Underlying network interface 00733 * @param[in] address Register address 00734 * @param[in] mask Bits to clear in the target register 00735 **/ 00736 00737 void ksz8851ClearBit(NetInterface *interface, uint8_t address, uint16_t mask) 00738 { 00739 uint16_t value; 00740 00741 //Read current register value 00742 value = ksz8851ReadReg(interface, address); 00743 //Clear specified bits 00744 ksz8851WriteReg(interface, address, value & ~mask); 00745 } 00746 00747 00748 /** 00749 * @brief CRC calculation 00750 * @param[in] data Pointer to the data over which to calculate the CRC 00751 * @param[in] length Number of bytes to process 00752 * @return Resulting CRC value 00753 **/ 00754 00755 uint32_t ksz8851CalcCrc(const void *data, size_t length) 00756 { 00757 uint_t i; 00758 uint_t j; 00759 00760 //Point to the data over which to calculate the CRC 00761 const uint8_t *p = (uint8_t *) data; 00762 //CRC preset value 00763 uint32_t crc = 0xFFFFFFFF; 00764 00765 //Loop through data 00766 for(i = 0; i < length; i++) 00767 { 00768 //The message is processed bit by bit 00769 for(j = 0; j < 8; j++) 00770 { 00771 //Update CRC value 00772 if(((crc >> 31) ^ (p[i] >> j)) & 0x01) 00773 crc = (crc << 1) ^ 0x04C11DB7; 00774 else 00775 crc = crc << 1; 00776 } 00777 } 00778 00779 //Return CRC value 00780 return crc; 00781 } 00782 00783 00784 /** 00785 * @brief Dump registers for debugging purpose 00786 * @param[in] interface Underlying network interface 00787 **/ 00788 00789 void ksz8851DumpReg(NetInterface *interface) 00790 { 00791 #if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG) 00792 uint_t i; 00793 uint_t j; 00794 uint_t address; 00795 00796 //Loop through register addresses 00797 for(i = 0; i < 256; i += 16) 00798 { 00799 //Display register address 00800 TRACE_DEBUG("%02" PRIu8 ": ", i); 00801 00802 //Display 8 registers at a time 00803 for(j = 0; j < 16; j += 2) 00804 { 00805 //Format register address 00806 address = i + j; 00807 //Display register contents 00808 TRACE_DEBUG("0x%04" PRIX16 " ", ksz8851ReadReg(interface, address)); 00809 } 00810 00811 //Jump to the following line 00812 TRACE_DEBUG("\r\n"); 00813 } 00814 00815 //Terminate with a line feed 00816 TRACE_DEBUG("\r\n"); 00817 #endif 00818 } 00819
Generated on Tue Jul 12 2022 17:10:14 by
