diff --git a/TESTS/mbed_drivers/crc/main.cpp b/TESTS/mbed_drivers/crc/main.cpp index 598305e8f9..7245ade955 100644 --- a/TESTS/mbed_drivers/crc/main.cpp +++ b/TESTS/mbed_drivers/crc/main.cpp @@ -63,6 +63,26 @@ void test_supported_polynomials() TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc)); TEST_ASSERT_EQUAL(0x57, crc); } + { + MbedCRC ct(0x2B, 0, true, false); + TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc)); + TEST_ASSERT_EQUAL(0x1D, crc); + } + { + MbedCRC ct(0x2B, 0, false, true); + TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc)); + TEST_ASSERT_EQUAL(0x2E, crc); + } + { + MbedCRC ct(0x2B, 0, true, true); + TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc)); + TEST_ASSERT_EQUAL(0x5C, crc); + } + { + MbedCRC ct(0, 0x2B, false, true); + TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc)); + TEST_ASSERT_EQUAL(0x7C, crc); + } { MbedCRC 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 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 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 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 ct; + TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc)); + TEST_ASSERT_EQUAL(0xCBF43926, crc); + } + { + MbedCRC ct; + TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc)); + TEST_ASSERT_EQUAL(0xCBF43926, crc); + } + { + MbedCRC 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), diff --git a/TESTS/mbed_hal/crc/main.cpp b/TESTS/mbed_hal/crc/main.cpp index f2bd505830..2bd3b5a3b5 100644 --- a/TESTS/mbed_hal/crc/main.cpp +++ b/TESTS/mbed_hal/crc/main.cpp @@ -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* diff --git a/drivers/MbedCRC.h b/drivers/MbedCRC.h index a8f7d790f1..7adcc9462b 100644 --- a/drivers/MbedCRC.h +++ b/drivers/MbedCRC.h @@ -29,7 +29,12 @@ #include "platform/SingletonPtr.h" #include "platform/PlatformMutex.h" +#ifdef UNITTEST #include +#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED +#else +#include +#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 = 0> + constexpr MbedCRC() : MbedCRC(0xFFFFFFFF, 0xFFFFFFFF, true, true) + { + } + + template = 0> + constexpr MbedCRC() : MbedCRC(0, 0, true, true) + { + } + + template = 0> + constexpr MbedCRC() : MbedCRC(0xFFFF, 0, false, false) + { + } + + template = 0> + constexpr MbedCRC() : MbedCRC(0, 0, false, false) + { + } + + template = 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 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::_crc_table[MBED_CRC_TABLE_SIZE]; + +template<> +const uint8_t MbedCRC::_crc_table[MBED_CRC_TABLE_SIZE]; + +template<> +const uint16_t MbedCRC::_crc_table[MBED_CRC_TABLE_SIZE]; + +template<> +const uint16_t MbedCRC::_crc_table[MBED_CRC_TABLE_SIZE]; + +template<> +const uint32_t MbedCRC::_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::MbedCRC() : MbedCRC(0xFFFFFFFF, 0xFFFFFFFF, true, true) -{ -} - -template<> -inline MbedCRC::MbedCRC() : MbedCRC(0, 0, true, true) -{ -} - -template<> -inline MbedCRC::MbedCRC() : MbedCRC(0xFFFF, 0, false, false) -{ -} - -template<> -inline MbedCRC::MbedCRC(): MbedCRC(0, 0, false, false) -{ -} - -template<> -inline MbedCRC::MbedCRC(): MbedCRC(0, 0, false, false) -{ -} - /** @}*/ /** @}*/ diff --git a/platform/cxxsupport/mstd_type_traits b/platform/cxxsupport/mstd_type_traits index bd598ac8a3..0a3007eedd 100644 --- a/platform/cxxsupport/mstd_type_traits +++ b/platform/cxxsupport/mstd_type_traits @@ -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 @@ -1361,6 +1362,29 @@ struct is_nothrow_invocable_r : impl::is_invocable_r= 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