$treeview $search $mathjax $extrastylesheet
avr-libc
2.0.0
$projectbrief
|
$projectbrief
|
$searchbox |
AVR Libc Home Page |
AVR Libc Development Pages |
||||
Main Page |
User Manual |
Library Reference |
FAQ |
Example Projects |
00001 /* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz 00002 Copyright (c) 2005, 2007 Joerg Wunsch 00003 Copyright (c) 2013 Dave Hylands 00004 Copyright (c) 2013 Frederic Nadeau 00005 All rights reserved. 00006 00007 Redistribution and use in source and binary forms, with or without 00008 modification, are permitted provided that the following conditions are met: 00009 00010 * Redistributions of source code must retain the above copyright 00011 notice, this list of conditions and the following disclaimer. 00012 00013 * Redistributions in binary form must reproduce the above copyright 00014 notice, this list of conditions and the following disclaimer in 00015 the documentation and/or other materials provided with the 00016 distribution. 00017 00018 * Neither the name of the copyright holders nor the names of 00019 contributors may be used to endorse or promote products derived 00020 from this software without specific prior written permission. 00021 00022 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00023 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00024 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00025 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00026 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00027 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00028 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00029 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00030 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00031 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 POSSIBILITY OF SUCH DAMAGE. */ 00033 00034 /* $Id$ */ 00035 00036 #ifndef _UTIL_CRC16_H_ 00037 #define _UTIL_CRC16_H_ 00038 00039 #include <stdint.h> 00040 00041 /** \file */ 00042 /** \defgroup util_crc <util/crc16.h>: CRC Computations 00043 \code#include <util/crc16.h>\endcode 00044 00045 This header file provides a optimized inline functions for calculating 00046 cyclic redundancy checks (CRC) using common polynomials. 00047 00048 \par References: 00049 00050 \par 00051 00052 See the Dallas Semiconductor app note 27 for 8051 assembler example and 00053 general CRC optimization suggestions. The table on the last page of the 00054 app note is the key to understanding these implementations. 00055 00056 \par 00057 00058 Jack Crenshaw's "Implementing CRCs" article in the January 1992 isue of \e 00059 Embedded \e Systems \e Programming. This may be difficult to find, but it 00060 explains CRC's in very clear and concise terms. Well worth the effort to 00061 obtain a copy. 00062 00063 A typical application would look like: 00064 00065 \code 00066 // Dallas iButton test vector. 00067 uint8_t serno[] = { 0x02, 0x1c, 0xb8, 0x01, 0, 0, 0, 0xa2 }; 00068 00069 int 00070 checkcrc(void) 00071 { 00072 uint8_t crc = 0, i; 00073 00074 for (i = 0; i < sizeof serno / sizeof serno[0]; i++) 00075 crc = _crc_ibutton_update(crc, serno[i]); 00076 00077 return crc; // must be 0 00078 } 00079 \endcode 00080 */ 00081 00082 /** \ingroup util_crc 00083 Optimized CRC-16 calculation. 00084 00085 Polynomial: x^16 + x^15 + x^2 + 1 (0xa001)<br> 00086 Initial value: 0xffff 00087 00088 This CRC is normally used in disk-drive controllers. 00089 00090 The following is the equivalent functionality written in C. 00091 00092 \code 00093 uint16_t 00094 crc16_update(uint16_t crc, uint8_t a) 00095 { 00096 int i; 00097 00098 crc ^= a; 00099 for (i = 0; i < 8; ++i) 00100 { 00101 if (crc & 1) 00102 crc = (crc >> 1) ^ 0xA001; 00103 else 00104 crc = (crc >> 1); 00105 } 00106 00107 return crc; 00108 } 00109 00110 \endcode */ 00111 00112 static __inline__ uint16_t 00113 _crc16_update(uint16_t __crc, uint8_t __data) 00114 { 00115 uint8_t __tmp; 00116 uint16_t __ret; 00117 00118 __asm__ __volatile__ ( 00119 "eor %A0,%2" "\n\t" 00120 "mov %1,%A0" "\n\t" 00121 "swap %1" "\n\t" 00122 "eor %1,%A0" "\n\t" 00123 "mov __tmp_reg__,%1" "\n\t" 00124 "lsr %1" "\n\t" 00125 "lsr %1" "\n\t" 00126 "eor %1,__tmp_reg__" "\n\t" 00127 "mov __tmp_reg__,%1" "\n\t" 00128 "lsr %1" "\n\t" 00129 "eor %1,__tmp_reg__" "\n\t" 00130 "andi %1,0x07" "\n\t" 00131 "mov __tmp_reg__,%A0" "\n\t" 00132 "mov %A0,%B0" "\n\t" 00133 "lsr %1" "\n\t" 00134 "ror __tmp_reg__" "\n\t" 00135 "ror %1" "\n\t" 00136 "mov %B0,__tmp_reg__" "\n\t" 00137 "eor %A0,%1" "\n\t" 00138 "lsr __tmp_reg__" "\n\t" 00139 "ror %1" "\n\t" 00140 "eor %B0,__tmp_reg__" "\n\t" 00141 "eor %A0,%1" 00142 : "=r" (__ret), "=d" (__tmp) 00143 : "r" (__data), "0" (__crc) 00144 : "r0" 00145 ); 00146 return __ret; 00147 } 00148 00149 /** \ingroup util_crc 00150 Optimized CRC-XMODEM calculation. 00151 00152 Polynomial: x^16 + x^12 + x^5 + 1 (0x1021)<br> 00153 Initial value: 0x0 00154 00155 This is the CRC used by the Xmodem-CRC protocol. 00156 00157 The following is the equivalent functionality written in C. 00158 00159 \code 00160 uint16_t 00161 crc_xmodem_update (uint16_t crc, uint8_t data) 00162 { 00163 int i; 00164 00165 crc = crc ^ ((uint16_t)data << 8); 00166 for (i=0; i<8; i++) 00167 { 00168 if (crc & 0x8000) 00169 crc = (crc << 1) ^ 0x1021; 00170 else 00171 crc <<= 1; 00172 } 00173 00174 return crc; 00175 } 00176 \endcode */ 00177 00178 static __inline__ uint16_t 00179 _crc_xmodem_update(uint16_t __crc, uint8_t __data) 00180 { 00181 uint16_t __ret; /* %B0:%A0 (alias for __crc) */ 00182 uint8_t __tmp1; /* %1 */ 00183 uint8_t __tmp2; /* %2 */ 00184 /* %3 __data */ 00185 00186 __asm__ __volatile__ ( 00187 "eor %B0,%3" "\n\t" /* crc.hi ^ data */ 00188 "mov __tmp_reg__,%B0" "\n\t" 00189 "swap __tmp_reg__" "\n\t" /* swap(crc.hi ^ data) */ 00190 00191 /* Calculate the ret.lo of the CRC. */ 00192 "mov %1,__tmp_reg__" "\n\t" 00193 "andi %1,0x0f" "\n\t" 00194 "eor %1,%B0" "\n\t" 00195 "mov %2,%B0" "\n\t" 00196 "eor %2,__tmp_reg__" "\n\t" 00197 "lsl %2" "\n\t" 00198 "andi %2,0xe0" "\n\t" 00199 "eor %1,%2" "\n\t" /* __tmp1 is now ret.lo. */ 00200 00201 /* Calculate the ret.hi of the CRC. */ 00202 "mov %2,__tmp_reg__" "\n\t" 00203 "eor %2,%B0" "\n\t" 00204 "andi %2,0xf0" "\n\t" 00205 "lsr %2" "\n\t" 00206 "mov __tmp_reg__,%B0" "\n\t" 00207 "lsl __tmp_reg__" "\n\t" 00208 "rol %2" "\n\t" 00209 "lsr %B0" "\n\t" 00210 "lsr %B0" "\n\t" 00211 "lsr %B0" "\n\t" 00212 "andi %B0,0x1f" "\n\t" 00213 "eor %B0,%2" "\n\t" 00214 "eor %B0,%A0" "\n\t" /* ret.hi is now ready. */ 00215 "mov %A0,%1" "\n\t" /* ret.lo is now ready. */ 00216 : "=d" (__ret), "=d" (__tmp1), "=d" (__tmp2) 00217 : "r" (__data), "0" (__crc) 00218 : "r0" 00219 ); 00220 return __ret; 00221 } 00222 00223 /** \ingroup util_crc 00224 Optimized CRC-CCITT calculation. 00225 00226 Polynomial: x^16 + x^12 + x^5 + 1 (0x8408)<br> 00227 Initial value: 0xffff 00228 00229 This is the CRC used by PPP and IrDA. 00230 00231 See RFC1171 (PPP protocol) and IrDA IrLAP 1.1 00232 00233 \note Although the CCITT polynomial is the same as that used by the Xmodem 00234 protocol, they are quite different. The difference is in how the bits are 00235 shifted through the alorgithm. Xmodem shifts the MSB of the CRC and the 00236 input first, while CCITT shifts the LSB of the CRC and the input first. 00237 00238 The following is the equivalent functionality written in C. 00239 00240 \code 00241 uint16_t 00242 crc_ccitt_update (uint16_t crc, uint8_t data) 00243 { 00244 data ^= lo8 (crc); 00245 data ^= data << 4; 00246 00247 return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4) 00248 ^ ((uint16_t)data << 3)); 00249 } 00250 \endcode */ 00251 00252 static __inline__ uint16_t 00253 _crc_ccitt_update (uint16_t __crc, uint8_t __data) 00254 { 00255 uint16_t __ret; 00256 00257 __asm__ __volatile__ ( 00258 "eor %A0,%1" "\n\t" 00259 00260 "mov __tmp_reg__,%A0" "\n\t" 00261 "swap %A0" "\n\t" 00262 "andi %A0,0xf0" "\n\t" 00263 "eor %A0,__tmp_reg__" "\n\t" 00264 00265 "mov __tmp_reg__,%B0" "\n\t" 00266 00267 "mov %B0,%A0" "\n\t" 00268 00269 "swap %A0" "\n\t" 00270 "andi %A0,0x0f" "\n\t" 00271 "eor __tmp_reg__,%A0" "\n\t" 00272 00273 "lsr %A0" "\n\t" 00274 "eor %B0,%A0" "\n\t" 00275 00276 "eor %A0,%B0" "\n\t" 00277 "lsl %A0" "\n\t" 00278 "lsl %A0" "\n\t" 00279 "lsl %A0" "\n\t" 00280 "eor %A0,__tmp_reg__" 00281 00282 : "=d" (__ret) 00283 : "r" (__data), "0" (__crc) 00284 : "r0" 00285 ); 00286 return __ret; 00287 } 00288 00289 /** \ingroup util_crc 00290 Optimized Dallas (now Maxim) iButton 8-bit CRC calculation. 00291 00292 Polynomial: x^8 + x^5 + x^4 + 1 (0x8C)<br> 00293 Initial value: 0x0 00294 00295 See http://www.maxim-ic.com/appnotes.cfm/appnote_number/27 00296 00297 The following is the equivalent functionality written in C. 00298 00299 \code 00300 uint8_t 00301 _crc_ibutton_update(uint8_t crc, uint8_t data) 00302 { 00303 uint8_t i; 00304 00305 crc = crc ^ data; 00306 for (i = 0; i < 8; i++) 00307 { 00308 if (crc & 0x01) 00309 crc = (crc >> 1) ^ 0x8C; 00310 else 00311 crc >>= 1; 00312 } 00313 00314 return crc; 00315 } 00316 \endcode 00317 */ 00318 00319 static __inline__ uint8_t 00320 _crc_ibutton_update(uint8_t __crc, uint8_t __data) 00321 { 00322 uint8_t __i, __pattern; 00323 __asm__ __volatile__ ( 00324 " eor %0, %4" "\n\t" 00325 " ldi %1, 8" "\n\t" 00326 " ldi %2, 0x8C" "\n\t" 00327 "1: lsr %0" "\n\t" 00328 " brcc 2f" "\n\t" 00329 " eor %0, %2" "\n\t" 00330 "2: dec %1" "\n\t" 00331 " brne 1b" "\n\t" 00332 : "=r" (__crc), "=d" (__i), "=d" (__pattern) 00333 : "0" (__crc), "r" (__data)); 00334 return __crc; 00335 } 00336 00337 /** \ingroup util_crc 00338 Optimized CRC-8-CCITT calculation. 00339 00340 Polynomial: x^8 + x^2 + x + 1 (0xE0)<br> 00341 00342 For use with simple CRC-8<br> 00343 Initial value: 0x0 00344 00345 For use with CRC-8-ROHC<br> 00346 Initial value: 0xff<br> 00347 Reference: http://tools.ietf.org/html/rfc3095#section-5.9.1 00348 00349 For use with CRC-8-ATM/ITU<br> 00350 Initial value: 0xff<br> 00351 Final XOR value: 0x55<br> 00352 Reference: http://www.itu.int/rec/T-REC-I.432.1-199902-I/en 00353 00354 The C equivalent has been originally written by Dave Hylands. 00355 Assembly code is based on _crc_ibutton_update optimization. 00356 00357 The following is the equivalent functionality written in C. 00358 00359 \code 00360 uint8_t 00361 _crc8_ccitt_update (uint8_t inCrc, uint8_t inData) 00362 { 00363 uint8_t i; 00364 uint8_t data; 00365 00366 data = inCrc ^ inData; 00367 00368 for ( i = 0; i < 8; i++ ) 00369 { 00370 if (( data & 0x80 ) != 0 ) 00371 { 00372 data <<= 1; 00373 data ^= 0x07; 00374 } 00375 else 00376 { 00377 data <<= 1; 00378 } 00379 } 00380 return data; 00381 } 00382 \endcode 00383 */ 00384 00385 static __inline__ uint8_t 00386 _crc8_ccitt_update(uint8_t __crc, uint8_t __data) 00387 { 00388 uint8_t __i, __pattern; 00389 __asm__ __volatile__ ( 00390 " eor %0, %4" "\n\t" 00391 " ldi %1, 8" "\n\t" 00392 " ldi %2, 0x07" "\n\t" 00393 "1: lsl %0" "\n\t" 00394 " brcc 2f" "\n\t" 00395 " eor %0, %2" "\n\t" 00396 "2: dec %1" "\n\t" 00397 " brne 1b" "\n\t" 00398 : "=r" (__crc), "=d" (__i), "=d" (__pattern) 00399 : "0" (__crc), "r" (__data)); 00400 return __crc; 00401 } 00402 00403 #endif /* _UTIL_CRC16_H_ */