From bbafc36b1cca944f738e44d5efa3d2a41b7f43a6 Mon Sep 17 00:00:00 2001 From: Michael Hope Date: Sun, 11 Feb 2018 18:07:39 +0100 Subject: [PATCH] lib: add crc7. Used as a checksum on command messages when talking with MMC cards. Implemented using the unwound bytewise implementation from https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks which is a good mix of size and speed. The API and naming matches lib/crc7.c in Linux. Signed-off-by: Michael Hope --- include/crc7.h | 36 ++++++++++++++++++++++++++++++++++++ lib/crc/CMakeLists.txt | 2 +- lib/crc/crc7_sw.c | 19 +++++++++++++++++++ tests/unit/lib/crc/main.c | 15 ++++++++++++++- 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 include/crc7.h create mode 100644 lib/crc/crc7_sw.c diff --git a/include/crc7.h b/include/crc7.h new file mode 100644 index 00000000000..7164d31e830 --- /dev/null +++ b/include/crc7.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018 Google LLC. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __CRC7_H_ +#define __CRC7_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Compute the CRC-7 checksum of a buffer. + * + * See JESD84-A441. Used by the MMC protocol. Uses 0x09 as the + * polynomial with no reflection. The CRC is left + * justified, so bit 7 of the result is bit 6 of the CRC. + * + * @param seed Value to seed the CRC with + * @param src Input bytes for the computation + * @param len Length of the input in bytes + * + * @return The computed CRC7 value + */ +u8_t crc7_be(u8_t seed, const u8_t *src, size_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/crc/CMakeLists.txt b/lib/crc/CMakeLists.txt index 7cc1f2ca77e..29ae1e4093e 100644 --- a/lib/crc/CMakeLists.txt +++ b/lib/crc/CMakeLists.txt @@ -1 +1 @@ -zephyr_sources(crc32_sw.c crc16_sw.c crc8_sw.c) +zephyr_sources(crc32_sw.c crc16_sw.c crc8_sw.c crc7_sw.c) diff --git a/lib/crc/crc7_sw.c b/lib/crc/crc7_sw.c new file mode 100644 index 00000000000..b02f1769991 --- /dev/null +++ b/lib/crc/crc7_sw.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018 Google LLC. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +u8_t crc7_be(u8_t seed, const u8_t *src, size_t len) +{ + while (len--) { + u8_t e = seed ^ *src++; + u8_t f = e ^ (e >> 4) ^ (e >> 7); + + seed = (f << 1) ^ (f << 4); + } + + return seed; +} diff --git a/tests/unit/lib/crc/main.c b/tests/unit/lib/crc/main.c index c680894477e..f6bf0cb42a5 100644 --- a/tests/unit/lib/crc/main.c +++ b/tests/unit/lib/crc/main.c @@ -9,6 +9,7 @@ #include #include #include +#include void test_crc32_ieee(void) { @@ -109,6 +110,17 @@ void test_crc8_ccitt(void) sizeof(test2)) == 0xFB, "pass", "fail"); } +void test_crc7_be(void) +{ + u8_t test0[] = { 0 }; + u8_t test1[] = { 'A' }; + u8_t test2[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' }; + + zassert_equal(crc7_be(0, test0, sizeof(test0)), 0, NULL); + zassert_equal(crc7_be(0, test1, sizeof(test1)), 0xDA, NULL); + zassert_equal(crc7_be(0, test2, sizeof(test2)), 0xEA, NULL); +} + void test_main(void) { ztest_test_suite(test_crc, @@ -118,6 +130,7 @@ void test_main(void) ztest_unit_test(test_crc16_ccitt), 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_crc8_ccitt), + ztest_unit_test(test_crc7_be)); ztest_run_test_suite(test_crc); }