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.
dm9000.c
00001 /** 00002 * @file dm9000.c 00003 * @brief DM9000A/B 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 "core/ethernet.h" 00035 #include "drivers/dm9000.h" 00036 #include "debug.h" 00037 00038 00039 /** 00040 * @brief DM9000 driver 00041 **/ 00042 00043 const NicDriver dm9000Driver = 00044 { 00045 NIC_TYPE_ETHERNET, 00046 ETH_MTU, 00047 dm9000Init, 00048 dm9000Tick, 00049 dm9000EnableIrq, 00050 dm9000DisableIrq, 00051 dm9000EventHandler, 00052 dm9000SendPacket, 00053 dm9000SetMulticastFilter, 00054 NULL, 00055 NULL, 00056 NULL, 00057 TRUE, 00058 TRUE, 00059 TRUE, 00060 FALSE 00061 }; 00062 00063 00064 /** 00065 * @brief DM9000 controller initialization 00066 * @param[in] interface Underlying network interface 00067 * @return Error code 00068 **/ 00069 00070 error_t dm9000Init(NetInterface *interface) 00071 { 00072 uint_t i; 00073 uint16_t vendorId; 00074 uint16_t productId; 00075 uint8_t chipRevision; 00076 Dm9000Context *context; 00077 00078 //Debug message 00079 TRACE_INFO("Initializing DM9000 Ethernet controller...\r\n"); 00080 00081 //Initialize external interrupt line 00082 interface->extIntDriver->init(); 00083 00084 //Point to the driver context 00085 context = (Dm9000Context *) interface->nicContext; 00086 00087 //Initialize driver specific variables 00088 context->queuedPackets = 0; 00089 00090 //Allocate TX and RX buffers 00091 context->txBuffer = memPoolAlloc(ETH_MAX_FRAME_SIZE); 00092 context->rxBuffer = memPoolAlloc(ETH_MAX_FRAME_SIZE); 00093 00094 //Failed to allocate memory? 00095 if(context->txBuffer == NULL || context->rxBuffer == NULL) 00096 { 00097 //Clean up side effects 00098 memPoolFree(context->txBuffer); 00099 memPoolFree(context->rxBuffer); 00100 00101 //Report an error 00102 return ERROR_OUT_OF_MEMORY; 00103 } 00104 00105 //Retrieve vendorID, product ID and chip revision 00106 vendorId = (dm9000ReadReg(DM9000_REG_VIDH) << 8) | dm9000ReadReg(DM9000_REG_VIDL); 00107 productId = (dm9000ReadReg(DM9000_REG_PIDH) << 8) | dm9000ReadReg(DM9000_REG_PIDL); 00108 chipRevision = dm9000ReadReg(DM9000_REG_CHIPR); 00109 00110 //Check vendor ID and product ID 00111 if(vendorId != DM9000_VID || productId != DM9000_PID) 00112 return ERROR_WRONG_IDENTIFIER; 00113 //Check chip revision 00114 if(chipRevision != DM9000A_CHIP_REV && chipRevision != DM9000B_CHIP_REV) 00115 return ERROR_WRONG_IDENTIFIER; 00116 00117 //Power up the internal PHY by clearing PHYPD 00118 dm9000WriteReg(DM9000_REG_GPR, 0x00); 00119 //Wait for the PHY to be ready 00120 sleep(10); 00121 00122 //Software reset 00123 dm9000WriteReg(DM9000_REG_NCR, NCR_RST); 00124 //Wait for the reset to complete 00125 while(dm9000ReadReg(DM9000_REG_NCR) & NCR_RST); 00126 00127 //PHY software reset 00128 dm9000WritePhyReg(DM9000_PHY_REG_BMCR, BMCR_RST); 00129 //Wait for the PHY reset to complete 00130 while(dm9000ReadPhyReg(DM9000_PHY_REG_BMCR) & BMCR_RST); 00131 00132 //Debug message 00133 TRACE_INFO(" VID = 0x%04" PRIX16 "\r\n", vendorId); 00134 TRACE_INFO(" PID = 0x%04" PRIX16 "\r\n", productId); 00135 TRACE_INFO(" CHIPR = 0x%02" PRIX8 "\r\n", chipRevision); 00136 TRACE_INFO(" PHYIDR1 = 0x%04" PRIX16 "\r\n", dm9000ReadPhyReg(DM9000_PHY_REG_PHYIDR1)); 00137 TRACE_INFO(" PHYIDR2 = 0x%04" PRIX16 "\r\n", dm9000ReadPhyReg(DM9000_PHY_REG_PHYIDR2)); 00138 00139 //Enable loopback mode? 00140 #if (DM9000_LOOPBACK_MODE == ENABLED) 00141 dm9000WriteReg(DM9000_REG_NCR, DM9000_LBK_PHY); 00142 dm9000WritePhyReg(DM9000_PHY_REG_BMCR, BMCR_LOOPBACK | BMCR_SPEED_SEL | BMCR_AN_EN | BMCR_DUPLEX_MODE); 00143 #endif 00144 00145 //Set host MAC address 00146 for(i = 0; i < 6; i++) 00147 dm9000WriteReg(DM9000_REG_PAR0 + i, interface->macAddr.b[i]); 00148 00149 //Initialize hash table 00150 for(i = 0; i < 8; i++) 00151 dm9000WriteReg(DM9000_REG_MAR0 + i, 0x00); 00152 00153 //Always accept broadcast packets 00154 dm9000WriteReg(DM9000_REG_MAR7, 0x80); 00155 00156 //Enable the Pointer Auto Return function 00157 dm9000WriteReg(DM9000_REG_IMR, IMR_PAR); 00158 //Clear NSR status bits 00159 dm9000WriteReg(DM9000_REG_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); 00160 //Clear interrupt flags 00161 dm9000WriteReg(DM9000_REG_ISR, ISR_LNKCHG | ISR_UDRUN | ISR_ROO | ISR_ROS | ISR_PT | ISR_PR); 00162 //Enable interrupts 00163 dm9000WriteReg(DM9000_REG_IMR, IMR_PAR | IMR_LNKCHGI | IMR_PTI | IMR_PRI); 00164 //Enable the receiver by setting RXEN 00165 dm9000WriteReg(DM9000_REG_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); 00166 00167 //Accept any packets from the upper layer 00168 osSetEvent(&interface->nicTxEvent); 00169 00170 //Force the TCP/IP stack to poll the link state at startup 00171 interface->nicEvent = TRUE; 00172 //Notify the TCP/IP stack of the event 00173 osSetEvent(&netEvent); 00174 00175 //Successful initialization 00176 return NO_ERROR; 00177 } 00178 00179 00180 /** 00181 * @brief DM9000 timer handler 00182 * @param[in] interface Underlying network interface 00183 **/ 00184 00185 void dm9000Tick(NetInterface *interface) 00186 { 00187 } 00188 00189 00190 /** 00191 * @brief Enable interrupts 00192 * @param[in] interface Underlying network interface 00193 **/ 00194 00195 void dm9000EnableIrq(NetInterface *interface) 00196 { 00197 //Enable interrupts 00198 interface->extIntDriver->enableIrq(); 00199 } 00200 00201 00202 /** 00203 * @brief Disable interrupts 00204 * @param[in] interface Underlying network interface 00205 **/ 00206 00207 void dm9000DisableIrq(NetInterface *interface) 00208 { 00209 //Disable interrupts 00210 interface->extIntDriver->disableIrq(); 00211 } 00212 00213 00214 /** 00215 * @brief DM9000 interrupt service routine 00216 * @param[in] interface Underlying network interface 00217 * @return TRUE if a higher priority task must be woken. Else FALSE is returned 00218 **/ 00219 00220 bool_t dm9000IrqHandler(NetInterface *interface) 00221 { 00222 bool_t flag; 00223 uint8_t status; 00224 uint8_t mask; 00225 Dm9000Context *context; 00226 00227 //This flag will be set if a higher priority task must be woken 00228 flag = FALSE; 00229 00230 //Point to the driver context 00231 context = (Dm9000Context *) interface->nicContext; 00232 00233 //Read interrupt status register 00234 status = dm9000ReadReg(DM9000_REG_ISR); 00235 00236 //Link status change? 00237 if(status & ISR_LNKCHG) 00238 { 00239 //Read interrupt mask register 00240 mask = dm9000ReadReg(DM9000_REG_IMR); 00241 //Disable LNKCHGI interrupt 00242 dm9000WriteReg(DM9000_REG_IMR, mask & ~IMR_LNKCHGI); 00243 00244 //Set event flag 00245 interface->nicEvent = TRUE; 00246 //Notify the TCP/IP stack of the event 00247 flag |= osSetEventFromIsr(&netEvent); 00248 } 00249 00250 //Packet transmission complete? 00251 if(status & ISR_PT) 00252 { 00253 //Check TX complete status bits 00254 if(dm9000ReadReg(DM9000_REG_NSR) & (NSR_TX2END | NSR_TX1END)) 00255 { 00256 //The transmission of the current packet is complete 00257 if(context->queuedPackets > 0) 00258 context->queuedPackets--; 00259 00260 //Notify the TCP/IP stack that the transmitter is ready to send 00261 flag |= osSetEventFromIsr(&interface->nicTxEvent); 00262 } 00263 00264 //Clear interrupt flag 00265 dm9000WriteReg(DM9000_REG_ISR, ISR_PT); 00266 } 00267 00268 //Packet received? 00269 if(status & ISR_PR) 00270 { 00271 //Read interrupt mask register 00272 mask = dm9000ReadReg(DM9000_REG_IMR); 00273 //Disable PRI interrupt 00274 dm9000WriteReg(DM9000_REG_IMR, mask & ~IMR_PRI); 00275 00276 //Set event flag 00277 interface->nicEvent = TRUE; 00278 //Notify the TCP/IP stack of the event 00279 flag |= osSetEventFromIsr(&netEvent); 00280 } 00281 00282 //A higher priority task must be woken? 00283 return flag; 00284 } 00285 00286 00287 /** 00288 * @brief DM9000 event handler 00289 * @param[in] interface Underlying network interface 00290 **/ 00291 00292 void dm9000EventHandler(NetInterface *interface) 00293 { 00294 error_t error; 00295 uint8_t status; 00296 00297 //Read interrupt status register 00298 status = dm9000ReadReg(DM9000_REG_ISR); 00299 00300 //Check whether the link status has changed? 00301 if(status & ISR_LNKCHG) 00302 { 00303 //Clear interrupt flag 00304 dm9000WriteReg(DM9000_REG_ISR, ISR_LNKCHG); 00305 //Read network status register 00306 status = dm9000ReadReg(DM9000_REG_NSR); 00307 00308 //Check link state 00309 if(status & NSR_LINKST) 00310 { 00311 //Get current speed 00312 if(status & NSR_SPEED) 00313 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00314 else 00315 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00316 00317 //Read network control register 00318 status = dm9000ReadReg(DM9000_REG_NCR); 00319 00320 //Determine the new duplex mode 00321 if(status & NCR_FDX) 00322 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00323 else 00324 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00325 00326 //Link is up 00327 interface->linkState = TRUE; 00328 } 00329 else 00330 { 00331 //Link is down 00332 interface->linkState = FALSE; 00333 } 00334 00335 //Process link state change event 00336 nicNotifyLinkChange(interface); 00337 } 00338 00339 //Check whether a packet has been received? 00340 if(status & ISR_PR) 00341 { 00342 //Clear interrupt flag 00343 dm9000WriteReg(DM9000_REG_ISR, ISR_PR); 00344 00345 //Process all pending packets 00346 do 00347 { 00348 //Read incoming packet 00349 error = dm9000ReceivePacket(interface); 00350 00351 //No more data in the receive buffer? 00352 } while(error != ERROR_BUFFER_EMPTY); 00353 } 00354 00355 //Re-enable LNKCHGI and PRI interrupts 00356 dm9000WriteReg(DM9000_REG_IMR, IMR_PAR | IMR_LNKCHGI | IMR_PTI | IMR_PRI); 00357 } 00358 00359 00360 /** 00361 * @brief Send a packet to DM9000 00362 * @param[in] interface Underlying network interface 00363 * @param[in] buffer Multi-part buffer containing the data to send 00364 * @param[in] offset Offset to the first data byte 00365 * @return Error code 00366 **/ 00367 00368 error_t dm9000SendPacket(NetInterface *interface, 00369 const NetBuffer *buffer, size_t offset) 00370 { 00371 size_t i; 00372 size_t length; 00373 uint16_t *p; 00374 Dm9000Context *context; 00375 00376 //Point to the driver context 00377 context = (Dm9000Context *) interface->nicContext; 00378 00379 //Retrieve the length of the packet 00380 length = netBufferGetLength(buffer) - offset; 00381 00382 //Check the frame length 00383 if(length > ETH_MAX_FRAME_SIZE) 00384 { 00385 //The transmitter can accept another packet 00386 osSetEvent(&interface->nicTxEvent); 00387 //Report an error 00388 return ERROR_INVALID_LENGTH; 00389 } 00390 00391 //Copy user data 00392 netBufferRead(context->txBuffer, buffer, offset, length); 00393 00394 //A dummy write is required before accessing FIFO 00395 dm9000WriteReg(DM9000_REG_MWCMDX, 0); 00396 //Select MWCMD register 00397 DM9000_INDEX_REG = DM9000_REG_MWCMD; 00398 00399 //Point to the beginning of the buffer 00400 p = (uint16_t *) context->txBuffer; 00401 00402 //Write data to the FIFO using 16-bit mode 00403 for(i = length; i > 1; i -= 2) 00404 DM9000_DATA_REG = *(p++); 00405 00406 //Odd number of bytes? 00407 if(i > 0) 00408 DM9000_DATA_REG = *((uint8_t *) p); 00409 00410 //Write the number of bytes to send 00411 dm9000WriteReg(DM9000_REG_TXPLL, LSB(length)); 00412 dm9000WriteReg(DM9000_REG_TXPLH, MSB(length)); 00413 00414 //Clear interrupt flag 00415 dm9000WriteReg(DM9000_REG_ISR, ISR_PT); 00416 //Start data transfer 00417 dm9000WriteReg(DM9000_REG_TCR, TCR_TXREQ); 00418 00419 //The packet was successfully written to FIFO 00420 context->queuedPackets++; 00421 00422 //Successful processing 00423 return NO_ERROR; 00424 } 00425 00426 00427 /** 00428 * @brief Receive a packet 00429 * @param[in] interface Underlying network interface 00430 * @return Error code 00431 **/ 00432 00433 error_t dm9000ReceivePacket(NetInterface *interface) 00434 { 00435 error_t error; 00436 size_t i; 00437 size_t n; 00438 size_t length; 00439 volatile uint8_t status; 00440 volatile uint16_t data; 00441 Dm9000Context *context; 00442 00443 //Point to the driver context 00444 context = (Dm9000Context *) interface->nicContext; 00445 00446 //A dummy read is required before accessing the 4-byte header 00447 data = dm9000ReadReg(DM9000_REG_MRCMDX); 00448 00449 //Select MRCMDX1 register 00450 DM9000_INDEX_REG = DM9000_REG_MRCMDX1; 00451 //Read the first byte of the header 00452 status = LSB(DM9000_DATA_REG); 00453 00454 //The first byte indicates if a packet has been received 00455 if(status == 0x01) 00456 { 00457 //Select MRCMD register 00458 DM9000_INDEX_REG = DM9000_REG_MRCMD; 00459 //The second byte is the RX status byte 00460 status = MSB(DM9000_DATA_REG); 00461 00462 //Retrieve packet length 00463 length = DM9000_DATA_REG; 00464 //Limit the number of data to read 00465 n = MIN(length, ETH_MAX_FRAME_SIZE); 00466 00467 //Point to the beginning of the buffer 00468 i = 0; 00469 00470 //Make sure no error occurred 00471 if(!(status & (RSR_LCS | RSR_RWTO | RSR_PLE | RSR_AE | RSR_CE | RSR_FOE))) 00472 { 00473 //Read data from FIFO using 16-bit mode 00474 while((i + 1) < n) 00475 { 00476 data = DM9000_DATA_REG; 00477 context->rxBuffer[i++] = LSB(data); 00478 context->rxBuffer[i++] = MSB(data); 00479 } 00480 00481 //Odd number of bytes to read? 00482 if((i + 1) == n) 00483 { 00484 data = DM9000_DATA_REG; 00485 context->rxBuffer[i] = LSB(data); 00486 i += 2; 00487 } 00488 00489 //Valid packet received 00490 error = NO_ERROR; 00491 } 00492 else 00493 { 00494 //The received packet contains an error 00495 error = ERROR_INVALID_PACKET; 00496 } 00497 00498 //Flush remaining bytes 00499 while(i < length) 00500 { 00501 data = DM9000_DATA_REG; 00502 i += 2; 00503 } 00504 } 00505 else 00506 { 00507 //No more data in the receive buffer 00508 error = ERROR_BUFFER_EMPTY; 00509 } 00510 00511 //Check whether a valid packet has been received 00512 if(!error) 00513 { 00514 //Pass the packet to the upper layer 00515 nicProcessPacket(interface, context->rxBuffer, n); 00516 } 00517 00518 //Return status code 00519 return error; 00520 } 00521 00522 00523 /** 00524 * @brief Configure multicast MAC address filtering 00525 * @param[in] interface Underlying network interface 00526 * @return Error code 00527 **/ 00528 00529 error_t dm9000SetMulticastFilter(NetInterface *interface) 00530 { 00531 uint_t i; 00532 uint_t k; 00533 uint32_t crc; 00534 uint8_t hashTable[8]; 00535 MacFilterEntry *entry; 00536 00537 //Debug message 00538 TRACE_DEBUG("Updating DM9000 hash table...\r\n"); 00539 00540 //Clear hash table 00541 memset(hashTable, 0, sizeof(hashTable)); 00542 //Always accept broadcast packets regardless of the MAC filter table 00543 hashTable[7] = 0x80; 00544 00545 //The MAC filter table contains the multicast MAC addresses 00546 //to accept when receiving an Ethernet frame 00547 for(i = 0; i < MAC_MULTICAST_FILTER_SIZE; i++) 00548 { 00549 //Point to the current entry 00550 entry = &interface->macMulticastFilter[i]; 00551 00552 //Valid entry? 00553 if(entry->refCount > 0) 00554 { 00555 //Compute CRC over the current MAC address 00556 crc = dm9000CalcCrc(&entry->addr, sizeof(MacAddr)); 00557 //Calculate the corresponding index in the table 00558 k = crc & 0x3F; 00559 //Update hash table contents 00560 hashTable[k / 8] |= (1 << (k % 8)); 00561 } 00562 } 00563 00564 //Write the hash table to the DM9000 controller 00565 for(i = 0; i < 8; i++) 00566 dm9000WriteReg(DM9000_REG_MAR0 + i, hashTable[i]); 00567 00568 //Debug message 00569 TRACE_DEBUG(" MAR = %02" PRIX8 " %02" PRIX8 " %02" PRIX8 " %02" PRIX8 " " 00570 "%02" PRIX8 " %02" PRIX8 " %02" PRIX8 " %02" PRIX8 "\r\n", 00571 dm9000ReadReg(DM9000_REG_MAR0), dm9000ReadReg(DM9000_REG_MAR1), 00572 dm9000ReadReg(DM9000_REG_MAR2), dm9000ReadReg(DM9000_REG_MAR3), 00573 dm9000ReadReg(DM9000_REG_MAR4), dm9000ReadReg(DM9000_REG_MAR5), 00574 dm9000ReadReg(DM9000_REG_MAR6), dm9000ReadReg(DM9000_REG_MAR7)); 00575 00576 //Successful processing 00577 return NO_ERROR; 00578 } 00579 00580 00581 /** 00582 * @brief Write DM9000 register 00583 * @param[in] address Register address 00584 * @param[in] data Register value 00585 **/ 00586 00587 void dm9000WriteReg(uint8_t address, uint8_t data) 00588 { 00589 //Write register address to INDEX register 00590 DM9000_INDEX_REG = address; 00591 //Write register value to DATA register 00592 DM9000_DATA_REG = data; 00593 } 00594 00595 00596 /** 00597 * @brief Read DM9000 register 00598 * @param[in] address Register address 00599 * @return Register value 00600 **/ 00601 00602 uint8_t dm9000ReadReg(uint8_t address) 00603 { 00604 //Write register address to INDEX register 00605 DM9000_INDEX_REG = address; 00606 //Read register value from DATA register 00607 return DM9000_DATA_REG; 00608 } 00609 00610 00611 /** 00612 * @brief Write DM9000 PHY register 00613 * @param[in] address PHY register address 00614 * @param[in] data Register value 00615 **/ 00616 00617 void dm9000WritePhyReg(uint8_t address, uint16_t data) 00618 { 00619 //Write PHY register address 00620 dm9000WriteReg(DM9000_REG_EPAR, 0x40 | address); 00621 //Write register value 00622 dm9000WriteReg(DM9000_REG_EPDRL, LSB(data)); 00623 dm9000WriteReg(DM9000_REG_EPDRH, MSB(data)); 00624 00625 //Start the write operation 00626 dm9000WriteReg(DM9000_REG_EPCR, EPCR_EPOS | EPCR_ERPRW); 00627 //PHY access is still in progress? 00628 while(dm9000ReadReg(DM9000_REG_EPCR) & EPCR_ERRE); 00629 00630 //Wait 5us minimum 00631 usleep(5); 00632 //Clear command register 00633 dm9000WriteReg(DM9000_REG_EPCR, EPCR_EPOS); 00634 } 00635 00636 00637 /** 00638 * @brief Read DM9000 PHY register 00639 * @param[in] address PHY register address 00640 * @return Register value 00641 **/ 00642 00643 uint16_t dm9000ReadPhyReg(uint8_t address) 00644 { 00645 //Write PHY register address 00646 dm9000WriteReg(DM9000_REG_EPAR, 0x40 | address); 00647 00648 //Start the read operation 00649 dm9000WriteReg(DM9000_REG_EPCR, EPCR_EPOS | EPCR_ERPRR); 00650 //PHY access is still in progress? 00651 while(dm9000ReadReg(DM9000_REG_EPCR) & EPCR_ERRE); 00652 00653 //Clear command register 00654 dm9000WriteReg(DM9000_REG_EPCR, EPCR_EPOS); 00655 //Wait 5us minimum 00656 usleep(5); 00657 00658 //Return register value 00659 return (dm9000ReadReg(DM9000_REG_EPDRH) << 8) | dm9000ReadReg(DM9000_REG_EPDRL); 00660 } 00661 00662 00663 /** 00664 * @brief CRC calculation 00665 * @param[in] data Pointer to the data over which to calculate the CRC 00666 * @param[in] length Number of bytes to process 00667 * @return Resulting CRC value 00668 **/ 00669 00670 uint32_t dm9000CalcCrc(const void *data, size_t length) 00671 { 00672 uint_t i; 00673 uint_t j; 00674 00675 //Point to the data over which to calculate the CRC 00676 const uint8_t *p = (uint8_t *) data; 00677 //CRC preset value 00678 uint32_t crc = 0xFFFFFFFF; 00679 00680 //Loop through data 00681 for(i = 0; i < length; i++) 00682 { 00683 //Update CRC value 00684 crc ^= p[i]; 00685 //The message is processed bit by bit 00686 for(j = 0; j < 8; j++) 00687 { 00688 if(crc & 0x00000001) 00689 crc = (crc >> 1) ^ 0xEDB88320; 00690 else 00691 crc = crc >> 1; 00692 } 00693 } 00694 00695 //Return CRC value 00696 return crc; 00697 } 00698
Generated on Tue Jul 12 2022 17:10:13 by
1.7.2