pycrc — a parametrisable Cyclic Redundancy Check (CRC) calculation utility and C source code generator written in Python
pycrc
[OPTIONS]
pycrc provides a parametrised CRC reference implementation written in Python and a source code generator for C. Different variants of the CRC algorithm are supported and range from a fast but space-consuming implementation to slower but smaller code suitable especially for embedded applications. The following operations are implemented:
generate the checksum of a string
generate the checksum of a file
generate the C header and source files for a client implementation.
The following variants of the CRC algorithm are supported:
bit-by-bit
: the basic algorithm which operates individually on every bit of the augmented message
(i.e. the input data with Width
0-bits attached to the end).
This algorithm is the easiest to understand because it is a direct implementation of the basic polynomial division,
but it is also the slowest among all possible variants.
bit-by-bit-fast
: a variation of the simple bit-by-bit
algorithm,
with the difference that it does not need to augment the data, i.e. it does not add Width
zero
bits at the end of the message.
This algorithm might be a good choice for embedded platforms, where code space is a major concern.
table-driven
: the standard table driven algorithm. This algorithm works only with a
Width
which is a multiple of 8.
This is the fastest variant because it operates on one byte at a time, as opposed to bits, and uses a look-up table of 256 elements,
which might not be feasible for small embedded systems, though. Anyway, the number of elements in the look-up table can be reduced by
means of the --table-idx-width
command line switch. By using 4 bits (16 elements in the look-up table) a significant
speed-up can be measured with respect to the bit-by-bit algorithms.
--version
show program's version number and exit
-h
,
--help
show this help message and exit
--verbose
be more verbose; in particular, print the value of the parameters and the chosen model
--check-string=
STRING
calculate the checksum of the given string ('123456789
' default)
--check-file=
FILE
calculate the checksum of the given file
--generate=
CODE
generate the source code type as a choice from {c, h, c-main, table}
--std=
STD
C standard style of the generated code from {C89, ANSI, C99}
--algorithm=
ALGO
choose an algorithm from {bit-by-bit
, bit-by-bit-fast
,
table-driven
, all
}
--model=
MODEL
choose a parameter set from {crc-5
,
crc-8
,
dallas-1-wire
,
crc-15
,
crc-16-usb
,
crc-16
,
ccitt
,
r-crc-16
,
kermit
,
x-25
,
xmodem
,
zmodem
,
crc-24
,
crc-32
,
crc-32c
,
posix
,
jam
,
xfer
,
crc-64
}
--width=
WIDTH
use WIDTH bits in the Poly
--poly=
HEX
use HEX as polynom
--reflect-in=
BOOL
reflect input bytes
--xor-in=
HEX
use HEX as initial value
--reflect-out=
BOOL
reflect output bytes
--xor-out=
HEX
xor the final crc value with HEX
--table-idx-width=
WIDTH
use WIDTH bits to index the crc table; WIDTH one of {1
, 2
,
4
, 8
}
--symbol-prefix=
STRING
when generating source code, use STRING
as prefix to the generated symbols
--crc-type=
STRING
when generating source code, use STRING
as crc_t type
--include-file=
FILE
when generating source code, include also FILE
as header file
-o
file
,
--output=
file
write the generated code to file instead to stdout
The parametric model has been picked from Ross N. Williams' "A Painless Guide to CRC Error Detection Algorithms". He calls this set of parameters "The Rocksoft Model". Since most people are familiar with this kind of parameters, pycrc follows this convention, described as follows:
Width
The width of the CRC Poly
, in number of bits. This is also the width of the final CRC result.
For the bit-by-bit
and the bit-by-bit-fast
algorithms, any width
can be used, but for the table-driven
algorithm which operate on 8 bits at a time, only
multiples of 8 can be chosen as Width
.
Poly
The unreflected polynom of the CRC algorithm.
The Poly
may be specified in its standard form, i.e. with bit Width
+1
set to 1, but the most significant bit may also be ommitted. For example, for a Width
of 16,
both forms 0x18005 and 0x8005 are accepted.
ReflectIn
Reflect the bytes of the message before processing them. A word is reflected by inverting the position of its bits with respect to the middle axis of the word. The reversed value of 0xa3 (10100010b) is 0x45 (01000101b), for example. Some CRC algorithms can be implemented more efficiently in a bit reversed version.
Reflected algorithms are more efficient than straight-forward implementations, thus many of the standard algorithmic variants use reflected input bytes.
XorIn
The initial value (usually all 0 or all 1) in the algorithms which operate on the non-augmented message.
This value can be seen as a value which will be XOR-ed into the CRC register after Width
iterations of the bit-by-bit
algorithm.
This means the simple bit-by-bit
algorithm must calculate the initial value with some sort of
reverse CRC algorithm on the XorIn
value.
ReflectOut
Reflect the final CRC result. This operation takes place before XOR-ing the final CRC
value with the XorOut
parameter.
XorOut
A value (usually all bits 0 or all 1) which will be XOR-ed to the final CRC value.
Check
This value is not exactly a parameter of a model but it is sometimes given together with the Rocksoft Model parameters.
It is the CRC value of the parametrised model over the standard string 123456789
and
may be used to validate an implementation.
In the default configuration, the generated code is strict ISO C99 code.
A minimal set of three functions are defined for each algorithm:
crc_init()
, crc_update()
and crc_finalize()
.
According to the number of parameters given to pycrc, a different interface definition is generated.
Fully parametrised models have a simpler API, while the generated code for runtime-specified implementations adds a
pointer to a configuration structure as first parameter to all functions.
The generated source code uses the type crc_t, which is used throughout the code. It may be redefined in the generated header file.
#include <stdlib.h> typedef XXXX crc_t; // this type is defined in the generated header file
crc_t crc_init( | void) ; |
crc_t crc_update( | crc_t | crc, |
const unsigned char * | data, | |
size_t | data_len) ; |
crc_t crc_finalize( | crc_t | crc) ; |
The following code snippet shows how to use the generated functions.
#include "my_generated_crc.h" #include <stdio.h> int main(void) { static const unsigned char str1[] = "1234"; static const unsigned char str2[] = "56789"; crc_t crc; crc = crc_init(); crc = crc_update(crc, str1, sizeof(str1) - 1); crc = crc_update(crc, str2, sizeof(str2) - 1); // more calls to crc_update... crc = crc_finalize(crc); printf("0x%lx\n", (long)crc); return 0; }
When the model is not fully defined then the missing parameters are contained in a structure of
type crc_cfg_t.
The first argument of the crc functions is a pointer to that structure, and its fields must be initialised
properly by the user before the first call to the crc functions.
Tis structure contains two additional parameters, msb_mask
and crc_mask
,
if the Width
was undefined when the code was generated.
typedef struct { unsigned int width; crc_t poly; bool reflect_in; crc_t xor_in; bool reflect_out; crc_t xor_out; // internal parameters crc_t msb_mask; // initialise as 1UL << (cfg->width - 1) crc_t crc_mask; // initialise as (cfg->msb_mask - 1) | cfg->msb_mask } crc_cfg_t;
msb_mask
is a bitmask with the most significant bit of a width
bits
wide data type set to 1.
msb_mask
is a bitmask with all bits of a width
bits
wide data type set to 1.
pycrc.py --model crc-32 --check-string 123456789
pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate h -o crc.h
pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c -o crc.c
The table index width of 4 bits ensures a moderate memory consumption. In fact, the resulting table is
16 * sizeof(crc_t)
bytes big.
A variant of the last generated output is the c-main
target:
a simple main()
function is generated in addition to the crc routines:
pycrc.py --model crc-16 --algorithm table-driven --table-idx-width 4 --generate c-main -o crc.c
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.