generator

Generate C code with pycrc

The tutorial shows how to generate CRC code. The following lines generate the code for the CRC-32 model (used with Ethernet, MPEG-2, Gzip, Bzip2, PNG and others). Note that all parameters are defined with this call.

python pycrc.py --model crc-32 --algorithm table-driven --generate h -o crc.h
python pycrc.py --model crc-32 --algorithm table-driven --generate c -o crc.c

C prototypes

The main C function prototypes (defined in the generated file crc.h) are:

typedef uint32_t crc_t;

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

See the section about undefined parameters for the prototypes when not all CRC parameters in a model are defined.

Usage of the generated functions

The main C function prototypes (defined in the generated file crc.h) are: The function crc_init() returns the initialised CRC accumulator. Then the function crc_update() is called on the input stream, either over the whole input buffer on one go, or on parts of it, iteratively. Once the CRC was updated with all input characters, the function crc_finalize() is called to finalise the CRC calculation.

The pseudo-code for a calling function might look like:

unsigned char data[MAX_DATA_LEN];
size_t data_len;

crc_t crc = crc_init();
while ((data_len = read_data(data, MAX_DATA_LEN)) > 0) {
    crc = crc_update(crc, data, data_len);
}
crc = crc_finalize(crc);

Undefined parameters

If not all parameters in the CRC model are defined, then the signature of the prototypes changes a bit:

typedef unsigned long crc_t;

typedef struct {
    /* some parameters that define the CRC model */
} crc_cfg_t;

void crc_table_gen(const crc_cfg_t *cfg);
crc_t crc_init(const crc_cfg_t *cfg);
crc_t crc_update(const crc_cfg_t *cfg, crc_t crc, const unsigned char *data, size_t data_len);
crc_t crc_finalize(const crc_cfg_t *cfg, crc_t crc);

The function crc_table_gen() is only used with the table-driven algorithm. The calling function might look like:

crc_t crc;
unsigned char data[MAX_DATA_LEN];
size_t data_len;
crc_cfg_t cfg;

cfg.width = 32;
cfg.poly = 0x04c11db7ul;
cfg.reflect_in = true;
cfg.xor_in = 0xfffffffful;
cfg.reflect_out = true;
cfg.xor_out = 0xfffffffful;

cfg.msb_mask = (crc_t)1u << (width - 1);
cfg.crc_mask = (cfg->msb_mask - 1) | cfg->msb_mask;
cfg.crc_shift = cfg->width < 8 ? 8 - cfg->width : 0;


crc_table_gen(&cfg)
crc = crc_init(&cfg);
while ((data_len = read_data(data), MAX_DATA_LEN) > 0) {
    crc = crc_update(&cfg, crc, data, data_len);
}
crc = crc_finalize(&cfg, crc);