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 <mlhx@google.com>
diff --git a/include/crc7.h b/include/crc7.h
new file mode 100644
index 0000000..7164d31
--- /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 <zephyr/types.h>
+#include <stddef.h>
+
+#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 7cc1f2c..29ae1e4 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 0000000..b02f176
--- /dev/null
+++ b/lib/crc/crc7_sw.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2018 Google LLC.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <crc7.h>
+
+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 c680894..f6bf0cb 100644
--- a/tests/unit/lib/crc/main.c
+++ b/tests/unit/lib/crc/main.c
@@ -9,6 +9,7 @@
#include <lib/crc/crc32_sw.c>
#include <lib/crc/crc16_sw.c>
#include <lib/crc/crc8_sw.c>
+#include <lib/crc/crc7_sw.c>
void test_crc32_ieee(void)
{
@@ -109,6 +110,17 @@
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 @@
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);
}