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.
ksz8851.c
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
1.7.2