ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
crc.h File Reference

Parameterized CRC engine - one source of truth for every cyclic redundancy check. More...

#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Classes

struct  pc_crc_params
 One CRC's full definition (Rocksoft model). See the file comment. More...
 

Namespaces

namespace  pc_crc_detail
 

Functions

uint32_t pc_crc_detail::mask (uint8_t width)
 Mask of width low bits (width 32 handled without a 32-bit shift, which is UB).
 
uint8_t pc_crc_detail::clamp_width (uint8_t width)
 Clamp a register width to the supported 8..32 range.
 
uint8_t pc_crc_detail::rev8 (uint8_t b)
 Reverse the 8 bits of b.
 
uint32_t pc_crc_detail::revN (uint32_t v, uint8_t width)
 Reverse the low width bits of v.
 
uint32_t pc_crc_begin (const pc_crc_params *p)
 Start a CRC.
 
uint32_t pc_crc_update (const pc_crc_params *p, uint32_t crc, const uint8_t *data, size_t len)
 Fold len octets at data into the running register crc.
 
uint32_t pc_crc_final (const pc_crc_params *p, uint32_t crc)
 Finish a CRC: apply the output reflection and the final XOR.
 
uint32_t pc_crc (const pc_crc_params *p, const uint8_t *data, size_t len)
 One-shot CRC of len octets at data.
 

Variables

constexpr pc_crc_params PC_CRC8_SMBUS = {8, 0x07u, 0x00u, false, false, 0x00u}
 CRC-8/SMBUS (a.k.a. CRC-8). check = 0xF4.
 
constexpr pc_crc_params PC_CRC8_MAXIM_DOW = {8, 0x31u, 0x00u, true, true, 0x00u}
 CRC-8/MAXIM-DOW (1-Wire / Dallas). check = 0xA1.
 
constexpr pc_crc_params PC_CRC8_NRSC5 = {8, 0x31u, 0xFFu, false, false, 0x00u}
 CRC-8/NRSC-5 - the Sensirion sensor CRC. check = 0xF7. Used by services/sht3x.
 
constexpr pc_crc_params PC_CRC16_ARC = {16, 0x8005u, 0x0000u, true, true, 0x0000u}
 CRC-16/ARC (a.k.a. CRC-16, IBM). check = 0xBB3D.
 
constexpr pc_crc_params PC_CRC16_MODBUS = {16, 0x8005u, 0xFFFFu, true, true, 0x0000u}
 CRC-16/MODBUS. check = 0x4B37.
 
constexpr pc_crc_params PC_CRC16_IBM_3740 = {16, 0x1021u, 0xFFFFu, false, false, 0x0000u}
 CRC-16/IBM-3740 (often called CCITT-FALSE). check = 0x29B1.
 
constexpr pc_crc_params PC_CRC16_XMODEM = {16, 0x1021u, 0x0000u, false, false, 0x0000u}
 CRC-16/XMODEM. check = 0x31C3.
 
constexpr pc_crc_params PC_CRC16_KERMIT = {16, 0x1021u, 0x0000u, true, true, 0x0000u}
 CRC-16/KERMIT (a.k.a. CRC-16/CCITT, reflected). check = 0x2189.
 
constexpr pc_crc_params PC_CRC16_X25 = {16, 0x1021u, 0xFFFFu, true, true, 0xFFFFu}
 CRC-16/X-25 (HDLC FCS). check = 0x906E. Used by services/radio/thread, mbplus, nema_ts2.
 
constexpr pc_crc_params PC_CRC16_DNP = {16, 0x3D65u, 0x0000u, true, true, 0xFFFFu}
 CRC-16/DNP (DNP3 link-layer block check). check = 0xEA82. Used by services/dnp3.
 
constexpr pc_crc_params PC_CRC24_OPENPGP = {24, 0x864CFBu, 0xB704CEu, false, false, 0x000000u}
 CRC-24/OPENPGP. check = 0x21CF02.
 
constexpr pc_crc_params PC_CRC32_ISO_HDLC = {32, 0x04C11DB7u, 0xFFFFFFFFu, true, true, 0xFFFFFFFFu}
 CRC-32/ISO-HDLC (zlib / PKZIP / Ethernet). check = 0xCBF43926.
 
