Add CRC32 implementation

This commit is contained in:
jaseg 2020-11-26 12:38:52 +01:00
parent e282a5eb37
commit 451904a0c5
7 changed files with 128 additions and 2 deletions

View file

@ -23,9 +23,9 @@ DEBUG ?= 1
OPT ?= 0
BUILDDIR ?= build
BINARY := safetyreset.elf
BINARY := rotohsm_proto_rotor.elf
LDSCRIPT := generic_stm32.ld
DEVICE := STM32F302C8
DEVICE := STM32F302CB
########################################################################################################################
@ -53,6 +53,7 @@ C_SOURCES += $(MUSL_SOURCES)
PREFIX ?= arm-none-eabi-
HOSTCC := gcc
CC := $(PREFIX)gcc
CPP := $(PREFIX)cpp
CXX := $(PREFIX)g++
@ -102,6 +103,8 @@ COMMON_CFLAGS += -O$(OPT) -std=gnu11 -g
COMMON_CFLAGS += $(DEVICE_DEFINES)
COMMON_CFLAGS += -DDEBUG=$(DEBUG)
HOST_CFLAGS += $(COMMON_CFLAGS)
# for musl
CFLAGS += -Dhidden=
@ -193,6 +196,13 @@ $(BUILDDIR)/%.o: %.s
mkdir -p $(@D)
$(CC) $(COMMON_CFLAGS) $(CFLAGS) $(EXT_CFLAGS) -o $@ -c $<
$(BUILDDIR)/crc32_test: src/crc32_test.c src/crc32.c
$(HOSTCC) $(HOST_CFLAGS) -o $@ $^
.PHONY: run_tests
run_tests: $(BUILDDIR)/crc32_test
$(PYTHON3) -m unittest test.crc32_ref
venv:
test -d venv || python3 -m venv --system-site-packages venv
source venv/bin/activate && pip install cxxfilt pyelftools libarchive matplotlib

35
prototype/fw/src/crc32.c Normal file
View file

@ -0,0 +1,35 @@
#include "crc32.h"
#include <unistd.h>
/* Polynomial: 0xEDB88320 */
/* python3:
* In [26]: apply = lambda st: ((st>>1) ^ 0xEDB88320) if (st & 1) else (st>>1)
* In [27]: print(',\n'.join([ '0x{:08x}'.format(apply(apply(apply(apply(x))))) for x in range(16) ]))
*/
uint32_t crc32_table[16] = {
0x00000000,
0x1db71064,
0x3b6e20c8,
0x26d930ac,
0x76dc4190,
0x6b6b51f4,
0x4db26158,
0x5005713c,
0xedb88320,
0xf00f9344,
0xd6d6a3e8,
0xcb61b38c,
0x9b64c2b0,
0x86d3d2d4,
0xa00ae278,
0xbdbdf21c
};
crc32_t crc32_update(crc32_t state, uint8_t c)
{
state ^= c;
state = (state>>4) ^ crc32_table[state&0xf];
state = (state>>4) ^ crc32_table[state&0xf];
return state;
}

12
prototype/fw/src/crc32.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef __CRC_32_H__
#define __CRC_32_H__
#include <stdint.h>
typedef uint32_t crc32_t;
inline static uint32_t crc32_reset() { return ~0; }
uint32_t crc32_update(uint32_t old_state, uint8_t c);
inline static uint32_t crc32_finalize(uint32_t state) { return ~state; }
#endif /* __CRC_32_H__ */

View file

@ -0,0 +1,20 @@
#include <stdio.h>
#include "crc32.h"
int main(void) {
crc32_t state = crc32_reset();
do {
char c;
if (fread(&c, 1, 1, stdin) != 1)
break;
state = crc32_update(state, (uint8_t)c);
} while(23);
state = crc32_finalize(state);
printf("%08x\n", state);
return 0;
}

View file

@ -0,0 +1,45 @@
#!/usr/bin/env python3
import subprocess
import zlib
import os
import itertools
import unittest
INTERESTING = bytes([0x00, 0x42, 0xff, 0x01, 0x80])
class RefdataTest(unittest.TestCase):
def run_test(self, test_data):
ref_val = zlib.crc32(test_data)
binary = os.environ.get('CRC32_TEST_BINARY', 'build/crc32_test')
output = subprocess.check_output(binary, input=test_data)
test_val = int(output, 16) & 0xffffffff
self.assertEqual(test_val, ref_val, f'mismatched results checking input {test_data}')
def test_empty(self):
self.run_test(b'')
def test_one_byte(self):
for x in range(256):
self.run_test(bytes([x]))
def test_two_byte(self):
for x, y in itertools.product(INTERESTING, repeat=2):
self.run_test(bytes([x, y]))
def test_three_bytes(self):
for x, y, z in itertools.product(INTERESTING, repeat=3):
self.run_test(bytes([x, y, z]))
def test_four_bytes(self):
for w, x, y, z in itertools.product(INTERESTING, repeat=4):
self.run_test(bytes([w, x, y, z]))
def test_random_strings(self):
for length in range(3, 24):
for i in range(20):
self.run_test(os.urandom(length))

@ -0,0 +1 @@
Subproject commit 77e9717a0e7c5b44214bdf70fbddf376cf2e8a7d