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" 32 #include <mstd_type_traits> 54 template<u
int32_t polynomial, u
int8_t w
idth, CrcMode mode>
57 constexpr
bool have_crc_table(uint32_t polynomial, uint8_t width)
59 #if MBED_CRC_TABLE_SIZE > 0 70 constexpr CrcMode choose_crc_mode(uint32_t polynomial, uint8_t width, CrcMode mode_limit)
74 mode_limit == CrcMode::HARDWARE && HAL_CRC_IS_SUPPORTED(polynomial, width) ? CrcMode::HARDWARE :
76 mode_limit <= CrcMode::TABLE && have_crc_table(polynomial, width) ? CrcMode::TABLE :
79 #endif // DOXYGEN_ONLY 147 template <u
int32_t polynomial = POLY_32BIT_ANSI, u
int8_t w
idth = 32, CrcMode mode_limit = CrcMode::HARDWARE>
149 impl::MbedCRC<polynomial, width, impl::choose_crc_mode(polynomial, width, mode_limit)> crc_impl;
155 HARDWARE = int(::mbed::CrcMode::HARDWARE),
157 TABLE = int(::mbed::CrcMode::TABLE),
158 BITWISE = int(::mbed::CrcMode::BITWISE)
161 typedef size_t crc_data_size_t;
179 MbedCRC(uint32_t initial_xor, uint32_t final_xor,
bool reflect_data,
bool reflect_remainder) :
180 crc_impl(initial_xor, final_xor, reflect_data, reflect_remainder)
187 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_32BIT_ANSI && w
idth == 32,
int> = 0>
188 constexpr MbedCRC() : MbedCRC(0xFFFFFFFF, 0xFFFFFFFF, true, true)
192 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_16BIT_IBM && w
idth == 16,
int> = 0>
193 constexpr MbedCRC() : MbedCRC(0, 0, true, true)
197 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_16BIT_CCITT && w
idth == 16,
int> = 0>
198 constexpr MbedCRC() : MbedCRC(0xFFFF, 0, false, false)
202 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_7BIT_SD && w
idth == 7,
int> = 0>
203 constexpr MbedCRC() : MbedCRC(0, 0, false, false)
207 template<u
int32_t poly = polynomial, std::enable_if_t<poly == POLY_8BIT_CCITT && w
idth == 8,
int> = 0>
208 constexpr MbedCRC() : MbedCRC(0, 0, false, false)
222 int32_t compute(
const void *buffer, crc_data_size_t size, uint32_t *crc)
224 return crc_impl.compute(buffer, size, crc);
248 int32_t compute_partial(
const void *buffer, crc_data_size_t size, uint32_t *crc)
250 return crc_impl.compute_partial(buffer, size, crc);
263 int32_t compute_partial_start(uint32_t *crc)
265 return crc_impl.compute_partial_start(crc);
277 int32_t compute_partial_stop(uint32_t *crc)
279 return crc_impl.compute_partial_stop(crc);
286 static constexpr uint32_t get_polynomial()
295 static constexpr uint8_t get_width()
301 #if !defined(DOXYGEN_ONLY) 305 template <u
int32_t polynomial, u
int8_t w
idth, CrcMode mode>
308 typedef size_t crc_data_size_t;
311 MbedCRC(uint32_t initial_xor, uint32_t final_xor,
bool reflect_data,
bool reflect_remainder) :
312 _initial_value(adjust_initial_value(initial_xor, reflect_data)),
313 _final_xor(final_xor),
314 _reflect_data(reflect_data),
315 _reflect_remainder(reflect_remainder)
317 static_assert(width <= 32,
"Max 32-bit CRC supported");
329 int32_t compute(
const void *buffer, crc_data_size_t size, uint32_t *crc)
333 status = compute_partial_start(crc);
338 status = compute_partial(buffer, size, crc);
343 status = compute_partial_stop(crc);
368 int32_t compute_partial(
const void *buffer, crc_data_size_t size, uint32_t *crc)
370 const uint8_t *data =
static_cast<const uint8_t *
>(buffer);
371 return do_compute_partial(data, size, crc);
384 int32_t compute_partial_start(uint32_t *crc)
387 if (mode == CrcMode::HARDWARE) {
391 config.
width = width;
401 *crc = _initial_value;
414 int32_t compute_partial_stop(uint32_t *crc)
417 if (mode == CrcMode::HARDWARE) {
418 *crc = hal_crc_get_result();
423 uint_fast32_t p_crc = *crc;
424 if (mode == CrcMode::BITWISE) {
427 if (!_reflect_remainder) {
428 p_crc = reflect_crc(p_crc);
432 p_crc = _reflect_remainder ? reflect(p_crc) : shift_right(p_crc);
436 if (!_reflect_remainder) {
437 p_crc = reflect_crc(p_crc);
442 p_crc &= get_crc_mask();
455 static constexpr uint32_t reflect_constant(uint32_t data)
458 return ((data & 0x00000001) << 31) |
459 ((data & 0x00000002) << 29) |
460 ((data & 0x00000004) << 27) |
461 ((data & 0x00000008) << 25) |
462 ((data & 0x00000010) << 23) |
463 ((data & 0x00000020) << 21) |
464 ((data & 0x00000040) << 19) |
465 ((data & 0x00000080) << 17) |
466 ((data & 0x00000100) << 15) |
467 ((data & 0x00000200) << 13) |
468 ((data & 0x00000400) << 11) |
469 ((data & 0x00000800) << 9) |
470 ((data & 0x00001000) << 7) |
471 ((data & 0x00002000) << 5) |
472 ((data & 0x00004000) << 3) |
473 ((data & 0x00008000) << 1) |
474 ((data & 0x00010000) >> 1) |
475 ((data & 0x00020000) >> 3) |
476 ((data & 0x00040000) >> 5) |
477 ((data & 0x00080000) >> 7) |
478 ((data & 0x00100000) >> 9) |
479 ((data & 0x00200000) >> 11) |
480 ((data & 0x00400000) >> 13) |
481 ((data & 0x00800000) >> 15) |
482 ((data & 0x01000000) >> 17) |
483 ((data & 0x02000000) >> 19) |
484 ((data & 0x04000000) >> 21) |
485 ((data & 0x08000000) >> 23) |
486 ((data & 0x10000000) >> 25) |
487 ((data & 0x20000000) >> 27) |
488 ((data & 0x40000000) >> 29) |
489 ((data & 0x80000000) >> 31);
504 #ifdef MSTD_HAS_IS_CONSTANT_EVALUATED 505 static constexpr uint32_t reflect(uint32_t data)
507 return mstd::is_constant_evaluated() ? reflect_constant(data) : __RBIT(data);
510 static uint32_t reflect(uint32_t data)
521 static MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
522 uint_fast32_t reflect_byte(uint_fast32_t data)
524 return reflect(data) >> 24;
531 static constexpr uint32_t get_reflected_polynomial()
533 return shift_right(reflect_constant(polynomial));
540 static constexpr uint32_t get_top_polynomial()
542 return shift_left(polynomial);
545 const uint32_t _initial_value;
546 const uint32_t _final_xor;
547 const bool _reflect_data;
548 const bool _reflect_remainder;
551 using crc_table_t = std::conditional_t<width <= 8, uint8_t,
552 std::conditional_t<width <= 16, uint16_t,
557 #if MBED_CRC_TABLE_SIZE > 0 559 static const crc_table_t _crc_table[MBED_CRC_TABLE_SIZE];
562 static constexpr uint32_t adjust_initial_value(uint32_t initial_xor,
bool reflect_data)
564 if (mode == CrcMode::BITWISE) {
569 return reflect_data ? reflect_crc(initial_xor) : shift_left(initial_xor);
570 }
else if (mode == CrcMode::TABLE) {
573 return reflect_crc(initial_xor);
584 if (mode == CrcMode::HARDWARE) {
585 mbed_crc_mutex->
lock();
595 if (mode == CrcMode::HARDWARE) {
605 static constexpr uint32_t get_crc_mask()
607 return (uint32_t)((uint32_t)2U << (width - 1)) - 1U;
615 static MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
616 uint32_t reflect_crc(uint32_t data)
618 return reflect(data) >> (32 - width);
626 static constexpr uint32_t shift_left(uint32_t data)
628 return data << (32 - width);
636 static constexpr uint32_t shift_right(uint32_t data)
638 return data >> (32 - width);
642 #if (defined __GNUC__ || defined __clang__) && \ 643 (defined __arm__ || defined __ARM_ARCH) 644 #if (__ARM_ARCH_7M__ == 1U) || \ 645 (__ARM_ARCH_7EM__ == 1U) || \ 646 (__ARM_ARCH_8M_MAIN__ == 1U) || \ 647 (__ARM_ARCH_8_1M_MAIN__ == 1U) || \ 648 (__ARM_ARCH_7A__ == 1U) 650 #define MBED_CRC_ARM_THUMB2 1 651 #define MBED_CRC_THUMB1 0 652 #elif (__ARM_ARCH_6M__ == 1U) || \ 653 (__ARM_ARCH_8M_BASE__ == 1U) 655 #define MBED_CRC_ARM_THUMB2 0 656 #define MBED_CRC_THUMB1 1 657 #else // __ARM_ARCH_xxx 658 #error "Unknown ARM architecture for CRC optimization" 659 #endif // __ARM_ARCH_xxx 660 #else // __arm__ || defined __ICC_ARM__ || defined __ARM_ARCH 662 #define MBED_CRC_ARM_THUMB2 0 663 #define MBED_CRC_THUMB1 0 678 static uint_fast32_t do_1_bit_normal(uint_fast32_t p_crc)
680 #if MBED_CRC_ARM_THUMB2 681 __asm(
".syntax unified\n\t" 682 "LSLS" "\t%[p_crc], %[p_crc], #1\n\t" 684 "EORCS" "\t%[p_crc], %[poly]" 685 : [p_crc]
"+&r" (p_crc)
686 : [poly]
"rI" (get_top_polynomial())
688 #elif MBED_CRC_THUMB1 689 __asm(
".syntax unified\n\t" 690 "LSLS" "\t%[p_crc], %[p_crc], #1\n\t" 692 "EORS" "\t%[p_crc], %[poly]\n" 694 : [p_crc]
"+&l" (p_crc)
695 : [poly]
"l" (get_top_polynomial())
698 if (p_crc & 0x80000000) {
699 p_crc = (p_crc << 1) ^ get_top_polynomial();
701 p_crc = (p_crc << 1);
718 static uint_fast32_t do_1_bit_reflected(uint_fast32_t p_crc)
720 #if MBED_CRC_ARM_THUMB2 721 __asm(
".syntax unified\n\t" 722 "LSRS" "\t%[p_crc], %[p_crc], #1\n\t" 724 "EORCS" "\t%[p_crc], %[poly]" 725 : [p_crc]
"+&r" (p_crc)
726 : [poly]
"rI" (get_reflected_polynomial())
728 #elif MBED_CRC_THUMB1 729 __asm(
".syntax unified\n\t" 730 "LSRS" "\t%[p_crc], %[p_crc], #1\n\t" 732 "EORS" "\t%[p_crc], %[poly]\n" 734 : [p_crc]
"+&l" (p_crc)
735 : [poly]
"l" (get_reflected_polynomial())
739 p_crc = (p_crc >> 1) ^ get_reflected_polynomial();
741 p_crc = (p_crc >> 1);
755 template<CrcMode mode_ = mode>
756 std::enable_if_t<mode_ == CrcMode::BITWISE, int32_t>
757 do_compute_partial(
const uint8_t *data, crc_data_size_t size, uint32_t *crc)
const 759 uint_fast32_t p_crc = *crc;
763 for (crc_data_size_t byte = 0; byte < size; byte++) {
767 for (
unsigned int bit = 8; bit > 0; --bit) {
768 p_crc = do_1_bit_reflected(p_crc);
773 for (crc_data_size_t byte = 0; byte < size; byte++) {
774 p_crc ^= (uint_fast32_t) data[byte] << 24;
777 for (
unsigned int bit = 8; bit > 0; --bit) {
778 p_crc = do_1_bit_normal(p_crc);
788 #if MBED_CRC_TABLE_SIZE > 0 796 template<CrcMode mode_ = mode>
797 std::enable_if_t<mode_ == CrcMode::TABLE, int32_t>
798 do_compute_partial(
const uint8_t *data, crc_data_size_t size, uint32_t *crc)
const 800 uint_fast32_t p_crc = *crc;
803 bool reflect = !_reflect_data;
805 for (crc_data_size_t byte = 0; byte < size; byte++) {
806 uint_fast32_t data_byte = data[byte];
808 data_byte = reflect_byte(data_byte);
810 #if MBED_CRC_TABLE_SIZE == 16 811 p_crc = _crc_table[(data_byte ^ p_crc) & 0xF] ^ (p_crc >> 4);
813 p_crc = _crc_table[(data_byte ^ p_crc) & 0xF] ^ (p_crc >> 4);
815 p_crc = _crc_table[(data_byte ^ p_crc) & 0xFF] ^ (p_crc >> 8);
830 template<CrcMode mode_ = mode>
831 std::enable_if_t<mode_ == CrcMode::HARDWARE, int32_t>
832 do_compute_partial(
const uint8_t *data, crc_data_size_t size, uint32_t *)
const 841 #if MBED_CRC_TABLE_SIZE > 0 847 const uint8_t MbedCRC<POLY_7BIT_SD, 7, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
850 const uint8_t MbedCRC<POLY_8BIT_CCITT, 8, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
853 const uint16_t MbedCRC<POLY_16BIT_CCITT, 16, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
856 const uint16_t MbedCRC<POLY_16BIT_IBM, 16, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
859 const uint32_t MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
861 #endif // MBED_CRC_TABLE_SIZE > 0 865 #endif // !defined(DOXYGEN_ONLY) 872 #endif // __cplusplus 878 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.