constexpr pc_crc_params PC_CRC32_BZIP2 = {32, 0x04C11DB7u, 0xFFFFFFFFu, false, false, 0xFFFFFFFFu}
 CRC-32/BZIP2 (unreflected CRC-32). check = 0xFC891918.
 

Detailed Description

Parameterized CRC engine - one source of truth for every cyclic redundancy check.

Sixteen codecs in this tree each hand-rolled their own CRC loop under a different local name, differing only in a polynomial and a couple of flags - the same duplication endian.h was written to end for byte packing. This is that one implementation, and thirteen of them now call it (C37.118, DF1, DNP3, EnOcean, INTERBUS, Modbus, Modbus Plus, NEMA TS2, raw L2, SDI-12, SHT3x, Thread, Zigbee). The three that do not are excluded on purpose, not overlooked: the WAL is table-driven for bulk log throughput, RTCM3's CRC-24Q seed has no preset here yet, and DShot's "CRC" is a 4-bit XOR fold rather than a CRC at all. See the ROADMAP migration entry.

It is the standard Rocksoft / Williams model, so any published CRC is expressible as six numbers and needs no new code:

Every preset below carries its cataloge check value - the CRC of the nine ASCII octets "123456789" - and test_crc asserts each one: a wrong polynomial or a flipped reflect flag cannot reproduce a published check value by accident. test_crc then diffs the engine against the hand-rolled loops themselves, across every length from 0 to 64, so a preset meant to replace one of them is proven byte-identical to the interop-tested code it retires - not merely plausible.

Bitwise, not table-driven: a 256-entry table per polynomial would cost more flash than the frames are worth on this class of device, and every caller here checksums tens to hundreds of octets, not megabytes. Header-only and pure (<stddef.h> / <stdint.h> only), so it is host-testable, identical on device and host, and costs nothing when unused - the same contract as endian.h.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file crc.h.

Function Documentation

◆ pc_crc_begin()

uint32_t pc_crc_begin ( const pc_crc_params p)
inline

Start a CRC.

Returns
the initial register value.

Split from pc_crc_update / pc_crc_final so a caller can checksum a frame that is not contiguous in memory (a header struct then a payload buffer) without copying it together first.

Definition at line 108 of file crc.h.

References pc_crc_params::init, pc_crc_detail::mask(), and pc_crc_params::width.

Referenced by pc_crc().

◆ pc_crc_update()

uint32_t pc_crc_update ( const pc_crc_params p,
uint32_t  crc,
const uint8_t *  data,
size_t  len 
)
inline

Fold len octets at data into the running register crc.

Reflection of the input is applied per octet here; reflection of the output belongs to pc_crc_final, so intermediate values from this function are not meaningful CRCs on their own.

Definition at line 119 of file crc.h.

References pc_crc_detail::clamp_width(), pc_crc_detail::mask(), pc_crc_params::poly, pc_crc_params::refin, pc_crc_detail::rev8(), and pc_crc_params::width.

Referenced by pc_crc().

◆ pc_crc_final()

uint32_t pc_crc_final ( const pc_crc_params p,
uint32_t  crc 
)
inline

Finish a CRC: apply the output reflection and the final XOR.

Definition at line 142 of file crc.h.

References pc_crc_detail::clamp_width(), pc_crc_detail::mask(), pc_crc_params::refout, pc_crc_detail::revN(), pc_crc_params::width, and pc_crc_params::xorout.

Referenced by pc_crc().

◆ pc_crc()

uint32_t pc_crc ( const pc_crc_params p,
const uint8_t *  data,
size_t  len 
)
inline

One-shot CRC of len octets at data.

Definition at line 158 of file crc.h.

References pc_crc_begin(), pc_crc_final(), and pc_crc_update().

Variable Documentation

◆ PC_CRC8_SMBUS

constexpr pc_crc_params PC_CRC8_SMBUS = {8, 0x07u, 0x00u, false, false, 0x00u}
constexpr

