mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-12-16 18:13:49 +01:00
Merge pull request #21543 from crasbe/pr/crc8_refl
sys/checksum: Add LSB-first (reflected) CRC8 Function
This commit is contained in:
commit
42a38240a2
@ -39,4 +39,21 @@ uint8_t crc8(const uint8_t *data, size_t len, uint8_t g_polynom, uint8_t crc)
|
||||
return crc;
|
||||
}
|
||||
|
||||
uint8_t crc8_lsb(const uint8_t *data, size_t len, uint8_t g_polynom, uint8_t crc)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
crc ^= data[i];
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
bool xor = crc & 0x01;
|
||||
crc = crc >> 1;
|
||||
crc = xor ? crc ^ g_polynom : crc;
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
33
sys/checksum/doc.md
Normal file
33
sys/checksum/doc.md
Normal file
@ -0,0 +1,33 @@
|
||||
<!--
|
||||
Copyright 2016 Freie Universität Berlin
|
||||
Copyright 2016 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
||||
|
||||
This file is subject to the terms and conditions of the GNU Lesser
|
||||
General Public License v2.1. See the file LICENSE in the top level
|
||||
directory for more details.
|
||||
-->
|
||||
|
||||
@defgroup sys_checksum Checksum
|
||||
@ingroup sys_hashes
|
||||
@brief Checksum function libraries
|
||||
|
||||
This module provides a number of checksum functions. Most notably is the
|
||||
@ref sys_checksum_crc16_ccitt and the @ref sys_checksum_ucrc16 modules which
|
||||
provide support for the CRC16 checksum.
|
||||
|
||||
@ref sys_checksum_crc16_ccitt only provides an implementation of the CCITT
|
||||
flavor of CRC16 (polynomial @$ x^{16} + x^{12} + x^{5} + 1 @$) for big-endian
|
||||
numbers with starting seed `0x1d0f` (though others can be provided), while
|
||||
@ref sys_checksum_ucrc16 is more generalized, since it takes the
|
||||
hexadecimal representation of the polynomial as a parameter and provides
|
||||
functions and standardized polynomials for both big- and little-endian
|
||||
numbers.
|
||||
|
||||
The caveat of @ref sys_checksum_ucrc16 is that it is significantly slower
|
||||
(approximately factor 8) than @ref sys_checksum_crc16_ccitt since the latter
|
||||
is able to calculate the checksum byte-wise, while the first calculates
|
||||
needs to calculate it bit-wise. @ref sys_checksum_crc16_ccitt achieves this
|
||||
advantage by using a look-up table that provides the checksum for every
|
||||
possible byte-value. It thus trades of memory against speed. If your
|
||||
platform is rather small equipped in memory you should prefer the
|
||||
@ref sys_checksum_ucrc16 version.
|
||||
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Freie Universität Berlin
|
||||
* Copyright 2016 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup sys_checksum Checksum
|
||||
* @ingroup sys_hashes
|
||||
* @brief Checksum function libraries
|
||||
*
|
||||
* This module provides a number of checksum functions. Most notably is the
|
||||
* @ref sys_checksum_crc16_ccitt and the @ref sys_checksum_ucrc16 modules which
|
||||
* provide support for the CRC16 checksum.
|
||||
*
|
||||
* @ref sys_checksum_crc16_ccitt only provides an implementation of the CCITT
|
||||
* flavor of CRC16 (polynomial @$ x^{16} + x^{12} + x^{5} + 1 @$) for big-endian
|
||||
* numbers with starting seed `0x1d0f` (though others can be provided), while
|
||||
* @ref sys_checksum_ucrc16 is more generalized, since it takes the
|
||||
* hexadecimal representation of the polynomial as a parameter and provides
|
||||
* functions and standardized polynomials for both big- and little-endian
|
||||
* numbers.
|
||||
*
|
||||
* The caveat of @ref sys_checksum_ucrc16 is that it is significantly slower
|
||||
* (approximately factor 8) than @ref sys_checksum_crc16_ccitt since the latter
|
||||
* is able to calculate the checksum byte-wise, while the first calculates
|
||||
* needs to calculate it bit-wise. @ref sys_checksum_crc16_ccitt achieves this
|
||||
* advantage by using a look-up table that provides the checksum for every
|
||||
* possible byte-value. It thus trades of memory against speed. If your
|
||||
* platform is rather small equipped in memory you should prefer the
|
||||
* @ref sys_checksum_ucrc16 version.
|
||||
*/
|
||||
@ -29,20 +29,37 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Calculate CRC-8
|
||||
* @brief Calculate CRC-8 (MSB first)
|
||||
*
|
||||
* This CRC8 checksum type is usually more common.
|
||||
*
|
||||
* @param[in] data Start of memory area to checksum
|
||||
* @param[in] len Number of bytes in @p buf to calculate checksum for
|
||||
* @param[in] poly The generator polynomial for the checksum
|
||||
* @param[in] seed The seed (starting value) for the checksum
|
||||
*
|
||||
* @note Reflected inputs or outputs and final XOR must be realized
|
||||
* by the caller if needed.
|
||||
* @note A final XOR must be realized by the caller if needed.
|
||||
*
|
||||
* @return Checksum of the specified memory area.
|
||||
*/
|
||||
uint8_t crc8(const uint8_t *data, size_t len, uint8_t poly, uint8_t seed);
|
||||
|
||||
/**
|
||||
* @brief Calculate a reflected CRC-8 (LSB first)
|
||||
*
|
||||
* This CRC8 checksum type is used for example by Onewire.
|
||||
*
|
||||
* @param[in] data Start of memory area to checksum
|
||||
* @param[in] len Number of bytes in @p buf to calculate checksum for
|
||||
* @param[in] poly The generator polynomial for the checksum
|
||||
* @param[in] seed The seed (starting value) for the checksum
|
||||
*
|
||||
* @note A final XOR must be realized by the caller if needed.
|
||||
*
|
||||
* @return Checksum of the specified memory area.
|
||||
*/
|
||||
uint8_t crc8_lsb(const uint8_t *data, size_t len, uint8_t poly, uint8_t seed);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
91
tests/unittests/tests-checksum/tests-checksum-crc8-lsb.c
Normal file
91
tests/unittests/tests-checksum/tests-checksum-crc8-lsb.c
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2019 Benjamin Valentin <benpicco@googlemail.com>
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "embUnit/embUnit.h"
|
||||
|
||||
#include "checksum/crc8.h"
|
||||
|
||||
#include "tests-checksum.h"
|
||||
|
||||
#define CRC8_POLY 0x31
|
||||
#define CRC8_INIT 0xff
|
||||
|
||||
static void test_checksum_crc8_lsb_sequence_empty(void)
|
||||
{
|
||||
unsigned char buf[] = "";
|
||||
uint8_t expect = 0xFF;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(expect, crc8_lsb(buf, sizeof(buf) - 1, CRC8_POLY, CRC8_INIT));
|
||||
}
|
||||
|
||||
static void test_checksum_crc8_lsb_sequence_1a(void)
|
||||
{
|
||||
unsigned char buf[] = "A";
|
||||
uint8_t expect = 0x0F;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(expect, crc8_lsb(buf, sizeof(buf) - 1, CRC8_POLY, CRC8_INIT));
|
||||
}
|
||||
|
||||
static void test_checksum_crc8_lsb_sequence_256a(void)
|
||||
{
|
||||
unsigned char buf[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||||
uint8_t expect = 0x0F;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(expect, crc8_lsb(buf, sizeof(buf) - 1, CRC8_POLY, CRC8_INIT));
|
||||
}
|
||||
|
||||
static void test_checksum_crc8_lsb_sequence_1to9(void)
|
||||
{
|
||||
unsigned char buf[] = "123456789";
|
||||
uint8_t expect = 0x20;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(expect, crc8_lsb(buf, sizeof(buf) - 1, CRC8_POLY, CRC8_INIT));
|
||||
}
|
||||
|
||||
static void test_checksum_crc8_lsb_sequence_4bytes(void)
|
||||
{
|
||||
unsigned char buf[] = { 0x12, 0x34, 0x56, 0x78 };
|
||||
uint8_t expect = 0x1C;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(expect, crc8_lsb(buf, sizeof(buf), CRC8_POLY, CRC8_INIT));
|
||||
}
|
||||
|
||||
static void test_checksum_crc8_lsb_onewire_params(void)
|
||||
{
|
||||
unsigned char buf[] = { 0x2A };
|
||||
uint8_t expect = 0x5D;
|
||||
|
||||
TEST_ASSERT_EQUAL_INT(expect, crc8_lsb(buf, sizeof(buf), 0x8C, 0x00));
|
||||
}
|
||||
|
||||
Test *tests_checksum_crc8_lsb_tests(void)
|
||||
{
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
/* Reference values according to
|
||||
* http://srecord.sourceforge.net/crc16-ccitt.html */
|
||||
new_TestFixture(test_checksum_crc8_lsb_sequence_empty),
|
||||
new_TestFixture(test_checksum_crc8_lsb_sequence_1a),
|
||||
new_TestFixture(test_checksum_crc8_lsb_sequence_256a),
|
||||
new_TestFixture(test_checksum_crc8_lsb_sequence_1to9),
|
||||
new_TestFixture(test_checksum_crc8_lsb_sequence_4bytes),
|
||||
new_TestFixture(test_checksum_crc8_lsb_onewire_params),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(checksum_crc8_lsb_tests, NULL, NULL, fixtures);
|
||||
|
||||
return (Test *)&checksum_crc8_lsb_tests;
|
||||
}
|
||||
@ -11,6 +11,7 @@
|
||||
void tests_checksum(void)
|
||||
{
|
||||
TESTS_RUN(tests_checksum_crc8_tests());
|
||||
TESTS_RUN(tests_checksum_crc8_lsb_tests());
|
||||
TESTS_RUN(tests_checksum_crc16_ccitt_kermit_tests());
|
||||
TESTS_RUN(tests_checksum_crc16_ccitt_mcrf4xx_tests());
|
||||
TESTS_RUN(tests_checksum_crc16_ccitt_aug_tests());
|
||||
|
||||
@ -36,6 +36,13 @@ void tests_checksum(void);
|
||||
*/
|
||||
Test *tests_checksum_crc8_tests(void);
|
||||
|
||||
/**
|
||||
* @brief Generates tests for checksum/crc8_lsb.h
|
||||
*
|
||||
* @return embUnit tests if successful, NULL if not.
|
||||
*/
|
||||
Test *tests_checksum_crc8_lsb_tests(void);
|
||||
|
||||
/**
|
||||
* @brief Generates tests for crc16-ccitt-kermit from checksum/crc16_ccitt.h
|
||||
*
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user