From 531b2e8f52bebb9eb4a6f0c3521c23469c40b2c7 Mon Sep 17 00:00:00 2001 From: Daniel Peter Chokola Date: Tue, 21 Apr 2020 05:55:23 -0400 Subject: [PATCH] Generate CRC LUT and test CRC calculation against reference implementation using a golden packet. --- Makefile | 9 +++++ crc.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 Makefile create mode 100644 crc.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c6c394e --- /dev/null +++ b/Makefile @@ -0,0 +1,9 @@ +CC=gcc +OBJ=crc.o +CFLAGS=-Wall -Wextra -Werror -pedantic + +%.o: %.c $(DEPS) + $(CC) -c -o $@ $< $(CFLAGS) + +crc: $(OBJ) + $(CC) -o $@ $^ $(CFLAGS) \ No newline at end of file diff --git a/crc.c b/crc.c new file mode 100644 index 0000000..4bbe123 --- /dev/null +++ b/crc.c @@ -0,0 +1,117 @@ +/* + * crc.c - reference CRC implementations and LUT generator + */ + +#include +#include + +/* + * CRC-16-IBM -- reversed reciprocal representation + * https://en.wikipedia.org/wiki/Cyclic_redundancy_check#Polynomial_representations_of_cyclic_redundancy_checks + */ +#define CRCPOLY (0xc002) + +static uint16_t crc16_lut[256] = { 0x0000 }; + +uint16_t crc16(uint8_t *data, uint32_t len); +void crc16_gen(); +uint16_t crc16_ref(uint8_t *Pkt, uint32_t PktCnt); + +int main() +{ + uint8_t i; + uint8_t golden_packet[32] = { + 0xf2, 0x22, 0x22, 0x22, + 0x20, 0x00, 0x00, 0x00, + 0x78, 0x56, 0x34, 0x12, + 0xd2, 0xc3, 0xb4, 0xa5, + 0x10, 0x00, 0x00, 0x00, + 0x01, 0x5a, 0x00, 0x00, + 0x42, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x00, 0x00 + }; + + /* generate lookup table */ + crc16_gen(); + + /* print out the table (for embedding into code data sections) */ + printf("CRC byte lookup table:\n0x0000"); + for(i = 0; i < 255; i++) + { + printf(", 0x%04x", crc16_lut[i + 1]); + } + printf("\n\n"); + + /* compute the golden checksum using the LUT and a reference algorithm */ + printf("Golden Checksum: 0x%04x\n", crc16(golden_packet, 32)); + printf("Reference Golden Checksum: 0x%04x\n", crc16_ref(golden_packet, 32)); + + return(0); +} + +/* fast CRC calculation using LUT */ +uint16_t crc16(uint8_t *data, uint32_t len) +{ + uint32_t i; + uint16_t rem = 0; + + for (i = 0; i < len; i++) + { + rem = (rem >> 8) ^ crc16_lut[data[i] ^ (rem & 0xff)]; + } + + return(rem); +} + +/* fast CRC LUT generation */ +void crc16_gen() +{ + uint16_t crc = 1; + uint8_t i; + uint16_t j; + + for(i = 0x80; i > 0; i >>= 1) + { + if(crc & 1) + { + crc = (crc >> 1) ^ CRCPOLY; + } + else + { + crc >>= 1; + } + + for(j = 0; j < 256; j += 2 * i) + { + crc16_lut[i + j] = crc ^ crc16_lut[j]; + } + } +} + +/* reference CRC implementation */ +uint16_t crc16_ref(uint8_t *buf, uint32_t len) +{ + uint16_t rem = 0; + uint16_t dat; + uint16_t tmp; + uint32_t i, j; + + for(i = 0; i < len; i++) + { + dat = buf[i]; + for(j = 0; j < 8; j++) + { + tmp = (rem ^ dat) & 0x0001; + + rem >>= 1; + dat >>= 1; + + if(tmp) + { + rem ^= CRCPOLY; + } + } + } + + return(rem); +}