Name

pycrc — pycrc is a free, easy to use Cyclic Redundancy Check (CRC) calculator and source code generator.

Synopsis

pycrc [OPTIONS]

Description

pycrc provides a parametrised CRC reference implementation written in Python and a source code generator for C. The generated C source code can be optimised for simplicity, speed or tight memory constraints for embedded platforms. The following operations are implemented:

  • generate the checksum of a string (ASCII or hex)

  • 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 straightforward 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 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.

Options

--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-hexstring=STRING

calculate the checksum of the given hexadecimal string

--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, crc-16-usb, crc-16-modbus, ccitt, r-crc-16, kermit, x-25, xmodem, zmodem, crc-24, crc-32, crc-32c, crc-32mpeg, posix, jam, xfer, crc-64, crc-64-jones}

--width=NUM

use NUM bits in the Polynomial

--poly=HEX

use HEX as Polynomial

--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=NUM

use NUM bits to index the CRC table; NUM must be one of the values {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

-oFILE , --output=FILE

write the generated code to FILE instead to stdout

The CRC Parametric Model

The parametric model follows Ross N. Williams' convention described in A Painless Guide to CRC Error Detection Algorithms, commonly called 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 Polynomial, in number of bits. This is also the width of the final CRC result. Previous versions of pycrc only multiples of 8 could be be used as Width for the table-driven algorithm. As of version 0.7.5, any Width is accepted on all algorithms.

Polynomial

The unreflected polynomial of the CRC algorithm.

The Polynomial may be specified in its standard form, i.e. with bit Width+1 set to 1, but the most significant bit may also be omitted. 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 using 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 string "123456789" and may be used to validate an implementation.

Code generation

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.

Fully parametrised models

#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;
}
            

Models with runtime-configurable parameters

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. This structure contains three additional parameters, msb_mask, crc_mask and crc_shift, 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
    unsigned int crc_shift;     // initialise as cfg->width < 8 ? 8 - cfg->width : 0
} crc_cfg_t;
            

msb_mask is a bitmask with the most significant bit of a Width bits wide data type set to 1. crc_mask is a bitmask with all bits of a Width bits wide data type set to 1. crc_shift is a shift counter that is used when Width is less than 8. It is the number of bits to shift the CRC register to align its top bit at a byte boundary.

The file test/main.c in the source package of pycrc contains a fully featured example of how to use the generated source code. A shorter, more compact main() function can be generated with the --generate c-main option. This second variant is the better option when some of the CRC parameters are known and some are unknown during code generation.

Examples

Calculate the CRC-32 checksum of the string 123456789:

pycrc.py --model crc-32 --check-string 123456789

Generate the source code of the table-driven algorithm for an embedded application.

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 size of the resulting table is 16 * sizeof(crc_t) bytes. 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

Generate the CRC table only:

pycrc.py --model kermit --generate table -o crc-table.txt

Homepage

pycrc can be downloaded from http://www.tty1.net/pycrc/.

Copyright

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.