mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
ucrc16: provide lightweight CRC16 implementation
This commit is contained in:
parent
b61ae80da1
commit
107bf0ae63
@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2016 Freie Universität Berlin
|
||||||
* Copyright 2016 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
* Copyright 2016 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU Lesser
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
@ -10,4 +11,24 @@
|
|||||||
* @defgroup sys_checksum Checksum
|
* @defgroup sys_checksum Checksum
|
||||||
* @ingroup sys
|
* @ingroup sys
|
||||||
* @brief Checksum function libraries
|
* @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 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.
|
||||||
*/
|
*/
|
||||||
|
53
sys/checksum/ucrc16.c
Normal file
53
sys/checksum/ucrc16.c
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
#include "checksum/ucrc16.h"
|
||||||
|
|
||||||
|
#define UINT8_BIT_SIZE (8U)
|
||||||
|
#define UINT16_BIT_SIZE (16U)
|
||||||
|
#define LEFTMOST_BIT_SET(value) ((value) & 0x8000U)
|
||||||
|
#define RIGHTMOST_BIT_SET(value) ((value) & 0x0001U)
|
||||||
|
|
||||||
|
uint16_t ucrc16_calc_be(const uint8_t *buf, size_t len, uint16_t poly,
|
||||||
|
uint16_t seed)
|
||||||
|
{
|
||||||
|
assert(buf != NULL);
|
||||||
|
for (unsigned c = 0; c < len; c++, buf++) {
|
||||||
|
uint32_t tmp = seed ^ (*buf << (UINT16_BIT_SIZE - UINT8_BIT_SIZE));
|
||||||
|
for (unsigned i = 0; i < UINT8_BIT_SIZE; i++) {
|
||||||
|
tmp = LEFTMOST_BIT_SET(tmp) ? ((tmp << 1) ^ poly) : (tmp << 1);
|
||||||
|
}
|
||||||
|
seed = tmp & UINT16_MAX;
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ucrc16_calc_le(const uint8_t *buf, size_t len, uint16_t poly,
|
||||||
|
uint16_t seed)
|
||||||
|
{
|
||||||
|
assert(buf != NULL);
|
||||||
|
for (unsigned c = 0; c < len; c++, buf++) {
|
||||||
|
seed ^= (*buf);
|
||||||
|
for (unsigned i = 0; i < UINT8_BIT_SIZE; i++) {
|
||||||
|
seed = RIGHTMOST_BIT_SET(seed) ? ((seed >> 1) ^ poly) : (seed >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @} */
|
@ -17,6 +17,11 @@
|
|||||||
* crc16_ccitt_update() with the desired start value
|
* crc16_ccitt_update() with the desired start value
|
||||||
* instead of crc16_ccitt_calc().
|
* instead of crc16_ccitt_calc().
|
||||||
*
|
*
|
||||||
|
* There is a more generalized version in @ref sys_checksum_ucrc16,
|
||||||
|
* that does not utilize a look-up table as this implementation
|
||||||
|
* does (and is thus also for more memory efficient). Its caveat
|
||||||
|
* however is that it is slower by about factor 8 than this version.
|
||||||
|
*
|
||||||
* @{
|
* @{
|
||||||
* @file
|
* @file
|
||||||
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
||||||
|
82
sys/include/checksum/ucrc16.h
Normal file
82
sys/include/checksum/ucrc16.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Freie Universität Berlin
|
||||||
|
*
|
||||||
|
* 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_ucrc16 CRC16 (lightweight)
|
||||||
|
* @ingroup sys_checksum
|
||||||
|
* @brief Lightweight CRC16 checksum algorithms
|
||||||
|
*
|
||||||
|
* This CRC16 implementation does not use pre-calculated lookup tables and is
|
||||||
|
* thus very lightweight (memory-wise), but as a caveat slower (about factor 8)
|
||||||
|
* than the version with pre-calculated lookup tables.
|
||||||
|
*
|
||||||
|
* Additionally compared to @ref sys_checksum_crc_ccitt this is a generalized
|
||||||
|
* implementation. One can easily exchange generator polynomials and starting
|
||||||
|
* seeds.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief ucrc16 definitions
|
||||||
|
*
|
||||||
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
||||||
|
*/
|
||||||
|
#ifndef UCRC16_H_
|
||||||
|
#define UCRC16_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @{
|
||||||
|
* @brief Various generator polynomials
|
||||||
|
*/
|
||||||
|
#define UCRC16_CCITT_POLY_BE (0x1021) /**< CRC16-CCITT polynomial (big-endian) */
|
||||||
|
#define UCRC16_CCITT_POLY_LE (0x8408) /**< CRC16-CCITT polynomial (little-endian) */
|
||||||
|
/** *} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate CRC16 (big-endian version)
|
||||||
|
*
|
||||||
|
* @param[in] buf Start of memory are 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
|
||||||
|
*
|
||||||
|
* @return Checksum of the specified memory area based on @p seed and @p poly
|
||||||
|
*
|
||||||
|
* @note The return value is not the complement of the sum but the sum itself
|
||||||
|
*/
|
||||||
|
uint16_t ucrc16_calc_be(const uint8_t *buf, size_t len, uint16_t poly,
|
||||||
|
uint16_t seed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate CRC16 (little-endian version)
|
||||||
|
*
|
||||||
|
* @param[in] buf Start of memory are 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
|
||||||
|
*
|
||||||
|
* @return Checksum of the specified memory area based on @p seed and @p poly
|
||||||
|
*
|
||||||
|
* @note The return value is not the complement of the sum but the sum itself
|
||||||
|
*/
|
||||||
|
uint16_t ucrc16_calc_le(const uint8_t *buf, size_t len, uint16_t poly,
|
||||||
|
uint16_t seed);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* UCRC16_H_ */
|
||||||
|
/** @} */
|
Loading…
Reference in New Issue
Block a user