CRC-8/SMBUS (a.k.a. CRC-8). check = 0xF4.

Definition at line 173 of file crc.h.

◆ PC_CRC8_MAXIM_DOW

constexpr pc_crc_params PC_CRC8_MAXIM_DOW = {8, 0x31u, 0x00u, true, true, 0x00u}
constexpr

CRC-8/MAXIM-DOW (1-Wire / Dallas). check = 0xA1.

Definition at line 175 of file crc.h.

◆ PC_CRC8_NRSC5

constexpr pc_crc_params PC_CRC8_NRSC5 = {8, 0x31u, 0xFFu, false, false, 0x00u}
constexpr

CRC-8/NRSC-5 - the Sensirion sensor CRC. check = 0xF7. Used by services/sht3x.

Definition at line 177 of file crc.h.

◆ PC_CRC16_ARC

constexpr pc_crc_params PC_CRC16_ARC = {16, 0x8005u, 0x0000u, true, true, 0x0000u}
constexpr

CRC-16/ARC (a.k.a. CRC-16, IBM). check = 0xBB3D.

Definition at line 180 of file crc.h.

◆ PC_CRC16_MODBUS

constexpr pc_crc_params PC_CRC16_MODBUS = {16, 0x8005u, 0xFFFFu, true, true, 0x0000u}
constexpr

CRC-16/MODBUS. check = 0x4B37.

Definition at line 182 of file crc.h.

◆ PC_CRC16_IBM_3740

constexpr pc_crc_params PC_CRC16_IBM_3740 = {16, 0x1021u, 0xFFFFu, false, false, 0x0000u}
constexpr

CRC-16/IBM-3740 (often called CCITT-FALSE). check = 0x29B1.

Definition at line 184 of file crc.h.

◆ PC_CRC16_XMODEM

constexpr pc_crc_params PC_CRC16_XMODEM = {16, 0x1021u, 0x0000u, false, false, 0x0000u}
constexpr

CRC-16/XMODEM. check = 0x31C3.

Definition at line 186 of file crc.h.

◆ PC_CRC16_KERMIT

constexpr pc_crc_params PC_CRC16_KERMIT = {16, 0x1021u, 0x0000u, true, true, 0x0000u}
constexpr

CRC-16/KERMIT (a.k.a. CRC-16/CCITT, reflected). check = 0x2189.

Definition at line 188 of file crc.h.

◆ PC_CRC16_X25

constexpr pc_crc_params PC_CRC16_X25 = {16, 0x1021u, 0xFFFFu, true, true, 0xFFFFu}
constexpr

CRC-16/X-25 (HDLC FCS). check = 0x906E. Used by services/radio/thread, mbplus, nema_ts2.

Definition at line 190 of file crc.h.

◆ PC_CRC16_DNP

constexpr pc_crc_params PC_CRC16_DNP = {16, 0x3D65u, 0x0000u, true, true, 0xFFFFu}
constexpr

CRC-16/DNP (DNP3 link-layer block check). check = 0xEA82. Used by services/dnp3.

Definition at line 192 of file crc.h.

◆ PC_CRC24_OPENPGP

constexpr pc_crc_params PC_CRC24_OPENPGP = {24, 0x864CFBu, 0xB704CEu, false, false, 0x000000u}
constexpr

CRC-24/OPENPGP. check = 0x21CF02.

Definition at line 195 of file crc.h.

◆ PC_CRC32_ISO_HDLC

constexpr pc_crc_params PC_CRC32_ISO_HDLC = {32, 0x04C11DB7u, 0xFFFFFFFFu, true, true, 0xFFFFFFFFu}
constexpr

CRC-32/ISO-HDLC (zlib / PKZIP / Ethernet). check = 0xCBF43926.

Definition at line 198 of file crc.h.

◆ PC_CRC32_BZIP2

constexpr pc_crc_params PC_CRC32_BZIP2 = {32, 0x04C11DB7u, 0xFFFFFFFFu, false, false, 0xFFFFFFFFu}
constexpr

CRC-32/BZIP2 (unreflected CRC-32). check = 0xFC891918.

Definition at line 200 of file crc.h.