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.
FastCRChw.cpp
00001 /* FastCRC library code is placed under the MIT license 00002 * Copyright (c) 2014,2015 Frank Bösing 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining 00005 * a copy of this software and associated documentation files (the 00006 * "Software"), to deal in the Software without restriction, including 00007 * without limitation the rights to use, copy, modify, merge, publish, 00008 * distribute, sublicense, and/or sell copies of the Software, and to 00009 * permit persons to whom the Software is furnished to do so, subject to 00010 * the following conditions: 00011 * 00012 * The above copyright notice and this permission notice shall be 00013 * included in all copies or substantial portions of the Software. 00014 * 00015 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 00016 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 00017 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00018 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 00019 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 00020 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00021 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00022 * SOFTWARE. 00023 */ 00024 00025 // 00026 // HW-calculations are 32BIT 00027 // 00028 // Thanks to: 00029 // - Catalogue of parametrised CRC algorithms, CRC RevEng 00030 // http://reveng.sourceforge.net/crc-catalogue/ 00031 // 00032 // - Danjel McGougan (CRC-Table-Generator) 00033 // 00034 00035 00036 #if defined(__CORTEX_M4) || defined(__MK20DX256__) 00037 00038 00039 #include "FastCRC.h" 00040 00041 // =============================================== 00042 00043 typedef struct { 00044 union { 00045 uint32_t CRC; //CRC Data register 00046 struct { 00047 uint16_t CRC16; 00048 uint16_t CRC16_1; 00049 }; 00050 struct { 00051 uint8_t CRC8; 00052 uint8_t CRC8_1; 00053 uint8_t CRC8_2; 00054 uint8_t CRC8_3; 00055 }; 00056 }; 00057 uint32_t GPOLY; //CRC Polynomial register 00058 uint32_t CTRL; //CRC Control register 00059 } CRC_T; 00060 00061 static volatile CRC_T * const rCRC = (CRC_T *)0x40032000; 00062 00063 #define CRC_CTRL_WAS 25 // Write CRC Data Register As Seed(1) / Data(0) 00064 #define CRC_CTRL_TCRC 24 // Width of CRC protocol (0=16 BIT, 1=32 BIT) 00065 #define CRC_CTRL_TOTR1 29 // TOTR[1] 00066 00067 00068 // ================= 8-BIT CRC =================== 00069 00070 /** Constructor 00071 * Enables CRC-clock 00072 */ 00073 FastCRC8::FastCRC8(){ 00074 SIM_SCGC6 |= SIM_SCGC6_CRC_MASK; 00075 } 00076 00077 /** SMBUS CRC 00078 * aka CRC-8 00079 * @param data Pointer to Data 00080 * @param datalen Length of Data 00081 * @return CRC value 00082 */ 00083 uint8_t FastCRC8::smbus(const uint8_t *data, const uint16_t datalen) 00084 { 00085 // poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4 00086 return generic(0x07, 0, CRC_FLAG_NOREFLECT, data, datalen); 00087 } 00088 00089 /** MAXIM 8-Bit CRC 00090 * equivalent to _crc_ibutton_update() in crc16.h from avr_libc 00091 * @param data Pointer to Data 00092 * @param datalen Length of Data 00093 * @return CRC value 00094 */ 00095 uint8_t FastCRC8::maxim(const uint8_t *data, const uint16_t datalen) 00096 { 00097 // poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1 00098 return generic(0x31, 0, CRC_FLAG_REFLECT, data, datalen); 00099 } 00100 00101 /** Update 00102 * Call for subsequent calculations with previous seed 00103 * @param data Pointer to Data 00104 * @param datalen Length of Data 00105 * @return CRC value 00106 */ 00107 uint8_t FastCRC8::update(const uint8_t *data, const uint16_t datalen) 00108 { 00109 00110 const uint8_t *src = data; 00111 const uint8_t *target = src + datalen; 00112 00113 while (((uintptr_t)src & 0x03) != 0 && (src < target)) { 00114 rCRC->CRC8_3 = *src++; //Write 8 BIT 00115 } 00116 00117 while (src <= target-4) { 00118 rCRC->CRC = *( uint32_t *)src; //Write 32 BIT 00119 src += 4; 00120 } 00121 00122 while (src < target) { 00123 rCRC->CRC8_3 = *src++; //Write 8 Bit 00124 } 00125 00126 if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1)) 00127 return rCRC->CRC8; 00128 else 00129 return rCRC->CRC8_3; 00130 } 00131 00132 /** generic function for all 8-Bit CRCs 00133 * @param polynom Polynom 00134 * @param seed Seed 00135 * @param flags Flags 00136 * @param data Pointer to Data 00137 * @param datalen Length of Data 00138 * @return CRC value 00139 */ 00140 uint8_t FastCRC8::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const uint16_t datalen) 00141 { 00142 00143 rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25) 00144 rCRC->GPOLY = ((uint32_t)polynom)<<24; // Set polynom 00145 rCRC->CRC = ((uint32_t)seed<<24); // Write seed 00146 rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data 00147 00148 return update(data, datalen); 00149 } 00150 uint8_t FastCRC8::smbus_upd(const uint8_t *data, uint16_t datalen){return update(data, datalen);} 00151 uint8_t FastCRC8::maxim_upd(const uint8_t *data, uint16_t datalen){return update(data, datalen);} 00152 00153 // ================= 16-BIT CRC =================== 00154 00155 /** Constructor 00156 * Enables CRC-clock 00157 */ 00158 FastCRC16::FastCRC16(){ 00159 SIM_SCGC6 |= SIM_SCGC6_CRC_MASK; 00160 } 00161 00162 /** CCITT 00163 * Alias "false CCITT" 00164 * @param data Pointer to Data 00165 * @param datalen Length of Data 00166 * @return CRC value 00167 */ 00168 uint16_t FastCRC16::ccitt(const uint8_t *data,const uint16_t datalen) 00169 { 00170 // poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 00171 return generic(0x1021, 0XFFFF, CRC_FLAG_NOREFLECT, data, datalen); 00172 } 00173 00174 /** MCRF4XX 00175 * equivalent to _crc_ccitt_update() in crc16.h from avr_libc 00176 * @param data Pointer to Data 00177 * @param datalen Length of Data 00178 * @return CRC value 00179 */ 00180 uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const uint16_t datalen) 00181 { 00182 // poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91 00183 return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT, data, datalen); 00184 } 00185 00186 /** MODBUS 00187 * equivalent to _crc_16_update() in crc16.h from avr_libc 00188 * @param data Pointer to Data 00189 * @param datalen Length of Data 00190 * @return CRC value 00191 */ 00192 uint16_t FastCRC16::modbus(const uint8_t *data, const uint16_t datalen) 00193 { 00194 // poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37 00195 return generic(0x8005, 0XFFFF, CRC_FLAG_REFLECT, data, datalen); 00196 } 00197 00198 /** KERMIT 00199 * Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT 00200 * @param data Pointer to Data 00201 * @param datalen Length of Data 00202 * @return CRC value 00203 */ 00204 uint16_t FastCRC16::kermit(const uint8_t *data, const uint16_t datalen) 00205 { 00206 // poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189 00207 // sometimes byteswapped presentation of result 00208 return generic(0x1021, 0x00, CRC_FLAG_REFLECT, data, datalen); 00209 } 00210 00211 /** XMODEM 00212 * Alias ZMODEM, CRC-16/ACORN 00213 * @param data Pointer to Data 00214 * @param datalen Length of Data 00215 * @return CRC value 00216 */ 00217 uint16_t FastCRC16::xmodem(const uint8_t *data, const uint16_t datalen) 00218 { 00219 //width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3 00220 return generic(0x1021, 0, CRC_FLAG_NOREFLECT, data, datalen); 00221 } 00222 00223 /** X25 00224 * Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B 00225 * @param data Pointer to Data 00226 * @param datalen Length of Data 00227 * @return CRC value 00228 */ 00229 uint16_t FastCRC16::x25(const uint8_t *data, const uint16_t datalen) 00230 { 00231 // poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e 00232 return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen); 00233 } 00234 00235 /** Update 00236 * Call for subsequent calculations with previous seed 00237 * @param data Pointer to Data 00238 * @param datalen Length of Data 00239 * @return CRC value 00240 */ 00241 uint16_t FastCRC16::update(const uint8_t *data, const uint16_t datalen) 00242 { 00243 const uint8_t *src = data; 00244 const uint8_t *target = src + datalen; 00245 00246 while (((uintptr_t)src & 0x03) !=0 && (src < target)) { 00247 rCRC->CRC8_3 = *src++; //Write 8 BIT 00248 } 00249 00250 while (src <= target-4) { 00251 rCRC->CRC = *( uint32_t *)src; //Write 32 BIT 00252 src += 4; 00253 } 00254 00255 while (src < target) { 00256 rCRC->CRC8_3 = *src++; //Write 8 Bit 00257 } 00258 00259 if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1)) 00260 return rCRC->CRC16; 00261 else 00262 return rCRC->CRC16_1; 00263 } 00264 00265 /** generic function for all 16-Bit CRCs 00266 * @param polynom Polynom 00267 * @param seed Seed 00268 * @param flags Flags 00269 * @param data Pointer to Data 00270 * @param datalen Length of Data 00271 * @return CRC value 00272 */ 00273 uint16_t FastCRC16::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen) 00274 { 00275 00276 rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25) 00277 rCRC->GPOLY = ((uint32_t)polynom)<<16; // set polynom 00278 rCRC->CRC = ((uint32_t)seed<<16); // this is the seed 00279 rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data 00280 00281 return update(data, datalen); 00282 } 00283 00284 uint16_t FastCRC16::ccitt_upd(const uint8_t *data, uint16_t len) {return update(data, len);} 00285 uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, uint16_t len){return update(data, len);} 00286 uint16_t FastCRC16::kermit_upd(const uint8_t *data, uint16_t len) {return update(data, len);} 00287 uint16_t FastCRC16::modbus_upd(const uint8_t *data, uint16_t len) {return update(data, len);} 00288 uint16_t FastCRC16::xmodem_upd(const uint8_t *data, uint16_t len) {return update(data, len);} 00289 uint16_t FastCRC16::x25_upd(const uint8_t *data, uint16_t len) {return update(data, len);} 00290 00291 00292 00293 // ================= 32-BIT CRC =================== 00294 00295 /** Constructor 00296 * Enables CRC-clock 00297 */ 00298 FastCRC32::FastCRC32(){ 00299 SIM_SCGC6 |= SIM_SCGC6_CRC_MASK; 00300 } 00301 00302 /** CRC32 00303 * Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3 00304 * @param data Pointer to Data 00305 * @param datalen Length of Data 00306 * @return CRC value 00307 */ 00308 uint32_t FastCRC32::crc32(const uint8_t *data, const uint16_t datalen) 00309 { 00310 // poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926 00311 return generic(0x04C11DB7L, 0XFFFFFFFFL, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen); 00312 } 00313 00314 /** CKSUM 00315 * Alias CRC-32/POSIX 00316 * @param data Pointer to Data 00317 * @param datalen Length of Data 00318 * @return CRC value 00319 */ 00320 uint32_t FastCRC32::cksum(const uint8_t *data, const uint16_t datalen) 00321 { 00322 // width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680 00323 return generic(0x04C11DB7L, 0, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen); 00324 } 00325 00326 /** Update 00327 * Call for subsequent calculations with previous seed 00328 * @param data Pointer to Data 00329 * @param datalen Length of Data 00330 * @return CRC value 00331 */ 00332 //#pragma GCC diagnostic ignored "-Wpointer-arith" 00333 uint32_t FastCRC32::update(const uint8_t *data, const uint16_t datalen) 00334 { 00335 00336 const uint8_t *src = data; 00337 const uint8_t *target = src + datalen; 00338 00339 while (((uintptr_t)src & 0x03) != 0 && (src < target)) { 00340 rCRC->CRC8_3 = *src++; //Write 8 BIT 00341 } 00342 00343 while (src <= target-4) { 00344 rCRC->CRC = *( uint32_t *)src; //Write 32 BIT 00345 src += 4; 00346 } 00347 00348 while (src < target) { 00349 rCRC->CRC8_3 = *src++; //Write 8 Bit 00350 } 00351 00352 return rCRC->CRC; 00353 } 00354 00355 /** generic function for all 32-Bit CRCs 00356 * @param polynom Polynom 00357 * @param seed Seed 00358 * @param flags Flags 00359 * @param data Pointer to Data 00360 * @param datalen Length of Data 00361 * @return CRC value 00362 */ 00363 uint32_t FastCRC32::generic(const uint32_t polynom, const uint32_t seed, const uint32_t flags, const uint8_t *data, const uint16_t datalen) 00364 { 00365 00366 rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, prepare to write seed(25) 00367 rCRC->GPOLY = polynom; // Set polynom 00368 rCRC->CRC = seed; // This is the seed 00369 rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data 00370 00371 return update(data, datalen); 00372 } 00373 00374 uint32_t FastCRC32::crc32_upd(const uint8_t *data, uint16_t len){return update(data, len);} 00375 uint32_t FastCRC32::cksum_upd(const uint8_t *data, uint16_t len){return update(data, len);} 00376 00377 #endif // __MK20DX128__ || __MK20DX256__
Generated on Mon Jul 25 2022 09:04:30 by
1.7.2