Name

pycrc — a parametrisable Cyclic Redundancy Check (CRC) calculation utility and C source code generator written in Python

Synopsis

pycrc [OPTIONS]

Description

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.

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-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 CRC Parametric Model

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.

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. 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 0x01 << (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.

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

Homepage

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

Author

Written by Thomas Pircher .

Copyright

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