17 #ifndef MBED_CRC_API_H 18 #define MBED_CRC_API_H 21 #include "hal/crc_api.h" 25 #include "platform/mbed_assert.h" 29 #include "platform/SingletonPtr.h" 30 #include "platform/PlatformMutex.h" 33 #include <type_traits> 34 #define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED 36 #include <mstd_type_traits> 59 template<u
int32_t polynomial, u
int8_t w
idth, CrcMode mode>
62 constexpr
bool have_crc_table(uint32_t polynomial, uint8_t width)
64 #if MBED_CRC_TABLE_SIZE > 0 75 constexpr CrcMode choose_crc_mode(uint32_t polynomial, uint8_t width, CrcMode mode_limit)
79 mode_limit == CrcMode::HARDWARE && HAL_CRC_IS_SUPPORTED(polynomial, width) ? CrcMode::HARDWARE :
81 mode_limit <= CrcMode::TABLE && have_crc_table(polynomial, width) ? CrcMode::TABLE :
84 #endif // DOXYGEN_ONLY 152 template <u
int32_t polynomial = POLY_32BIT_ANSI, u
int8_t w
idth = 32, CrcMode mode_limit = CrcMode::HARDWARE>
154 impl::MbedCRC<polynomial, width, impl::choose_crc_mode(polynomial, width, mode_limit)> crc_impl;
160 HARDWARE = int(::mbed::CrcMode::HARDWARE),
162 TABLE = int(::mbed::CrcMode::TABLE),
163 BITWISE = int(::mbed::CrcMode::BITWISE)
166 typedef size_t crc_data_size_t;
184 MbedCRC(uint32_t initial_xor, uint32_t final_xor,
bool reflect_data,
bool reflect_remainder) :
185 crc_impl(initial_xor, final_xor, reflect_data, reflect_remainder)
192 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_32BIT_ANSI && w
idth == 32,
int> = 0>
193 constexpr MbedCRC() : MbedCRC(0xFFFFFFFF, 0xFFFFFFFF, true, true)
197 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_16BIT_IBM && w
idth == 16,
int> = 0>
198 constexpr MbedCRC() : MbedCRC(0, 0, true, true)
202 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_16BIT_CCITT && w
idth == 16,
int> = 0>
203 constexpr MbedCRC() : MbedCRC(0xFFFF, 0, false, false)
207 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_7BIT_SD && w
idth == 7,
int> = 0>
208 constexpr MbedCRC() : MbedCRC(0, 0, false, false)
212 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_8BIT_CCITT && w
idth == 8,
int> = 0>
213 constexpr MbedCRC() : MbedCRC(0, 0, false, false)
227 int32_t compute(
const void *buffer, crc_data_size_t size, uint32_t *crc)
229 return crc_impl.compute(buffer, size, crc);
253 int32_t compute_partial(
const void *buffer, crc_data_size_t size, uint32_t *crc)
255 return crc_impl.compute_partial(buffer, size, crc);
268 int32_t compute_partial_start(uint32_t *crc)
270 return crc_impl.compute_partial_start(crc);
282 int32_t compute_partial_stop(uint32_t *crc)
284 return crc_impl.compute_partial_stop(crc);
291 static constexpr uint32_t get_polynomial()
300 static constexpr uint8_t get_width()
306 #if !defined(DOXYGEN_ONLY) 310 template <u
int32_t polynomial, u
int8_t w
idth, CrcMode mode>
313 typedef size_t crc_data_size_t;
316 MbedCRC(uint32_t initial_xor, uint32_t final_xor,
bool reflect_data,
bool reflect_remainder) :
317 _initial_value(adjust_initial_value(initial_xor, reflect_data)),
318 _final_xor(final_xor),
319 _reflect_data(reflect_data),
320 _reflect_remainder(reflect_remainder)
322 static_assert(width <= 32,
"Max 32-bit CRC supported");
334 int32_t compute(
const void *buffer, crc_data_size_t size, uint32_t *crc)
338 status = compute_partial_start(crc);
343 status = compute_partial(buffer, size, crc);
348 status = compute_partial_stop(crc);
373 int32_t compute_partial(
const void *buffer, crc_data_size_t size, uint32_t *crc)
375 const uint8_t *data =
static_cast<const uint8_t *
>(buffer);
376 return do_compute_partial(data, size, crc);
389 int32_t compute_partial_start(uint32_t *crc)
392 if (mode == CrcMode::HARDWARE) {
396 config.
width = width;
406 *crc = _initial_value;
419 int32_t compute_partial_stop(uint32_t *crc)
422 if (mode == CrcMode::HARDWARE) {
423 *crc = hal_crc_get_result();
428 uint_fast32_t p_crc = *crc;
429 if (mode == CrcMode::BITWISE) {
432 if (!_reflect_remainder) {
433 p_crc = reflect_crc(p_crc);
437 p_crc = _reflect_remainder ? reflect(p_crc) : shift_right(p_crc);
441 if (!_reflect_remainder) {
442 p_crc = reflect_crc(p_crc);
447 p_crc &= get_crc_mask();
460 static constexpr uint32_t reflect_constant(uint32_t data)
463 return ((data & 0x00000001) << 31) |
464 ((data & 0x00000002) << 29) |
465 ((data & 0x00000004) << 27) |
466 ((data & 0x00000008) << 25) |
467 ((data & 0x00000010) << 23) |
468 ((data & 0x00000020) << 21) |
469 ((data & 0x00000040) << 19) |
470 ((data & 0x00000080) << 17) |
471 ((data & 0x00000100) << 15) |
472 ((data & 0x00000200) << 13) |
473 ((data & 0x00000400) << 11) |
474 ((data & 0x00000800) << 9) |
475 ((data & 0x00001000) << 7) |
476 ((data & 0x00002000) << 5) |
477 ((data & 0x00004000) << 3) |
478 ((data & 0x00008000) << 1) |
479 ((data & 0x00010000) >> 1) |
480 ((data & 0x00020000) >> 3) |
481 ((data & 0x00040000) >> 5) |
482 ((data & 0x00080000) >> 7) |
483 ((data & 0x00100000) >> 9) |
484 ((data & 0x00200000) >> 11) |
485 ((data & 0x00400000) >> 13) |
486 ((data & 0x00800000) >> 15) |
487 ((data & 0x01000000) >> 17) |
488 ((data & 0x02000000) >> 19) |
489 ((data & 0x04000000) >> 21) |
490 ((data & 0x08000000) >> 23) |
491 ((data & 0x10000000) >> 25) |
492 ((data & 0x20000000) >> 27) |
493 ((data & 0x40000000) >> 29) |
494 ((data & 0x80000000) >> 31);
509 #ifdef MSTD_HAS_IS_CONSTANT_EVALUATED 510 static constexpr uint32_t reflect(uint32_t data)
512 return mstd::is_constant_evaluated() ? reflect_constant(data) : __RBIT(data);
515 static uint32_t reflect(uint32_t data)
526 static MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
527 uint_fast32_t reflect_byte(uint_fast32_t data)
529 return reflect(data) >> 24;
536 static constexpr uint32_t get_reflected_polynomial()
538 return shift_right(reflect_constant(polynomial));
545 static constexpr uint32_t get_top_polynomial()
547 return shift_left(polynomial);
550 const uint32_t _initial_value;
551 const uint32_t _final_xor;
552 const bool _reflect_data;
553 const bool _reflect_remainder;
556 using crc_table_t = std::conditional_t<width <= 8, uint8_t,
557 std::conditional_t<width <= 16, uint16_t,
562 #if MBED_CRC_TABLE_SIZE > 0 564 static const crc_table_t _crc_table[MBED_CRC_TABLE_SIZE];
567 static constexpr uint32_t adjust_initial_value(uint32_t initial_xor,
bool reflect_data)
569 if (mode == CrcMode::BITWISE) {
574 return reflect_data ? reflect_crc(initial_xor) : shift_left(initial_xor);
575 }
else if (mode == CrcMode::TABLE) {
578 return reflect_crc(initial_xor);
589 if (mode == CrcMode::HARDWARE) {
590 mbed_crc_mutex->
lock();
600 if (mode == CrcMode::HARDWARE) {
610 static constexpr uint32_t get_crc_mask()
612 return (uint32_t)((uint32_t)2U << (width - 1)) - 1U;
620 static MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
621 uint32_t reflect_crc(uint32_t data)
623 return reflect(data) >> (32 - width);
631 static constexpr uint32_t shift_left(uint32_t data)
633 return data << (32 - width);
641 static constexpr uint32_t shift_right(uint32_t data)
643 return data >> (32 - width);
647 #if (defined __GNUC__ || defined __clang__) && \ 648 (defined __arm__ || defined __ARM_ARCH) 649 #if (__ARM_ARCH_7M__ == 1U) || \ 650 (__ARM_ARCH_7EM__ == 1U) || \ 651 (__ARM_ARCH_8M_MAIN__ == 1U) || \ 652 (__ARM_ARCH_7A__ == 1U) 654 #define MBED_CRC_ARM_THUMB2 1 655 #define MBED_CRC_THUMB1 0 656 #elif (__ARM_ARCH_6M__ == 1U) || \ 657 (__ARM_ARCH_8M_BASE__ == 1U) 659 #define MBED_CRC_ARM_THUMB2 0 660 #define MBED_CRC_THUMB1 1 661 #else // __ARM_ARCH_xxx 662 #error "Unknown ARM architecture for CRC optimization" 663 #endif // __ARM_ARCH_xxx 664 #else // __arm__ || defined __ICC_ARM__ || defined __ARM_ARCH 666 #define MBED_CRC_ARM_THUMB2 0 667 #define MBED_CRC_THUMB1 0 682 static uint_fast32_t do_1_bit_normal(uint_fast32_t p_crc)
684 #if MBED_CRC_ARM_THUMB2 685 __asm(
".syntax unified\n\t" 686 "LSLS" "\t%[p_crc], %[p_crc], #1\n\t" 688 "EORCS" "\t%[p_crc], %[poly]" 689 : [p_crc]
"+&r" (p_crc)
690 : [poly]
"rI" (get_top_polynomial())
692 #elif MBED_CRC_THUMB1 693 __asm(
".syntax unified\n\t" 694 "LSLS" "\t%[p_crc], %[p_crc], #1\n\t" 696 "EORS" "\t%[p_crc], %[poly]\n" 698 : [p_crc]
"+&l" (p_crc)
699 : [poly]
"l" (get_top_polynomial())
702 if (p_crc & 0x80000000) {
703 p_crc = (p_crc << 1) ^ get_top_polynomial();
705 p_crc = (p_crc << 1);
722 static uint_fast32_t do_1_bit_reflected(uint_fast32_t p_crc)
724 #if MBED_CRC_ARM_THUMB2 725 __asm(
".syntax unified\n\t" 726 "LSRS" "\t%[p_crc], %[p_crc], #1\n\t" 728 "EORCS" "\t%[p_crc], %[poly]" 729 : [p_crc]
"+&r" (p_crc)
730 : [poly]
"rI" (get_reflected_polynomial())
732 #elif MBED_CRC_THUMB1 733 __asm(
".syntax unified\n\t" 734 "LSRS" "\t%[p_crc], %[p_crc], #1\n\t" 736 "EORS" "\t%[p_crc], %[poly]\n" 738 : [p_crc]
"+&l" (p_crc)
739 : [poly]
"l" (get_reflected_polynomial())
743 p_crc = (p_crc >> 1) ^ get_reflected_polynomial();
745 p_crc = (p_crc >> 1);
759 template<CrcMode mode_ = mode>
760 std::enable_if_t<mode_ == CrcMode::BITWISE, int32_t>
761 do_compute_partial(
const uint8_t *data, crc_data_size_t size, uint32_t *crc)
const 763 uint_fast32_t p_crc = *crc;
767 for (crc_data_size_t byte = 0; byte < size; byte++) {
771 for (
unsigned int bit = 8; bit > 0; --bit) {
772 p_crc = do_1_bit_reflected(p_crc);
777 for (crc_data_size_t byte = 0; byte < size; byte++) {
778 p_crc ^= (uint_fast32_t) data[byte] << 24;
781 for (
unsigned int bit = 8; bit > 0; --bit) {
782 p_crc = do_1_bit_normal(p_crc);
792 #if MBED_CRC_TABLE_SIZE > 0 800 template<CrcMode mode_ = mode>
801 std::enable_if_t<mode_ == CrcMode::TABLE, int32_t>
802 do_compute_partial(
const uint8_t *data, crc_data_size_t size, uint32_t *crc)
const 804 uint_fast32_t p_crc = *crc;
807 bool reflect = !_reflect_data;
809 for (crc_data_size_t byte = 0; byte < size; byte++) {
810 uint_fast32_t data_byte = data[byte];
812 data_byte = reflect_byte(data_byte);
814 #if MBED_CRC_TABLE_SIZE == 16 815 p_crc = _crc_table[(data_byte ^ p_crc) & 0xF] ^ (p_crc >> 4);
817 p_crc = _crc_table[(data_byte ^ p_crc) & 0xF] ^ (p_crc >> 4);
819 p_crc = _crc_table[(data_byte ^ p_crc) & 0xFF] ^ (p_crc >> 8);
834 template<CrcMode mode_ = mode>
835 std::enable_if_t<mode_ == CrcMode::HARDWARE, int32_t>
836 do_compute_partial(
const uint8_t *data, crc_data_size_t size, uint32_t *)
const 845 #if MBED_CRC_TABLE_SIZE > 0 851 const uint8_t MbedCRC<POLY_7BIT_SD, 7, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
854 const uint8_t MbedCRC<POLY_8BIT_CCITT, 8, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
857 const uint16_t MbedCRC<POLY_16BIT_CCITT, 16, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
860 const uint16_t MbedCRC<POLY_16BIT_IBM, 16, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
863 const uint32_t MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
865 #endif // MBED_CRC_TABLE_SIZE > 0 869 #endif // !defined(DOXYGEN_ONLY) 876 #endif // __cplusplus 882 uint32_t mbed_tiny_compute_crc32(
const void *data,
int datalen);
uint32_t final_xor
Final xor value for the computation.
void hal_crc_compute_partial_start(const crc_mbed_config_t *config)
Initialize the hardware CRC module with the given polynomial.
uint32_t width
CRC Bit Width.
void hal_crc_compute_partial(const uint8_t *data, const size_t size)
Writes data to the current CRC module.
bool reflect_out
Reflect bits in final result before returning.
uint32_t polynomial
CRC Polynomial.
x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
bool reflect_in
Reflect bits on input.
uint32_t initial_xor
Initial seed value for the computation.