diff --git a/include/sys/crc.h b/include/sys/crc.h index bf579789b89..d088ad57876 100644 --- a/include/sys/crc.h +++ b/include/sys/crc.h @@ -55,6 +55,24 @@ extern "C" { u16_t crc16(const u8_t *src, size_t len, u16_t polynomial, u16_t initial_value, bool pad); +/** + * @brief Generic function for computing CRC 8 + * + * Compute CRC 8 by passing in the address of the input, the input length + * and polynomial used in addition to the initial value. + * + * @param src Input bytes for the computation + * @param len Length of the input in bytes + * @param polynomial The polynomial to use omitting the leading x^8 + * coefficient + * @param initial_value Initial value for the CRC computation + * @param reversed Should we use reflected/reversed values or not + * + * @return The computed CRC8 value + */ +u8_t crc8(const u8_t *src, size_t len, u8_t polynomial, u8_t initial_value, + bool reversed); + /** * @brief Compute the CRC-16/CCITT checksum of a buffer. * diff --git a/lib/os/crc8_sw.c b/lib/os/crc8_sw.c index 3c4f30d357f..8c6d32c93fe 100644 --- a/lib/os/crc8_sw.c +++ b/lib/os/crc8_sw.c @@ -1,4 +1,5 @@ /* + * Copyright (c) 2020 Intel Corporation * Copyright (c) 2017 Nordic Semiconductor ASA * Copyright (c) 2015 Runtime Inc * @@ -24,3 +25,32 @@ u8_t crc8_ccitt(u8_t val, const void *buf, size_t cnt) } return val; } + +u8_t crc8(const u8_t *src, size_t len, u8_t polynomial, u8_t initial_value, + bool reversed) +{ + u8_t crc = initial_value; + size_t i, j; + + for (i = 0; i < len; i++) { + crc ^= src[i]; + + for (j = 0; j < 8; j++) { + if (reversed) { + if (crc & 0x01) { + crc = (crc >> 1) ^ polynomial; + } else { + crc >>= 1; + } + } else { + if (crc & 0x80) { + crc = (crc << 1) ^ polynomial; + } else { + crc <<= 1; + } + } + } + } + + return crc; +} diff --git a/tests/unit/crc/main.c b/tests/unit/crc/main.c index 0f50946d87a..2294ed48140 100644 --- a/tests/unit/crc/main.c +++ b/tests/unit/crc/main.c @@ -122,6 +122,86 @@ void test_crc7_be(void) zassert_equal(crc7_be(0, test2, sizeof(test2)), 0xEA, NULL); } +void test_crc8(void) +{ + u8_t fcs, expected; + + u8_t test0[] = { 0x00 }; + u8_t test1[] = { 0xBE, 0xEF }; + u8_t test2[] = { 0x07, 0x3F }; /* GSM 07.10 example */ + u8_t test3[] = { 0x07, 0x3F, 0x89 }; /* GSM 07.10 example */ + u8_t test4[] = { 0x03, 0x02, 0x0A, 0x38, 0x17, 0x00 }; + u8_t test5[] = { 0x03, 0x3f, 0x01, 0x1c }; /* Our GSM 07.10 calc */ + + fcs = crc8(test0, sizeof(test0), 0x00, 0x00, false); + expected = 0x00; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test0, sizeof(test0), 0x31, 0x00, false); + expected = 0x00; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test1, sizeof(test1), 0x07, 0x00, false); + expected = 0x1a; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test1, sizeof(test1), 0x31, 0xff, false); + expected = 0x92; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test1, sizeof(test1), 0x07, 0x00, false); + expected = 0x1a; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test2, sizeof(test2), 0x31, 0x00, false); + expected = 0x45; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test2, sizeof(test2), 0x31, 0xff, false); + expected = 0xc4; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test2, sizeof(test2), 0x07, 0x00, false); + expected = 0xd6; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test2, sizeof(test2), 0x07, 0xff, false); + expected = 0x01; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test2, sizeof(test2), 0xe0, 0xff, true); + expected = 0x76; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test3, sizeof(test3), 0xe0, 0xff, true); + expected = 0xcf; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test3, sizeof(test3), 0x07, 0xff, false); + expected = 0xb1; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test4, sizeof(test4), 0x31, 0x00, false); + expected = 0x3a; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test4, sizeof(test4), 0x07, 0x00, false); + expected = 0xaf; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test4, sizeof(test4), 0x9b, 0xff, false); + expected = 0xf0; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test4, sizeof(test4), 0x1d, 0xfd, false); + expected = 0x49; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); + + fcs = crc8(test5, sizeof(test5), 0xe0, 0xff, true); + expected = 0xcf; + zassert_equal(fcs, expected, "0x%02x vs 0x%02x", fcs, expected); +} + void test_main(void) { ztest_test_suite(test_crc, @@ -132,6 +212,7 @@ void test_main(void) ztest_unit_test(test_crc16_ccitt_for_ppp), ztest_unit_test(test_crc16_itu_t), ztest_unit_test(test_crc8_ccitt), - ztest_unit_test(test_crc7_be)); + ztest_unit_test(test_crc7_be), + ztest_unit_test(test_crc8)); ztest_run_test_suite(test_crc); }