STM32 подсчёт CRC32 массива по частям

Подскажите плз, в чем проблема, не сходится CRC массива при подсчете по частям, код ниже

     uint8_t arr[] =
  {
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
    0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
    0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD
  };

  uint32_t crc_check_sum = 0;

  crc_check_sum = CRC_Calc(arr, sizeof(arr), DEFAULT_INIT_VALUE_ENABLE);
  printf("________CRC_Calc: 0x%x\r\n", crc_check_sum);

  uint8_t arr_1[] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
  uint8_t arr_2[] = {0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB};
  uint8_t arr_3[] = {0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC};
  uint8_t arr_4[] = {0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD};

  uint32_t div_crc = 0; 
  uint32_t temp_crc = 0; 

  div_crc = CRC_TEST_Calc(arr_1, sizeof(arr_1), 0xFFFFFFFFU);

  temp_crc = div_crc;
  div_crc = CRC_TEST_Calc(arr_2, sizeof(arr_2), temp_crc);

  temp_crc = div_crc;
  div_crc = CRC_TEST_Calc(arr_3, sizeof(arr_3), temp_crc);

  temp_crc = div_crc;
  div_crc = CRC_TEST_Calc(arr_4, sizeof(arr_4), temp_crc);

  temp_crc = div_crc;
  printf("temp_crc: 0x%x\r\n", temp_crc);
  
  temp_crc = ~div_crc;
  printf("~temp_crc: 0x%x\r\n", temp_crc); 

реализация функций:

void CRC_TEST_Init(uint32_t initValue)
{
  crc_hcrc.Instance = CRC;
  __HAL_RCC_CRC_CLK_ENABLE();
  crc_hcrc.Init.DefaultPolynomialUse    = DEFAULT_POLYNOMIAL_ENABLE;
  crc_hcrc.Init.DefaultInitValueUse     = DEFAULT_INIT_VALUE_DISABLE;
  crc_hcrc.Init.InitValue               = initValue;
  crc_hcrc.Init.InputDataInversionMode  = CRC_INPUTDATA_INVERSION_BYTE;
  crc_hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
  crc_hcrc.Init.CRCLength               = CRC_POLYLENGTH_32B;
  crc_hcrc.InputDataFormat              = CRC_INPUTDATA_FORMAT_BYTES;
  if (HAL_CRC_Init(&crc_hcrc) != HAL_OK)
  {
    Error_Handler();
  }
}

    
uint32_t CRC_TEST_Calc(uint8_t * data, uint32_t size, uint32_t initValue)
{
  CRC_TEST_Init(initValue);
  CRPT_CksumStart();

  uint32_t res = HAL_CRC_Calculate(&crc_hcrc, (uint32_t *)data, size);

  return res;
}

uint32_t CRC_Calc(uint8_t * data, uint32_t size, uint32_t initValue)
{
  CRC_TEST_Init(initValue);
  CRPT_CksumStart();

  uint32_t res = HAL_CRC_Calculate(&crc_hcrc, (uint32_t *)data, size);

  return ~res;
}

Ответы (1 шт):

Автор решения: Embedder

Во-первых, у вас задаются разные начальные значения при инициализации расчётов. В первом случаи DEFAULT_INIT_VALUE_ENABLE. Во втором - 0xFFFFFFFFU.

crc_check_sum = CRC_Calc(arr, sizeof(arr), DEFAULT_INIT_VALUE_ENABLE);
div_crc = CRC_TEST_Calc(arr_1, sizeof(arr_1), 0xFFFFFFFFU);
    

Макрос DEFAULT_INIT_VALUE_ENABLE определён в stm32f7xx_hal_crc.h (у вас может быть другая серия, но сути это не меняет) следующим образом:

#define DEFAULT_INIT_VALUE_ENABLE  ((uint8_t)0x00U) /*!< Enable initial CRC default value  */
#define DEFAULT_INIT_VALUE_DISABLE ((uint8_t)0x01U) /*!< Disable initial CRC default value */

Во-вторых, отключите output bit-reversing при расчёте crc для 1, 2 и 3 массивов. Оставьте его включённым только для 4 массива.

// CRC_TEST_Init
// crc_hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
div_crc = CRC_TEST_Calc(arr_1, sizeof(arr_1), 0xFFFFFFFFU);

// CRC_TEST_Init
// crc_hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
div_crc = CRC_TEST_Calc(arr_2, sizeof(arr_2), temp_crc);

// CRC_TEST_Init
// crc_hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
div_crc = CRC_TEST_Calc(arr_3, sizeof(arr_3), temp_crc);

// CRC_TEST_Init
// crc_hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
div_crc = CRC_TEST_Calc(arr_4, sizeof(arr_4), temp_crc);
→ Ссылка