AVR-LibC  2.3.0
Standard C library for AVR-GCC
 

AVR-LibC Manual

AVR-LibC Sources

Main Page

User Manual

Lib­rary Refe­rence

FAQ

Exam­ple Pro­jects

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
75The hexadecimal values shown beneath the polynomials may be in
76little-endian or big-endian notation. The leading term is implicit.
77For details, see the respective implementation and the references.
78*/
79
80/** \ingroup util_crc
81 Optimized CRC-16 calculation.
82
83 Polynomial: x<sup>16</sup> + x<sup>15</sup> + x<sup>2</sup> + 1 (0xa001, big-endian)<br>
84 Initial value: \c 0xffff
85
86 This CRC is normally used in disk-drive controllers.
87
88 The following is the equivalent functionality written in C.
89
90 \code
91 static inline uint16_t
92 _crc16_update (uint16_t crc, uint8_t a)
93 {
94 crc ^= a;
95 for (int i = 0; i < 8; ++i)
96 {
97 if (crc & 1)
98 crc = (crc >> 1) ^ 0xA001;
99 else
100 crc = crc >> 1;
101 }
102
103 return crc;
104 }
105 \endcode */
106
107static __ATTR_ALWAYS_INLINE__ uint16_t
109{
110 uint8_t __tmp;
111 uint16_t __ret;
112
113 __asm__ __volatile__ (
114 "eor %A0,%2" "\n\t"
115 "mov %1,%A0" "\n\t"
116 "swap %1" "\n\t"
117 "eor %1,%A0" "\n\t"
118 "mov __tmp_reg__,%1" "\n\t"
119 "lsr %1" "\n\t"
120 "lsr %1" "\n\t"
121 "eor %1,__tmp_reg__" "\n\t"
122 "mov __tmp_reg__,%1" "\n\t"
123 "lsr %1" "\n\t"
124 "eor %1,__tmp_reg__" "\n\t"
125 "andi %1,0x07" "\n\t"
126 "mov __tmp_reg__,%A0" "\n\t"
127 "mov %A0,%B0" "\n\t"
128 "lsr %1" "\n\t"
129 "ror __tmp_reg__" "\n\t"
130 "ror %1" "\n\t"
131 "mov %B0,__tmp_reg__" "\n\t"
132 "eor %A0,%1" "\n\t"
133 "lsr __tmp_reg__" "\n\t"
134 "ror %1" "\n\t"
135 "eor %B0,__tmp_reg__" "\n\t"
136 "eor %A0,%1"
137 : "=r" (__ret), "=d" (__tmp)
138 : "r" (__data), "0" (__crc)
139 : "r0"
140 );
141 return __ret;
142}
143
144/** \ingroup util_crc
145 Optimized CRC-XMODEM calculation.
146
147 Polynomial: x<sup>16</sup> + x<sup>12</sup> + x<sup>5</sup> + 1 (0x1021, little-endian)<br>
148 Initial value: \c 0x0
149
150 This is the CRC used by the Xmodem-CRC protocol.
151
152 The following is the equivalent functionality written in C.
153
154 \code
155 static inline uint16_t
156 _crc_xmodem_update (uint16_t crc, uint8_t data)
157 {
158 crc = crc ^ ((uint16_t)data << 8);
159 for (int i = 0; i < 8; i++)
160 {
161 if (crc & 0x8000)
162 crc = (crc << 1) ^ 0x1021;
163 else
164 crc <<= 1;
165 }
166
167 return crc;
168 }
169 \endcode */
170
171static __ATTR_ALWAYS_INLINE__ uint16_t
173{
174 uint16_t __ret; /* %B0:%A0 (alias for __crc) */
175 uint8_t __tmp1; /* %1 */
176 uint8_t __tmp2; /* %2 */
177 /* %3 __data */
178
179 __asm__ __volatile__ (
180 "eor %B0,%3" "\n\t"
181 "mov %1,%A0" "\n\t"
182 "mov %2,%B0" "\n\t"
183
184 "mov %A0,%B0" "\n\t"
185 "swap %B0" "\n\t"
186 "eor %A0,%B0" "\n\t"
187
188 "andi %A0,0xf0" "\n\t"
189 "andi %B0,0x0f" "\n\t"
190
191 "eor %1,%A0" "\n\t"
192 "eor %2,%B0" "\n\t"
193
194 "lsl %A0" "\n\t"
195 "rol %B0" "\n\t"
196
197 "eor %B0,%1" "\n\t"
198 "eor %A0,%2"
199 : "=d" (__ret), "=r" (__tmp1), "=r" (__tmp2)
200 : "r" (__data), "0" (__crc)
201 );
202 return __ret;
203}
204
205/** \ingroup util_crc
206 Optimized CRC-CCITT calculation.
207
208 Polynomial: x<sup>16</sup> + x<sup>12</sup> + x<sup>5</sup> + 1 (0x8408, big-endian)<br>
209 Initial value: \c 0xffff
210
211 This is the CRC used by PPP and IrDA.
212
213 See RFC1171 (PPP protocol) and IrDA IrLAP 1.1
214
215 \note Although the CCITT polynomial is the same as that used by the Xmodem
216 protocol, they are quite different. The difference is in how the bits are
217 shifted through the algorithm. Xmodem shifts the MSB of the CRC and the
218 input first, while CCITT shifts the LSB of the CRC and the input first.
219
220 The following is the equivalent functionality written in C.
221
222 \code
223 static inline uint16_t
224 _crc_ccitt_update (uint16_t crc, uint8_t data)
225 {
226 data ^= lo8 (crc);
227 data ^= data << 4;
228
229 return ((((uint16_t)data << 8) | hi8 (crc)) ^ (uint8_t)(data >> 4)
230 ^ ((uint16_t)data << 3));
231 }
232 \endcode */
233
234static __ATTR_ALWAYS_INLINE__ uint16_t
236{
237 uint16_t __ret;
238
239 __asm__ __volatile__ (
240 "eor %A0,%1" "\n\t"
241
242 "mov __tmp_reg__,%A0" "\n\t"
243 "swap %A0" "\n\t"
244 "andi %A0,0xf0" "\n\t"
245 "eor %A0,__tmp_reg__" "\n\t"
246
247 "mov __tmp_reg__,%B0" "\n\t"
248
249 "mov %B0,%A0" "\n\t"
250
251 "swap %A0" "\n\t"
252 "andi %A0,0x0f" "\n\t"
253 "eor __tmp_reg__,%A0" "\n\t"
254
255 "lsr %A0" "\n\t"
256 "eor %B0,%A0" "\n\t"
257
258 "eor %A0,%B0" "\n\t"
259 "lsl %A0" "\n\t"
260 "lsl %A0" "\n\t"
261 "lsl %A0" "\n\t"
262 "eor %A0,__tmp_reg__"
263
264 : "=d" (__ret)
265 : "r" (__data), "0" (__crc)
266 : "r0"
267 );
268 return __ret;
269}
270
271/** \ingroup util_crc
272 Optimized Dallas (now Maxim) iButton 8-bit CRC calculation.
273
274 Polynomial: x<sup>8</sup> + x<sup>5</sup> + x<sup>4</sup> + 1 (0x8C, big-endian)<br>
275 Initial value: \c 0x0
276
277 See http://www.maxim-ic.com/appnotes.cfm/appnote_number/27
278
279 The following is the equivalent functionality written in C.
280
281 \code
282 static inline uint8_t
283 _crc_ibutton_update (uint8_t crc, uint8_t data)
284 {
285 crc = crc ^ data;
286 for (uint8_t i = 0; i < 8; i++)
287 {
288 if (crc & 0x01)
289 crc = (crc >> 1) ^ 0x8C;
290 else
291 crc >>= 1;
292 }
293
294 return crc;
295 }
296 \endcode
297*/
298
299static __ATTR_ALWAYS_INLINE__ uint8_t
301{
302 uint8_t __i, __pattern;
303 __asm__ __volatile__ (
304 "eor %0, %4" "\n\t"
305 "ldi %1, 8" "\n\t"
306 "ldi %2, 0x8C" "\n"
307 "1: lsr %0" "\n\t"
308 "brcc 2f" "\n\t"
309 "eor %0, %2" "\n"
310 "2: dec %1" "\n\t"
311 "brne 1b"
312 : "=r" (__crc), "=d" (__i), "=d" (__pattern)
313 : "0" (__crc), "r" (__data));
314 return __crc;
315}
316
317/** \ingroup util_crc
318 Optimized CRC-8-CCITT calculation.
319
320 Polynomial: x<sup>8</sup> + x<sup>2</sup> + x + 1 (0xE0, big-endian)<br>
321
322 For use with simple CRC-8<br>
323 Initial value: 0x0
324
325 For use with CRC-8-ROHC<br>
326 Initial value: 0xff<br>
327 Reference: http://tools.ietf.org/html/rfc3095#section-5.9.1
328
329 For use with CRC-8-ATM/ITU<br>
330 Initial value: 0xff<br>
331 Final XOR value: 0x55<br>
332 Reference: http://www.itu.int/rec/T-REC-I.432.1-199902-I/en
333
334 The C equivalent has been originally written by Dave Hylands.
335 Assembly code is based on \c _crc_ibutton_update optimization.
336
337 The following is the equivalent functionality written in C.
338
339 \code
340 static inline uint8_t
341 _crc8_ccitt_update (uint8_t inCrc, uint8_t inData)
342 {
343 uint8_t data = inCrc ^ inData;
344
345 for (int i = 0; i < 8; i++)
346 {
347 if ((data & 0x80) != 0)
348 {
349 data <<= 1;
350 data ^= 0x07;
351 }
352 else
353 {
354 data <<= 1;
355 }
356 }
357 return data;
358 }
359 \endcode
360*/
361
362static __ATTR_ALWAYS_INLINE__ uint8_t
364{
365 uint8_t __i, __pattern;
366 __asm__ __volatile__ (
367 "eor %0, %4" "\n\t"
368 "ldi %1, 8" "\n\t"
369 "ldi %2, 0x07" "\n"
370 "1: lsl %0" "\n\t"
371 "brcc 2f" "\n\t"
372 "eor %0, %2" "\n"
373 "2: dec %1" "\n\t"
374 "brne 1b"
375 : "=r" (__crc), "=d" (__i), "=d" (__pattern)
376 : "0" (__crc), "r" (__data));
377 return __crc;
378}
379
380#endif /* _UTIL_CRC16_H_ */
unsigned int uint16_t
Definition: stdint.h:96
unsigned char uint8_t
Definition: stdint.h:88
static uint16_t _crc_xmodem_update(uint16_t __crc, uint8_t __data)
Definition: crc16.h:172
static uint16_t _crc_ccitt_update(uint16_t __crc, uint8_t __data)
Definition: crc16.h:235
static uint8_t _crc8_ccitt_update(uint8_t __crc, uint8_t __data)
Definition: crc16.h:363
static uint8_t _crc_ibutton_update(uint8_t __crc, uint8_t __data)
Definition: crc16.h:300
static uint16_t _crc16_update(uint16_t __crc, uint8_t __data)
Definition: crc16.h:108