Make CRC on stm32 match with software implementation

Question:

Upd. See the end of post for working code

I’m already mad with this. How can I make checksum from CRC unit on stm32f103 match with software implementation? Stm has polynom 0x04C11DB7 and reset value 0xFFFFFFFF. So I’ve tried to calculate it in python.

Code for stm:

uint32_t crc32_hard_block(uint32_t *buf, uint32_t len)
{
    CRC_ResetDR();
    uint32_t crc = CRC_CalcBlockCRC(buf, len);
    return crc;
}

uint32_t buf[4] = {50, 10, 243, 147};
uint32_t crc_hard_block = crc32_hard_block(buf, 4);

Code for python:

custom_crc_table = {}

def int_to_bytes(i):
    return [(i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF]

def reverse_int(i, w):
    b = '{:0{width}b}'.format(i, width=w)
    return int(b[::-1], 2)


def generate_crc32_table(_poly):

    global custom_crc_table

    for i in range(256):
        c = i << 24

        for j in range(8):
            c = (c << 1) ^ _poly if (c & 0x80000000) else c << 1

        custom_crc_table[i] = c


def custom_crc32(buf, _poly):

    global custom_crc_table
    crc = 0xFFFFFFFF

    for integer in buf:
        b = int_to_bytes(integer)

        for byte in b:
            top = (crc >> 24) & 0xFF
            crc = (crc << 8) | byte
            crc = crc ^ custom_crc_table[top]

    return crc, reverse_int(crc, 32)

poly = 0x04C11DB7
buf = [50, 10, 243, 147]

generate_crc32_table(poly)
custom_crc, rev = custom_crc32(buf, poly)

print("Custom rev src      " + hex(rev))
print("Custom crc          " + hex(custom_crc))

Testing on array [50, 10, 243, 147] gives me output:

In python:

Custom rev src      0x344a9514f010200020100010100020301000203
Custom crc          0x3010002030100020200020100010203ca2a548b #reversed

It’s definetly something wrong with my crc.

In stm:

0x491b3bf3

UPDATE

Here is working code for software crc as on stm32f103 and code for stm32f103.

Python:

def generate_crc32_table(_poly):

    global custom_crc_table

    for i in range(256):
        c = i << 24

        for j in range(8):
            c = (c << 1) ^ _poly if (c & 0x80000000) else c << 1

        custom_crc_table[i] = c & 0xffffffff


def crc32_stm(bytes_arr):

    length = len(bytes_arr)
    crc = 0xffffffff

    k = 0
    while length >= 4:

        v = ((bytes_arr[k] << 24) & 0xFF000000) | ((bytes_arr[k+1] << 16) & 0xFF0000) | 
        ((bytes_arr[k+2] << 8) & 0xFF00) | (bytes_arr[k+3] & 0xFF)

        crc = ((crc << 8) & 0xffffffff) ^ custom_crc_table[0xFF & ((crc >> 24) ^ v)]
        crc = ((crc << 8) & 0xffffffff) ^ custom_crc_table[0xFF & ((crc >> 24) ^ (v >> 8))]
        crc = ((crc << 8) & 0xffffffff) ^ custom_crc_table[0xFF & ((crc >> 24) ^ (v >> 16))]
        crc = ((crc << 8) & 0xffffffff) ^ custom_crc_table[0xFF & ((crc >> 24) ^ (v >> 24))]

        k += 4
        length -= 4

    if length > 0:
        v = 0

        for i in range(length):
            v |= (bytes_arr[k+i] << 24-i*8)

        if length == 1:
            v &= 0xFF000000

        elif length == 2:
            v &= 0xFFFF0000

        elif length == 3:
            v &= 0xFFFFFF00

        crc = (( crc << 8 ) & 0xffffffff) ^ custom_crc_table[0xFF & ( (crc >> 24) ^ (v ) )];
        crc = (( crc << 8 ) & 0xffffffff) ^ custom_crc_table[0xFF & ( (crc >> 24) ^ (v >> 8) )];
        crc = (( crc << 8 ) & 0xffffffff) ^ custom_crc_table[0xFF & ( (crc >> 24) ^ (v >> 16) )];
        crc = (( crc << 8 ) & 0xffffffff) ^ custom_crc_table[0xFF & ( (crc >> 24) ^ (v >> 24) )];

    return crc

poly = 0x04C11DB7
buf = [50, 10, 243, 147]

generate_crc32_table(poly)
crc_stm = crc32_stm(bytearray(buf))

Stm32f103:

#include <stm32f10x_crc.h>    

uint32_t crc32_native(char *bfr, int len, int clear) {

    uint32_t crc;
    int l = len / 4;
    uint32_t *p = (uint32_t*)bfr;
    uint32_t x = p[l];

    if(clear)
    {
        CRC_ResetDR();
    }

    while(l--)
    {
        crc = CRC_CalcCRC(*p++);
    }

    switch(len & 3)
    {
        case 1: crc = CRC_CalcCRC(x & 0x000000FF); break;
        case 2: crc = CRC_CalcCRC(x & 0x0000FFFF); break;
        case 3: crc = CRC_CalcCRC(x & 0x00FFFFFF); break;
    }

    return crc;
}
Asked By: Long Smith

||

Answers:

custom_crc_table = {}

def int_to_bytes(i):
    return [(i >> 24) & 0xFF, (i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF]


def generate_crc32_table(_poly):

    global custom_crc_table

    for i in range(256):
        c = i << 24

        for j in range(8):
            c = (c << 1) ^ _poly if (c & 0x80000000) else c << 1

        custom_crc_table[i] = c & 0xffffffff


def custom_crc32(buf):

    global custom_crc_table
    crc = 0xffffffff

    for integer in buf:
        b = int_to_bytes(integer)

        for byte in b:
            crc = ((crc << 8) & 0xffffffff) ^ custom_crc_table[(crc >> 24) ^ byte]

    return crc

poly = 0x04C11DB7
buf = [50, 10, 243, 147]

generate_crc32_table(poly)
custom_crc = custom_crc32(buf)

print("Custom crc          " + hex(custom_crc))
Answered By: Mark Adler

I have tried many approaches to get a CRC32 python implementation that mimics the HAL STM32f407 implementation and I finally came across that it uses the crc32 mpeg2 algorithm. For anyone like me stuck, here is a python implementation of it.

def crc32mpeg2(buf, crc=0xffffffff):
for val in buf:
    crc ^= val << 24
    for _ in range(8):
        crc = crc << 1 if (crc & 0x80000000) == 0 else (crc << 1) ^ 0x104c11db7
return crc
Answered By: Satake
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.