Skip to content

Commit ec5354c

Browse files
ndrs-pstaescolar
authored andcommitted
lib: crc: add crc8_rohc for CRC-8/ROHC variant calculation
This commit introduces the `crc8_rohc` function to the CRC library, implementing the CRC-8/ROHC (RObust Header Compression) variant. This algorithm is widely used in networking protocols, which is commonly found in modem subsystems. Signed-off-by: Pisit Sawangvonganan <[email protected]>
1 parent 339ba1a commit ec5354c

File tree

4 files changed

+64
-4
lines changed

4 files changed

+64
-4
lines changed

include/zephyr/sys/crc.h

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern "C" {
2929
* computation.
3030
*/
3131
#define CRC8_CCITT_INITIAL_VALUE 0xFF
32+
#define CRC8_ROHC_INITIAL_VALUE 0xFF
3233

3334
/* Initial value expected to be used at the beginning of the OpenPGP CRC-24 computation. */
3435
#define CRC24_PGP_INITIAL_VALUE 0x00B704CEU
@@ -58,9 +59,10 @@ enum crc_type {
5859
CRC4, /**< Use @ref crc4 */
5960
CRC4_TI, /**< Use @ref crc4_ti */
6061
CRC7_BE, /**< Use @ref crc7_be */
61-
CRC8, /**< Use @ref crc8 */
62+
CRC8, /**< Use @ref crc8 */
6263
CRC8_CCITT, /**< Use @ref crc8_ccitt */
63-
CRC16, /**< Use @ref crc16 */
64+
CRC8_ROHC, /**< Use @ref crc8_rohc */
65+
CRC16, /**< Use @ref crc16 */
6466
CRC16_ANSI, /**< Use @ref crc16_ansi */
6567
CRC16_CCITT, /**< Use @ref crc16_ccitt */
6668
CRC16_ITU_T, /**< Use @ref crc16_itu_t */
@@ -135,7 +137,7 @@ uint16_t crc16_reflect(uint16_t poly, uint16_t seed, const uint8_t *src, size_t
135137
* @return The computed CRC8 value
136138
*/
137139
uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
138-
bool reversed);
140+
bool reversed);
139141

140142
/**
141143
* @brief Compute the checksum of a buffer with polynomial 0x1021, reflecting
@@ -274,6 +276,20 @@ uint32_t crc32_c(uint32_t crc, const uint8_t *data,
274276
*/
275277
uint8_t crc8_ccitt(uint8_t initial_value, const void *buf, size_t len);
276278

279+
/**
280+
* @brief Compute ROHC variant of CRC 8
281+
*
282+
* ROHC (Robust Header Compression) variant of CRC 8.
283+
* Uses 0x07 as the polynomial with reflection.
284+
*
285+
* @param initial_value Initial value for the CRC computation
286+
* @param buf Input bytes for the computation
287+
* @param len Length of the input in bytes
288+
*
289+
* @return The computed CRC8 value
290+
*/
291+
uint8_t crc8_rohc(uint8_t initial_value, const void *buf, size_t len);
292+
277293
/**
278294
* @brief Compute the CRC-7 checksum of a buffer.
279295
*
@@ -322,7 +338,7 @@ uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len);
322338
* @return The computed CRC4 value
323339
*/
324340
uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
325-
bool reversed);
341+
bool reversed);
326342

327343
/**
328344
* @brief Generate an OpenPGP CRC-24 checksum as defined in RFC 4880 section 6.1.
@@ -384,6 +400,8 @@ static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_
384400
return crc8(src, len, poly, seed, reflect);
385401
case CRC8_CCITT:
386402
return crc8_ccitt(seed, src, len);
403+
case CRC8_ROHC:
404+
return crc8_rohc(seed, src, len);
387405
case CRC16:
388406
if (reflect) {
389407
return crc16_reflect(poly, seed, src, len);

lib/crc/crc8_sw.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ static const uint8_t crc8_ccitt_small_table[16] = {
1313
0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d
1414
};
1515

16+
static const uint8_t crc8_rohc_small_table[16] = {
17+
0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54,
18+
0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4
19+
};
20+
1621
uint8_t crc8_ccitt(uint8_t val, const void *buf, size_t cnt)
1722
{
1823
size_t i;
@@ -26,6 +31,19 @@ uint8_t crc8_ccitt(uint8_t val, const void *buf, size_t cnt)
2631
return val;
2732
}
2833

34+
uint8_t crc8_rohc(uint8_t val, const void *buf, size_t cnt)
35+
{
36+
size_t i;
37+
const uint8_t *p = buf;
38+
39+
for (i = 0; i < cnt; i++) {
40+
val ^= p[i];
41+
val = (val >> 4) ^ crc8_rohc_small_table[val & 0x0f];
42+
val = (val >> 4) ^ crc8_rohc_small_table[val & 0x0f];
43+
}
44+
return val;
45+
}
46+
2947
uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
3048
bool reversed)
3149
{

lib/crc/crc_shell.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ static const char *const crc_types[] = {
2424
[CRC7_BE] = "7_be",
2525
[CRC8] = "8",
2626
[CRC8_CCITT] = "8_ccitt",
27+
[CRC8_ROHC] = "8_rohc",
2728
[CRC16] = "16",
2829
[CRC16_ANSI] = "16_ansi",
2930
[CRC16_CCITT] = "16_ccitt",

tests/unit/crc/main.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,29 @@ ZTEST(crc, test_crc8_ccitt)
187187
sizeof(test2)) == 0xFB, "pass", "fail");
188188
}
189189

190+
ZTEST(crc, test_crc8_rohc)
191+
{
192+
uint8_t test0[] = { 0 };
193+
uint8_t test1[] = { 'A' };
194+
uint8_t test2[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
195+
uint8_t test3[] = { 0x07, 0x3F }; /* GSM 07.10 example */
196+
uint8_t test4[] = { 0x07, 0x3F, 0x89 }; /* GSM 07.10 example */
197+
uint8_t test5[] = { 0x03, 0x3f, 0x01, 0x1c }; /* Our GSM 07.10 calc */
198+
199+
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test0,
200+
sizeof(test0)) == 0xcf, "pass", "fail");
201+
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test1,
202+
sizeof(test1)) == 0x2e, "pass", "fail");
203+
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test2,
204+
sizeof(test2)) == 0xd0, "pass", "fail");
205+
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test3,
206+
sizeof(test3)) == 0x76, "pass", "fail");
207+
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test4,
208+
sizeof(test4)) == 0xcf, "pass", "fail");
209+
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test5,
210+
sizeof(test5)) == 0xcf, "pass", "fail");
211+
}
212+
190213
ZTEST(crc, test_crc7_be)
191214
{
192215
uint8_t test0[] = { 0 };

0 commit comments

Comments
 (0)