AVR-LibC  2.3.0git
Standard C library for AVR-GCC
 

AVR-LibC Documen­tation

AVR-LibC Development Pages

Main Page

User Manual

Library Refe­rence

FAQ

Example Projects

File List

Index

Loading...
Searching...
No Matches
crc16.h
Go to the documentation of this file.
1/* Copyright (c) 2002, 2003, 2004 Marek Michalkiewicz
2 Copyright (c) 2005, 2007 Joerg Wunsch
3 Copyright (c) 2013 Dave Hylands
4 Copyright (c) 2013 Frederic Nadeau
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9
10 * Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12
13 * Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in
15 the documentation and/or other materials provided with the
16 distribution.
17
18 * Neither the name of the copyright holders nor the names of
19 contributors may be used to endorse or promote products derived
20 from this software without specific prior written permission.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 POSSIBILITY OF SUCH DAMAGE. */
33
34#ifndef _UTIL_CRC16_H_
35#define _UTIL_CRC16_H_
36
37#include <stdint.h>
38#include <bits/attribs.h>
39
40/** \file */
41/** \defgroup util_crc <util/crc16.h>: CRC Computations
42 \code#include <util/crc16.h>\endcode
43
44 This header file provides optimized inline functions for calculating
45 cyclic redundancy checks (CRC) using common polynomials.
46
47 A typical application would look like:
48
49 \code
50 // Dallas iButton test vector.
51 uint8_t serno[] = { 0x02, 0x1c, 0xb8, 0x01, 0, 0, 0, 0xa2 };
52
53 int
54 checkcrc (void)
55 {
56 uint8_t crc = 0, i;
57
58 for (i = 0; i < sizeof serno / sizeof serno[0]; i++)
59 crc = _crc_ibutton_update (crc, serno[i]);
60
61 return crc; // must be 0
62 }
63 \endcode
64
65 \par References:
66 See the Dallas Semiconductor app note 27 for 8051 assembler example and
67 general CRC optimization suggestions. The table on the last page of the
68 app note is the key to understanding these implementations.
69 \par
70 Jack Crenshaw's "Implementing CRCs" article in the January 1992 issue of \e
71 Embedded \e Systems \e Programming. This may be difficult to find, but it
72 explains CRC's in very clear and concise terms. Well worth the effort to
73 obtain a copy.
74*/
75
76/** \ingroup util_crc
77 Optimized CRC-16 calculation.
78
79 Polynomial: x<sup>16</sup> + x<sup>15</sup> + x<sup>2</sup> + 1 (0xa001)<br>
80 Initial value: \c 0xffff
81
82 This CRC is normally used in disk-drive controllers.
83
84 The following is the equivalent functionality written in C.
85
86 \code
87 static inline uint16_t
88 _crc16_update (uint16_t crc, uint8_t a)
89 {
90 crc ^= a;
91 for (int i = 0; i < 8; ++i)
92 {
93 if (crc & 1)
94 crc = (crc >> 1) ^ 0xA001;
95 else
96 crc = crc >> 1;
97 }
98
99 return crc;
100 }
101 \endcode */
102
103static __ATTR_ALWAYS_INLINE__ uint16_t
105{
106 uint8_t __tmp;
107 uint16_t __ret;
108
109 __asm__ __volatile__ (
110 "eor %A0,%2" "\n\t"
111 "mov %1,%A0" "\n\t"
112 "swap %1" "\n\t"
113 "eor %1,%A0" "\n\t"
114 "mov __tmp_reg__,%1" "\n\t"
115 "lsr %1" "\n\t"
116 "lsr %1" "\n\t"
117 "eor %1,__tmp_reg__" "\n\t"
118 "mov __tmp_reg__,%1" "\n\t"
119 "lsr %1" "\n\t"
120 "eor %1,__tmp_reg__" "\n\t"
121 "andi %1,0x07" "\n\t"
122 "mov __tmp_reg__,%A0" "\n\t"
123 "mov %A0,%B0" "\n\t"
124 "lsr %1" "\n\t"
125 "ror __tmp_reg__" "\n\t"
126 "ror %1" "\n\t"
127 "mov %B0,__tmp_reg__" "\n\t"
128 "eor %A0,%1" "\n\t"
129 "lsr __tmp_reg__" "\n\t"
130 "ror %1" "\n\t"
131 "eor %B0,__tmp_reg__" "\n\t"
132 "eor %A0,%1"
133 : "=r" (__ret), "=d" (__tmp)
134 : "r" (__data), "0" (__crc)
135 : "r0"
136 );
137 return __ret;
138}
139
140/** \ingroup util_crc
141 Optimized CRC-XMODEM calculation.
142
143 Polynomial: x<sup>16</sup> + x<sup>12</sup> + x<sup>5</sup> + 1 (0x1021)<br>
144 Initial value: \c 0x0
145
146 This is the CRC used by the Xmodem-CRC protocol.
147
148 The following is the equivalent functionality written in C.
149
150 \code
151 static inline uint16_t
152 _crc_xmodem_update (uint16_t crc, uint8_t data)
153 {
154 crc = crc ^ ((uint16_t)data << 8);
155 for (int i = 0; i < 8; i++)
156 {
157 if (crc & 0x8000)
158 crc = (crc << 1) ^ 0x1021;
159 else
160 crc <<= 1;
161 }
162
163 return crc;
164 }
165 \endcode */
166
167static __ATTR_ALWAYS_INLINE__ uint16_t
169{
170 uint16_t __ret; /* %B0:%A0 (alias for __crc) */
171 uint8_t __tmp1; /* %1 */
172 uint8_t __tmp2; /* %2 */
173 /* %3 __data */
174
175 __asm__ __volatile__ (
176 "eor %B0,%3" "\n\t"
177 "mov %1,%A0" "\n\t"
178 "mov %2,%B0" "\n\t"
179
180 "mov %A0,%B0" "\n\t"
181 "swap %B0" "\n\t"
182 "eor %A0,%B0" "\n\t"
183
184 "andi %A0,0xf0" "\n\t"
185 "andi %B0,0x0f" "\n\t"
186
187 "eor %1,%A0" "\n\t"
188 "eor %2,%B0" "\n\t"
189
190 "lsl %A0" "\n\t"
191 "rol %B0" "\n\t"
192
193 "eor %B0,%1" "\n\t"
194 "eor %A0,%2"
195 : "=d" (__ret), "=r" (__tmp1), "=r" (__tmp2)
196 : "r" (__data), "0" (__crc)
197 );
198 return __ret;
199}
200
201/** \ingroup util_crc
202 Optimized CRC-CCITT calculation.
203
204 Polynomial: x<sup>16</sup> + x<sup>12</sup> + x<sup>5</sup> + 1 (0x8408)<br>
205 Initial value: \c 0xffff
206
207 This is the CRC used by PPP and IrDA.
208
209 See RFC1171 (PPP protocol) and IrDA IrLAP 1.1
210
211 \note Although the CCITT polynomial is the same as that used by the Xmodem
212 protocol, they are quite different. The difference is in how the bits are
213 shifted through the algorithm. Xmodem shifts the MSB of the CRC and the
214 input first, while CCITT shifts the LSB of the CRC and the input first.
215
216 The following is the equivalent functionality written in C.
217
218 \code
219 static inline uint16_t
220 _crc_ccitt_update (uint16_t crc, uint8_t data)
221 {
222 data ^= lo8 (crc);
223 data ^= data << 4;
224
225 return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4)
226 ^ ((uint16_t)data << 3));
227 }
228 \endcode */
229
230static __ATTR_ALWAYS_INLINE__ uint16_t
232{
233 uint16_t __ret;
234
235 __asm__ __volatile__ (
236 "eor %A0,%1" "\n\t"
237
238 "mov __tmp_reg__,%A0" "\n\t"
239 "swap %A0" "\n\t"
240 "andi %A0,0xf0" "\n\t"
241 "eor %A0,__tmp_reg__" "\n\t"
242
243 "mov __tmp_reg__,%B0" "\n\t"
244
245 "mov %B0,%A0" "\n\t"
246
247 "swap %A0" "\n\t"
248 "andi %A0,0x0f" "\n\t"
249 "eor __tmp_reg__,%A0" "\n\t"
250
251 "lsr %A0" "\n\t"
252 "eor %B0,%A0" "\n\t"
253
254 "eor %A0,%B0" "\n\t"
255 "lsl %A0" "\n\t"
256 "lsl %A0" "\n\t"
257 "lsl %A0" "\n\t"
258 "eor %A0,__tmp_reg__"
259
260 : "=d" (__ret)
261 : "r" (__data), "0" (__crc)
262 : "r0"
263 );
264 return __ret;
265}
266
267/** \ingroup util_crc
268 Optimized Dallas (now Maxim) iButton 8-bit CRC calculation.
269
270 Polynomial: x<sup>8</sup> + x<sup>5</sup> + x<sup>4</sup> + 1 (0x8C)<br>
271 Initial value: \c 0x0
272
273 See http://www.maxim-ic.com/appnotes.cfm/appnote_number/27
274
275 The following is the equivalent functionality written in C.
276
277 \code
278 static inline uint8_t
279 _crc_ibutton_update (uint8_t crc, uint8_t data)
280 {
281 crc = crc ^ data;
282 for (uint8_t i = 0; i < 8; i++)
283 {
284 if (crc & 0x01)
285 crc = (crc >> 1) ^ 0x8C;
286 else
287 crc >>= 1;
288 }
289
290 return crc;
291 }
292 \endcode
293*/
294
295static __ATTR_ALWAYS_INLINE__ uint8_t
297{
298 uint8_t __i, __pattern;
299 __asm__ __volatile__ (
300 "eor %0, %4" "\n\t"
301 "ldi %1, 8" "\n\t"
302 "ldi %2, 0x8C" "\n"
303 "1: lsr %0" "\n\t"
304 "brcc 2f" "\n\t"
305 "eor %0, %2" "\n"
306 "2: dec %1" "\n\t"
307 "brne 1b"
308 : "=r" (__crc), "=d" (__i), "=d" (__pattern)
309 : "0" (__crc), "r" (__data));
310 return __crc;
311}
312
313/** \ingroup util_crc
314 Optimized CRC-8-CCITT calculation.
315
316 Polynomial: x<sup>8</sup> + x<sup>2</sup> + x + 1 (0xE0)<br>
317
318 For use with simple CRC-8<br>
319 Initial value: 0x0
320
321 For use with CRC-8-ROHC<br>
322 Initial value: 0xff<br>
323 Reference: http://tools.ietf.org/html/rfc3095#section-5.9.1
324
325 For use with CRC-8-ATM/ITU<br>
326 Initial value: 0xff<br>
327 Final XOR value: 0x55<br>
328 Reference: http://www.itu.int/rec/T-REC-I.432.1-199902-I/en
329
330 The C equivalent has been originally written by Dave Hylands.
331 Assembly code is based on \c _crc_ibutton_update optimization.
332
333 The following is the equivalent functionality written in C.
334
335 \code
336 static inline uint8_t
337 _crc8_ccitt_update (uint8_t inCrc, uint8_t inData)
338 {
339 uint8_t data = inCrc ^ inData;
340
341 for (int i = 0; i < 8; i++)
342 {
343 if ((data & 0x80) != 0)
344 {
345 data <<= 1;
346 data ^= 0x07;
347 }
348 else
349 {
350 data <<= 1;
351 }
352 }
353 return data;
354 }
355 \endcode
356*/
357
358static __ATTR_ALWAYS_INLINE__ uint8_t
360{
361 uint8_t __i, __pattern;
362 __asm__ __volatile__ (
363 "eor %0, %4" "\n\t"
364 "ldi %1, 8" "\n\t"
365 "ldi %2, 0x07" "\n"
366 "1: lsl %0" "\n\t"
367 "brcc 2f" "\n\t"
368 "eor %0, %2" "\n"
369 "2: dec %1" "\n\t"
370 "brne 1b"
371 : "=r" (__crc), "=d" (__i), "=d" (__pattern)
372 : "0" (__crc), "r" (__data));
373 return __crc;
374}
375
376#endif /* _UTIL_CRC16_H_ */
unsigned int uint16_t
Definition: stdint.h:91
unsigned char uint8_t
Definition: stdint.h:81
static uint16_t _crc_xmodem_update(uint16_t __crc, uint8_t __data)
Definition: crc16.h:168
static uint16_t _crc_ccitt_update(uint16_t __crc, uint8_t __data)
Definition: crc16.h:231
static uint8_t _crc8_ccitt_update(uint8_t __crc, uint8_t __data)
Definition: crc16.h:359
static uint8_t _crc_ibutton_update(uint8_t __crc, uint8_t __data)
Definition: crc16.h:296
static uint16_t _crc16_update(uint16_t __crc, uint8_t __data)
Definition: crc16.h:104