mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #11897 from kjbracey-arm/crc
MbedCRC: improve init value handling and testspull/12225/head
commit
8c4ed4a6cb
|
|
@ -63,6 +63,26 @@ void test_supported_polynomials()
|
|||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
TEST_ASSERT_EQUAL(0x57, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_7BIT_SD, 7> ct(0x2B, 0, true, false);
|
||||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
TEST_ASSERT_EQUAL(0x1D, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_7BIT_SD, 7> ct(0x2B, 0, false, true);
|
||||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
TEST_ASSERT_EQUAL(0x2E, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_7BIT_SD, 7> ct(0x2B, 0, true, true);
|
||||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
TEST_ASSERT_EQUAL(0x5C, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_7BIT_SD, 7> ct(0, 0x2B, false, true);
|
||||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
TEST_ASSERT_EQUAL(0x7C, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_8BIT_CCITT, 8> ct;
|
||||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
|
|
@ -98,6 +118,51 @@ void test_partial_crc()
|
|||
|
||||
TEST_ASSERT_EQUAL(0x29B1, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_32BIT_ANSI, 32> ct;
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial_start(&crc));
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial(test, 8, &crc));
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial(&test[8], 1, &crc));
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial_stop(&crc));
|
||||
|
||||
TEST_ASSERT_EQUAL(0xCBF43926, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_32BIT_ANSI, 32> ct(0xFFFFFFFF, 0, true, false);
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial_start(&crc));
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial(test, 8, &crc));
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial_stop(&crc));
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_32BIT_ANSI, 32> ct(crc, 0xFFFFFFFF, true, true);
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial_start(&crc));
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial(&test[8], 1, &crc));
|
||||
TEST_ASSERT_EQUAL(0, ct.compute_partial_stop(&crc));
|
||||
|
||||
TEST_ASSERT_EQUAL(0xCBF43926, crc);
|
||||
}
|
||||
}
|
||||
|
||||
void test_mode_limit()
|
||||
{
|
||||
const char test[] = "123456789";
|
||||
uint32_t crc;
|
||||
|
||||
{
|
||||
MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::BITWISE> ct;
|
||||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
TEST_ASSERT_EQUAL(0xCBF43926, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::TABLE> ct;
|
||||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
TEST_ASSERT_EQUAL(0xCBF43926, crc);
|
||||
}
|
||||
{
|
||||
MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::HARDWARE> ct;
|
||||
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
|
||||
TEST_ASSERT_EQUAL(0xCBF43926, crc);
|
||||
}
|
||||
}
|
||||
|
||||
void test_sd_crc()
|
||||
|
|
@ -189,6 +254,7 @@ void test_thread_safety()
|
|||
Case cases[] = {
|
||||
Case("Test supported polynomials", test_supported_polynomials),
|
||||
Case("Test partial CRC", test_partial_crc),
|
||||
Case("Test mode-limited CRC", test_mode_limit),
|
||||
Case("Test SD CRC polynomials", test_sd_crc),
|
||||
#if defined(MBED_CONF_RTOS_PRESENT)
|
||||
Case("Test thread safety", test_thread_safety),
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@
|
|||
using namespace utest::v1;
|
||||
|
||||
#define POLY_8BIT_MAXIM 0x31
|
||||
#define POLY_16BIT_MAXIM 0x8005
|
||||
#define POLY_32BIT_POSIX 0x4C11DB7
|
||||
|
||||
#define UNSUPPORTED (-1)
|
||||
#define POL_CNT (2)
|
||||
|
|
@ -201,70 +199,78 @@ int main()
|
|||
// *INDENT-OFF*
|
||||
TEST_CASE local_test_cases[] = {
|
||||
/* Predefined polynomials. */
|
||||
/* 00 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, false, false}, 0x75 },
|
||||
/* 01 */{ {POLY_7BIT_SD , 7, 0x0000007F, 0x00000000, false, false}, 0x50 },
|
||||
/* 02 */{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, false, false}, 0x3A },
|
||||
/* 03 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000007F, false, false}, 0x0A },
|
||||
/* 04 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000002B, false, false}, 0x5E },
|
||||
/* 05 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, true , false}, 0x52 },
|
||||
/* 06 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, false, true }, 0x57 },
|
||||
{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, false, false}, 0x75 },
|
||||
{ {POLY_7BIT_SD , 7, 0x0000007F, 0x00000000, false, false}, 0x50 },
|
||||
{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, false, false}, 0x3A },
|
||||
{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000007F, false, false}, 0x0A },
|
||||
{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000002B, false, false}, 0x5E },
|
||||
{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, true , false}, 0x52 },
|
||||
{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, false, true }, 0x57 },
|
||||
{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, true , false}, 0x1D },
|
||||
{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, false, true }, 0x2E },
|
||||
{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, true , true }, 0x5C },
|
||||
{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000002B, false, true }, 0x7C },
|
||||
|
||||
/* 07 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, false, false}, 0xF4 },
|
||||
/* 08 */{ {POLY_8BIT_CCITT , 8, 0x000000FF, 0x00000000, false, false}, 0xFB },
|
||||
/* 09 */{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, false, false}, 0x87 },
|
||||
/* 10 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000FF, false, false}, 0x0B },
|
||||
/* 11 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000AB, false, false}, 0x5F },
|
||||
/* 12 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, true , false}, 0x04 },
|
||||
/* 13 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, false, true }, 0x2F },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, false, false}, 0xF4 },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x000000FF, 0x00000000, false, false}, 0xFB },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, false, false}, 0x87 },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000FF, false, false}, 0x0B },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000AB, false, false}, 0x5F },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, true , false}, 0x04 },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, false, true }, 0x2F },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, true, false}, 0x77 },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, false, true }, 0xE1 },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, true, true }, 0xEE },
|
||||
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000AB, false, true }, 0x84 },
|
||||
|
||||
/* 14 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, false}, 0x31C3 },
|
||||
/* 15 */{ {POLY_16BIT_CCITT , 16, 0x0000FFFF, 0x00000000, false, false}, 0x29B1 },
|
||||
/* 16 */{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, false, false}, 0x7D70 },
|
||||
/* 17 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000FFFF, false, false}, 0xCE3C },
|
||||
/* 18 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000ABAB, false, false}, 0x9A68 },
|
||||
/* 19 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, true , false}, 0x9184 },
|
||||
/* 20 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, true }, 0xC38C },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, false}, 0x31C3 },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x0000FFFF, 0x00000000, false, false}, 0x29B1 },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, false, false}, 0x7D70 },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000FFFF, false, false}, 0xCE3C },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000ABAB, false, false}, 0x9A68 },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, true , false}, 0x9184 },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, true }, 0xC38C },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, true, false}, 0xDD37 },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, false, true }, 0x0EBE },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, true, true }, 0xECBB },
|
||||
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000ABAB, false, true }, 0x6827 },
|
||||
|
||||
/* 21 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, false, false}, 0xFEE8 },
|
||||
/* 22 */{ {POLY_16BIT_IBM , 16, 0x0000FFFF, 0x00000000, false, false}, 0xAEE7 },
|
||||
/* 23 */{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, false, false}, 0x0887 },
|
||||
/* 24 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000FFFF, false, false}, 0x0117 },
|
||||
/* 25 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000ABAB, false, false}, 0x5543 },
|
||||
/* 26 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, true , false}, 0xBCDD },
|
||||
/* 27 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, false, true }, 0x177F },
|
||||
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, false, false}, 0xFEE8 },
|
||||
{ {POLY_16BIT_IBM , 16, 0x0000FFFF, 0x00000000, false, false}, 0xAEE7 },
|
||||
{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, false, false}, 0x0887 },
|
||||
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000FFFF, false, false}, 0x0117 },
|
||||
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000ABAB, false, false}, 0x5543 },
|
||||
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, true , false}, 0xBCDD },
|
||||
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, false, true }, 0x177F },
|
||||
{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, true, false}, 0x4AB2 },
|
||||
{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, false, true }, 0xE110 },
|
||||
{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, true, true }, 0x4D52 },
|
||||
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000ABAB, false, true }, 0xBCD4 },
|
||||
|
||||
/* 28 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, false, false}, 0x89A1897F },
|
||||
/* 29 */{ {POLY_32BIT_ANSI , 32, 0xFFFFFFFF, 0x00000000, false, false}, 0x0376E6E7 },
|
||||
/* 30 */{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, false, false}, 0x871A2FAA },
|
||||
/* 31 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xFFFFFFFF, false, false}, 0x765E7680 },
|
||||
/* 32 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xABABABAB, false, false}, 0x220A22D4 },
|
||||
/* 33 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, true , false}, 0x11B4BFB4 },
|
||||
/* 34 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, false, true }, 0xFE918591 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, false, false}, 0x89A1897F },
|
||||
{ {POLY_32BIT_ANSI , 32, 0xFFFFFFFF, 0x00000000, false, false}, 0x0376E6E7 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, false, false}, 0x871A2FAA },
|
||||
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xFFFFFFFF, false, false}, 0x765E7680 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xABABABAB, false, false}, 0x220A22D4 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, true , false}, 0x11B4BFB4 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, false, true }, 0xFE918591 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, true, false}, 0x1F0F1961 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, false, true }, 0x55F458E1 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, true, true }, 0x8698F0F8 },
|
||||
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xABABABAB, false, true }, 0x553A2E3A },
|
||||
|
||||
/* Not-predefined polynomials. */
|
||||
/* 35 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, false, false}, 0xA2 },
|
||||
/* 36 */{ {POLY_8BIT_MAXIM , 8, 0x000000FF, 0x00000000, false, false}, 0xF7 },
|
||||
/* 37 */{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, false, false}, 0x71 },
|
||||
/* 38 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000FF, false, false}, 0x5D },
|
||||
/* 39 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000AB, false, false}, 0x09 },
|
||||
/* 40 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, true , false}, 0x85 },
|
||||
/* 41 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, false, true }, 0x45 },
|
||||
|
||||
/* 42 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x00000000, false, false}, 0xFEE8 },
|
||||
/* 43 */{ {POLY_16BIT_MAXIM , 16, 0x0000FFFF, 0x00000000, false, false}, 0xAEE7 },
|
||||
/* 44 */{ {POLY_16BIT_MAXIM , 16, 0x0000ABAB, 0x00000000, false, false}, 0x0887 },
|
||||
/* 45 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x0000FFFF, false, false}, 0x0117 },
|
||||
/* 46 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x0000ABAB, false, false}, 0x5543 },
|
||||
/* 47 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x00000000, true , false}, 0xBCDD },
|
||||
/* 48 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x00000000, false, true }, 0x177F },
|
||||
|
||||
/* 49 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0x00000000, false, false}, 0x89A1897F },
|
||||
/* 50 */{ {POLY_32BIT_POSIX , 32, 0xFFFFFFFF, 0x00000000, false, false}, 0x0376E6E7 },
|
||||
/* 51 */{ {POLY_32BIT_POSIX , 32, 0xABABABAB, 0x00000000, false, false}, 0x871A2FAA },
|
||||
/* 52 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0xFFFFFFFF, false, false}, 0x765E7680 },
|
||||
/* 53 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0xABABABAB, false, false}, 0x220A22D4 },
|
||||
/* 54 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0x00000000, true , false}, 0x11B4BFB4 },
|
||||
/* 55 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0x00000000, false, true }, 0xFE918591 },
|
||||
/* Not-predefined polynomials. */
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, false, false}, 0xA2 },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x000000FF, 0x00000000, false, false}, 0xF7 },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, false, false}, 0x71 },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000FF, false, false}, 0x5D },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000AB, false, false}, 0x09 },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, true , false}, 0x85 },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, false, true }, 0x45 },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, true, false}, 0x56 },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, false, true }, 0x8E },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, true, true }, 0x6A },
|
||||
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000AB, false, true }, 0xEE },
|
||||
};
|
||||
// *INDENT-ON*
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,12 @@
|
|||
#include "platform/SingletonPtr.h"
|
||||
#include "platform/PlatformMutex.h"
|
||||
|
||||
#ifdef UNITTEST
|
||||
#include <type_traits>
|
||||
#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
|
||||
#else
|
||||
#include <mstd_type_traits>
|
||||
#endif
|
||||
|
||||
namespace mbed {
|
||||
/** \addtogroup drivers-public-api */
|
||||
|
|
@ -175,12 +180,40 @@ public:
|
|||
* polynomials with different initial/final/reflect values
|
||||
*
|
||||
*/
|
||||
constexpr
|
||||
MbedCRC(uint32_t initial_xor, uint32_t final_xor, bool reflect_data, bool reflect_remainder) :
|
||||
crc_impl(initial_xor, final_xor, reflect_data, reflect_remainder)
|
||||
{
|
||||
}
|
||||
|
||||
MbedCRC();
|
||||
/* Default values for different types of polynomials
|
||||
*/
|
||||
// *INDENT-OFF*
|
||||
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_32BIT_ANSI && width == 32, int> = 0>
|
||||
constexpr MbedCRC() : MbedCRC(0xFFFFFFFF, 0xFFFFFFFF, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_16BIT_IBM && width == 16, int> = 0>
|
||||
constexpr MbedCRC() : MbedCRC(0, 0, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_16BIT_CCITT && width == 16, int> = 0>
|
||||
constexpr MbedCRC() : MbedCRC(0xFFFF, 0, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_7BIT_SD && width == 7, int> = 0>
|
||||
constexpr MbedCRC() : MbedCRC(0, 0, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_8BIT_CCITT && width == 8, int> = 0>
|
||||
constexpr MbedCRC() : MbedCRC(0, 0, false, false)
|
||||
{
|
||||
}
|
||||
// *INDENT-ON*
|
||||
|
||||
/** Compute CRC for the data input
|
||||
* Compute CRC performs the initialization, computation and collection of
|
||||
|
|
@ -279,6 +312,7 @@ class MbedCRC {
|
|||
public:
|
||||
typedef size_t crc_data_size_t;
|
||||
|
||||
constexpr
|
||||
MbedCRC(uint32_t initial_xor, uint32_t final_xor, bool reflect_data, bool reflect_remainder) :
|
||||
_initial_value(adjust_initial_value(initial_xor, reflect_data)),
|
||||
_final_xor(final_xor),
|
||||
|
|
@ -400,7 +434,7 @@ public:
|
|||
}
|
||||
} else {
|
||||
/* CRC has MSB in top bit of register */
|
||||
p_crc = _reflect_remainder ? reflect_register(p_crc) : shift_right(p_crc);
|
||||
p_crc = _reflect_remainder ? reflect(p_crc) : shift_right(p_crc);
|
||||
}
|
||||
} else { // TABLE
|
||||
/* CRC has MSB in bottom bit of register */
|
||||
|
|
@ -417,45 +451,91 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
/** Guaranteed constexpr reflection (all toolchains)
|
||||
*
|
||||
* @note This should never be run-time evaluated - very inefficient
|
||||
* @param Register value to be reflected (full 32-bit value)
|
||||
* @return Reflected value (full 32-bit value)
|
||||
*/
|
||||
static constexpr uint32_t reflect_constant(uint32_t data)
|
||||
{
|
||||
/* Doing this hard way to keep it C++11 constexpr and hence ARM C 5 compatible */
|
||||
return ((data & 0x00000001) << 31) |
|
||||
((data & 0x00000002) << 29) |
|
||||
((data & 0x00000004) << 27) |
|
||||
((data & 0x00000008) << 25) |
|
||||
((data & 0x00000010) << 23) |
|
||||
((data & 0x00000020) << 21) |
|
||||
((data & 0x00000040) << 19) |
|
||||
((data & 0x00000080) << 17) |
|
||||
((data & 0x00000100) << 15) |
|
||||
((data & 0x00000200) << 13) |
|
||||
((data & 0x00000400) << 11) |
|
||||
((data & 0x00000800) << 9) |
|
||||
((data & 0x00001000) << 7) |
|
||||
((data & 0x00002000) << 5) |
|
||||
((data & 0x00004000) << 3) |
|
||||
((data & 0x00008000) << 1) |
|
||||
((data & 0x00010000) >> 1) |
|
||||
((data & 0x00020000) >> 3) |
|
||||
((data & 0x00040000) >> 5) |
|
||||
((data & 0x00080000) >> 7) |
|
||||
((data & 0x00100000) >> 9) |
|
||||
((data & 0x00200000) >> 11) |
|
||||
((data & 0x00400000) >> 13) |
|
||||
((data & 0x00800000) >> 15) |
|
||||
((data & 0x01000000) >> 17) |
|
||||
((data & 0x02000000) >> 19) |
|
||||
((data & 0x04000000) >> 21) |
|
||||
((data & 0x08000000) >> 23) |
|
||||
((data & 0x10000000) >> 25) |
|
||||
((data & 0x20000000) >> 27) |
|
||||
((data & 0x40000000) >> 29) |
|
||||
((data & 0x80000000) >> 31);
|
||||
}
|
||||
|
||||
/** General reflection
|
||||
*
|
||||
* @note This is used when we may need to perform run-time computation, so
|
||||
* we need the possibility to produce the optimal run-time RBIT instruction. But
|
||||
* if the compiler doesn't treat RBIT as a built-in, it's useful to have a C fallback
|
||||
* for the constant case, avoiding runtime RBIT(0) computations. This is an
|
||||
* optimization only available for some toolchains; others will always use runtime
|
||||
* RBIT. If we require a constant expression, use reflect_constant instead.
|
||||
*
|
||||
* @param Register value to be reflected (full 32-bit value)
|
||||
* @return Reflected value (full 32-bit value)
|
||||
*/
|
||||
#ifdef MSTD_HAS_IS_CONSTANT_EVALUATED
|
||||
static constexpr uint32_t reflect(uint32_t data)
|
||||
{
|
||||
return mstd::is_constant_evaluated() ? reflect_constant(data) : __RBIT(data);
|
||||
}
|
||||
#else
|
||||
static uint32_t reflect(uint32_t data)
|
||||
{
|
||||
return __RBIT(data);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Data bytes may need to be reflected.
|
||||
*
|
||||
* @param data value to be reflected (bottom 8 bits)
|
||||
* @return Reflected value (bottom 8 bits)
|
||||
*/
|
||||
static MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
|
||||
uint_fast32_t reflect_byte(uint_fast32_t data)
|
||||
{
|
||||
return reflect(data) >> 24;
|
||||
}
|
||||
|
||||
/** Get the current CRC polynomial, reflected at bottom of register.
|
||||
*
|
||||
* @return Reflected polynomial value (so x^width term would be at bit -1)
|
||||
*/
|
||||
static constexpr uint32_t get_reflected_polynomial()
|
||||
{
|
||||
/* Doing this hard way to keep it C++11 constexpr and hence ARM C 5 compatible */
|
||||
return shift_right(((polynomial & 0x00000001) << 31) |
|
||||
((polynomial & 0x00000002) << 29) |
|
||||
((polynomial & 0x00000004) << 27) |
|
||||
((polynomial & 0x00000008) << 25) |
|
||||
((polynomial & 0x00000010) << 23) |
|
||||
((polynomial & 0x00000020) << 21) |
|
||||
((polynomial & 0x00000040) << 19) |
|
||||
((polynomial & 0x00000080) << 17) |
|
||||
((polynomial & 0x00000100) << 15) |
|
||||
((polynomial & 0x00000200) << 13) |
|
||||
((polynomial & 0x00000400) << 11) |
|
||||
((polynomial & 0x00000800) << 9) |
|
||||
((polynomial & 0x00001000) << 7) |
|
||||
((polynomial & 0x00002000) << 5) |
|
||||
((polynomial & 0x00004000) << 3) |
|
||||
((polynomial & 0x00008000) << 1) |
|
||||
((polynomial & 0x00010000) >> 1) |
|
||||
((polynomial & 0x00020000) >> 3) |
|
||||
((polynomial & 0x00040000) >> 5) |
|
||||
((polynomial & 0x00080000) >> 7) |
|
||||
((polynomial & 0x00100000) >> 9) |
|
||||
((polynomial & 0x00200000) >> 11) |
|
||||
((polynomial & 0x00400000) >> 13) |
|
||||
((polynomial & 0x00800000) >> 15) |
|
||||
((polynomial & 0x01000000) >> 17) |
|
||||
((polynomial & 0x02000000) >> 19) |
|
||||
((polynomial & 0x04000000) >> 21) |
|
||||
((polynomial & 0x08000000) >> 23) |
|
||||
((polynomial & 0x10000000) >> 25) |
|
||||
((polynomial & 0x20000000) >> 27) |
|
||||
((polynomial & 0x40000000) >> 29) |
|
||||
((polynomial & 0x80000000) >> 31));
|
||||
return shift_right(reflect_constant(polynomial));
|
||||
}
|
||||
|
||||
/** Get the current CRC polynomial, at top of register.
|
||||
|
|
@ -479,27 +559,13 @@ private:
|
|||
>>;
|
||||
// *INDENT-ON*
|
||||
|
||||
/* Not [MBED_CRC_TABLE_SIZE] as that could be [0], which is illegal.
|
||||
* We do need the declaration to always exist so that do_compute_partial<TABLE> is always well-formed,
|
||||
* but we never actually use it MBED_CRC_TABLE_SIZE is 0.
|
||||
*/
|
||||
static const crc_table_t _crc_table[];
|
||||
#if MBED_CRC_TABLE_SIZE > 0
|
||||
/* Tables only actually defined for mode == TABLE, and certain polynomials - see below */
|
||||
static const crc_table_t _crc_table[MBED_CRC_TABLE_SIZE];
|
||||
#endif
|
||||
|
||||
static uint32_t adjust_initial_value(uint32_t initial_xor, bool reflect_data)
|
||||
static constexpr uint32_t adjust_initial_value(uint32_t initial_xor, bool reflect_data)
|
||||
{
|
||||
/* As initial_xor is almost certain to be constant all zeros or ones, try to
|
||||
* process that a constant, avoiding an RBIT instruction (or worse).
|
||||
*/
|
||||
if (initial_xor == 0 || initial_xor == (get_crc_mask() & -1U)) {
|
||||
/* Only possible adjustment is shifting to top for bitwise */
|
||||
if (mode == CrcMode::BITWISE && !reflect_data) {
|
||||
return shift_left(initial_xor);
|
||||
} else {
|
||||
return initial_xor;
|
||||
}
|
||||
}
|
||||
|
||||
/* Weird or non-constant initial value - need to think about reflection */
|
||||
if (mode == CrcMode::BITWISE) {
|
||||
/* For bitwise calculation, CRC register is reflected if data is, to match input.
|
||||
* (MSB at bottom of register). If not reflected, it is at the top of the register
|
||||
|
|
@ -546,34 +612,15 @@ private:
|
|||
return (uint32_t)((uint32_t)2U << (width - 1)) - 1U;
|
||||
}
|
||||
|
||||
/** Data bytes may need to be reflected.
|
||||
*
|
||||
* @param data value to be reflected (bottom 8 bits)
|
||||
* @return Reflected value (bottom 8 bits)
|
||||
*/
|
||||
static uint_fast32_t reflect_byte(uint_fast32_t data)
|
||||
{
|
||||
return __RBIT(data) >> 24;
|
||||
}
|
||||
|
||||
/** CRC values may need to be reflected.
|
||||
*
|
||||
* @param CRC value to be reflected (width bits at bottom of 32-bit word)
|
||||
* @return Reflected value (still at bottom of 32-bit word)
|
||||
*/
|
||||
static uint32_t reflect_crc(uint32_t data)
|
||||
static MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
|
||||
uint32_t reflect_crc(uint32_t data)
|
||||
{
|
||||
return __RBIT(data) >> (32 - width);
|
||||
}
|
||||
|
||||
/** Register values may need to be reflected.
|
||||
*
|
||||
* @param Register value to be reflected (full 32-bit value)
|
||||
* @return Reflected value (full 32-bit value)
|
||||
*/
|
||||
static uint32_t reflect_register(uint32_t data)
|
||||
{
|
||||
return __RBIT(data);
|
||||
return reflect(data) >> (32 - width);
|
||||
}
|
||||
|
||||
/** Register values may need to be shifted left.
|
||||
|
|
@ -742,6 +789,7 @@ private:
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if MBED_CRC_TABLE_SIZE > 0
|
||||
/** CRC computation using ROM tables.
|
||||
*
|
||||
* @param buffer data buffer
|
||||
|
|
@ -774,6 +822,7 @@ private:
|
|||
*crc = p_crc;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEVICE_CRC
|
||||
/** Hardware CRC computation.
|
||||
|
|
@ -793,37 +842,32 @@ private:
|
|||
|
||||
};
|
||||
|
||||
#if MBED_CRC_TABLE_SIZE > 0
|
||||
/* Declarations of the tables we provide. (Not strictly needed, but compilers
|
||||
* can warn if they see us using the template without a generic definition, so
|
||||
* let it know we have provided these specialisations.)
|
||||
*/
|
||||
template<>
|
||||
const uint8_t MbedCRC<POLY_7BIT_SD, 7, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
|
||||
|
||||
template<>
|
||||
const uint8_t MbedCRC<POLY_8BIT_CCITT, 8, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
|
||||
|
||||
template<>
|
||||
const uint16_t MbedCRC<POLY_16BIT_CCITT, 16, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
|
||||
|
||||
template<>
|
||||
const uint16_t MbedCRC<POLY_16BIT_IBM, 16, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
|
||||
|
||||
template<>
|
||||
const uint32_t MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
|
||||
|
||||
#endif // MBED_CRC_TABLE_SIZE > 0
|
||||
|
||||
} // namespace impl
|
||||
|
||||
#endif // !defined(DOXYGEN_ONLY)
|
||||
|
||||
/* Default values for different types of polynomials
|
||||
*/
|
||||
template<>
|
||||
inline MbedCRC<POLY_32BIT_ANSI, 32>::MbedCRC() : MbedCRC(0xFFFFFFFF, 0xFFFFFFFF, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
template<>
|
||||
inline MbedCRC<POLY_16BIT_IBM, 16>::MbedCRC() : MbedCRC(0, 0, true, true)
|
||||
{
|
||||
}
|
||||
|
||||
template<>
|
||||
inline MbedCRC<POLY_16BIT_CCITT, 16>::MbedCRC() : MbedCRC(0xFFFF, 0, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
template<>
|
||||
inline MbedCRC<POLY_7BIT_SD, 7>::MbedCRC(): MbedCRC(0, 0, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
template<>
|
||||
inline MbedCRC<POLY_8BIT_CCITT, 8>::MbedCRC(): MbedCRC(0, 0, false, false)
|
||||
{
|
||||
}
|
||||
|
||||
/** @}*/
|
||||
/** @}*/
|
||||
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@
|
|||
* - mstd::is_invocable, mbed::is_invocable_r, etc
|
||||
* - mstd::invoke_result
|
||||
* - logical operator traits (mstd::conjunction, mstd::disjunction, mstd::negation)
|
||||
* - mstd::is_constant_evaluated
|
||||
*/
|
||||
|
||||
#include <mstd_cstddef>
|
||||
|
|
@ -1361,6 +1362,29 @@ struct is_nothrow_invocable_r : impl::is_invocable_r<R, invoke_result<F, Args...
|
|||
|
||||
#endif // __cpp_lib_is_invocable
|
||||
|
||||
/* C++20 is_constant_evaluated */
|
||||
constexpr bool is_constant_evaluated() noexcept
|
||||
{
|
||||
#ifdef __clang__
|
||||
#if __has_builtin(__builtin_is_constant_evaluated)
|
||||
#define MSTD_HAS_IS_CONSTANT_EVALUATED 1
|
||||
return __builtin_is_constant_evaluated();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
#elif __GNUC__ >= 9
|
||||
#define MSTD_HAS_IS_CONSTANT_EVALUATED 1
|
||||
return __builtin_is_constant_evaluated();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if MSTD_HAS_IS_CONSTANT_EVALUATED
|
||||
#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED constexpr
|
||||
#else
|
||||
#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
|
||||
#endif
|
||||
|
||||
} // namespace mstd
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue