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;
|
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
|
#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] data Start of memory area to checksum
|
||||||
* @param[in] len Number of bytes in @p buf to calculate checksum for
|
* @param[in] len Number of bytes in @p buf to calculate checksum for
|
||||||
* @param[in] poly The generator polynomial for the checksum
|
* @param[in] poly The generator polynomial for the checksum
|
||||||
* @param[in] seed The seed (starting value) for the checksum
|
* @param[in] seed The seed (starting value) for the checksum
|
||||||
*
|
*
|
||||||
* @note Reflected inputs or outputs and final XOR must be realized
|
* @note A final XOR must be realized by the caller if needed.
|
||||||
* by the caller if needed.
|
|
||||||
*
|
*
|
||||||
* @return Checksum of the specified memory area.
|
* @return Checksum of the specified memory area.
|
||||||
*/
|
*/
|
||||||
uint8_t crc8(const uint8_t *data, size_t len, uint8_t poly, uint8_t seed);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
void tests_checksum(void)
|
||||||
{
|
{
|
||||||
TESTS_RUN(tests_checksum_crc8_tests());
|
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_kermit_tests());
|
||||||
TESTS_RUN(tests_checksum_crc16_ccitt_mcrf4xx_tests());
|
TESTS_RUN(tests_checksum_crc16_ccitt_mcrf4xx_tests());
|
||||||
TESTS_RUN(tests_checksum_crc16_ccitt_aug_tests());
|
TESTS_RUN(tests_checksum_crc16_ccitt_aug_tests());
|
||||||
|
|||||||
@ -36,6 +36,13 @@ void tests_checksum(void);
|
|||||||
*/
|
*/
|
||||||
Test *tests_checksum_crc8_tests(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
|
* @brief Generates tests for crc16-ccitt-kermit from checksum/crc16_ccitt.h
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user