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

--algorithm=ALGO

choose an algorithm from {bit_by_bit, bit_by_bit_fast, table_driven, all}

--model=MODEL

choose a parameter set from {crc-8, crc-16, citt, kermit, x-25, xmodem, zmodem, crc-32, crc-32c, posix, jam, xfer}

This is the parameter with the lowest priority. Any other option (whether specified before or after the --model option) will override its parameter.

--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_with=WIDTH

use WIDTH bits to index the crc table; WIDTH one of {1, 2, 4, 8}

--check_string=STRING

calculate the checksum of the given string ('123456789' default)

--check_file=FILE

calculate the checksum of the given file

--generate_c

generate a C source file

--generate_c_main

generate a C source file with main function

--generate_h

generate a C header source file

--symbol_prefix=STRING

when generating source code, use STRING as prefix to the generated symbols

-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

The Code generator outputs strict ISO C99 code. For every chosen parameter set, at least three functions are defined: 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 <unistd.h>
typedef XXXX ctc_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-16 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_with 4 --generate_h -o crc.h

pycrc.py --model crc-16 --algorithm table_driven --table_idx_with 4 --generate_c -o crc.c

The table index with of 4 bits ensures a moderate memory consumption. In fact, the resulting table is 16 * sizeof(crc_t) bytes big.

Author

Written by Thomas Pircher

Copyright

This work is licensed under the Creative Commons Attribution-Share Alike 2.5 License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/2.5/ or send a letter to Creative Commons, 543 Howard Street, 5th Floor, San Francisco, California, 94105, USA.