2016-09-22 8 views
3

Я пытаюсь создать CRC с аппаратным модулем STM32L4. Я хотел бы проверить файлы fatfs, так что в основном у меня есть байтовые массивы. Я использую этот CRC generator.Как установить STM32 для генерации стандартного CRC32

К сожалению, я не могу понять, как установить STM32L4 для создания того же результата. Мне нужно CRC32 и я

конфигурации:

hcrc.Instance = CRC; 

/* The default polynomial is not used. It is required to defined it in CrcHandle.Init.GeneratingPolynomial*/ 
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE; 
/* Set the value of the polynomial */ 
hcrc.Init.GeneratingPolynomial = 0x4C11DB7; 
//hcrc.Init.GeneratingPolynomial = 0xFB3EE248; 
hcrc.Init.CRCLength= CRC_POLYLENGTH_32B; 
/* The default init value is used */ 
/* The default init value is not used */ 
hcrc.Init.DefaultInitValueUse  = DEFAULT_INIT_VALUE_ENABLE; 

/* User init value is used instead */ 
//hcrc.Init.InitValue    = 0; 
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE; 
//hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE; 
/* The input data are inverted by word */ 
//hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_WORD; 

//hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE; 
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE; 
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; 
HAL_CRC_Init(&hcrc); 

испытание:

uint8_t test[] = {49,50,51,52}; 
uint32_t uwCRCValue = HAL_CRC_Calculate(&hcrc,(uint32_t *) test, 4); 

результат: A695C4AA

Я из идей. Существует один способ, которым я успешно с ним иметь uint32_t test[] и вход настроен на hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; К сожалению, у меня есть uint8_t ...

+0

Вы не забыли включить периферийные часы CRC? Ваш код не показывает его. – rost0031

+1

Вы прочитали соответствующее справочное руководство? Модуль CRC имеет расширенные настройки для разных случаев, связанных с проверкой подлинности. Если у вас есть правильный результат с uint32_t test [], так что проблема только в настройках настройки. – imbearr

+0

Спасибо за ваш ответ. Да, я проверил их (я использовал генератор кода CubeMX). Я прочитал справочное руководство. К сожалению, никакая комбинация настроек не дает мне никакого CRC32, вычисленного по стандартным алгоритмам. –

ответ

2

Используйте следующий код для известково СС32. CRC32 calc by STM32 CRC - это не то же самое, что наш стандартный CRC32, он использовал большой endian, и он не будет XOR с 0xFFFFFFFF.

u32 CRC32_ForBytes(u8 *pData, u32 uLen); 

#define UNUSED(x) ((void)(x)) 

/** 
* @brief CRC functions 
*/ 
#define __HAL_RCC_CRC_CLK_ENABLE() do { \ 
             __IO uint32_t tmpreg; \ 
             SET_BIT(RCC->AHBENR, RCC_AHBENR_CRCEN);\ 
             /* Delay after an RCC peripheral clock enabling */\ 
             tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_CRCEN);\ 
             UNUSED(tmpreg); \ 
             } while(0) 

#define __HAL_RCC_CRC_CLK_DISABLE()  (RCC->AHBENR &= ~(RCC_AHBENR_CRCEN)) 

#define CRC32_POLYNOMIAL      ((u32)0xEDB88320) 
#define RCC_CRC_BIT        ((u32)0x00001000) 


/** 
* @brief Calc CRC32 for data in bytes 
* @param pData Buffer pointer 
* @param uLen Buffer Length 
* @retval CRC32 Checksum 
*/ 
u32 CRC32_ForBytes(u8 *pData,u32 uLen) 
{ 
    u32 uIndex= 0,uData = 0,i; 
    uIndex = uLen >> 2; 

    __HAL_RCC_CRC_CLK_ENABLE(); 

    /* Reset CRC generator */ 
    CRC_ResetDR(); 

    while(uIndex--) 
    { 
#ifdef USED_BIG_ENDIAN  
     uData = __REV((u32*)pData); 
#else 
     ((u8 *)&uData)[0] = pData[0]; 
     ((u8 *)&uData)[1] = pData[1]; 
     ((u8 *)&uData)[2] = pData[2]; 
     ((u8 *)&uData)[3] = pData[3]; 
#endif   
     pData += 4; 
     uData = revbit(uData); 
     CRC->DR = uData; 
    } 
    uData = revbit(CRC->DR); 
    uIndex = uLen & 0x03; 
    while(uIndex--) 
    { 
     uData ^= (u32)*pData++; 
     for(i = 0;i < 8;i++) 
      if (uData & 0x1) 
      uData = (uData >> 1)^CRC32_POLYNOMIAL; 
      else 
      uData >>= 1; 
    } 

    __HAL_RCC_CRC_CLK_DISABLE(); 

    return uData^0xFFFFFFFF; 
} 

static u32 revbit(u32 uData) 
{ 
    u32 uRevData = 0,uIndex = 0; 
    uRevData |= ((uData >> uIndex) & 0x01); 
    for(uIndex = 1;uIndex < 32;uIndex++) 
    { 
     uRevData <<= 1; 
     uRevData |= ((uData >> uIndex) & 0x01); 
    } 
    return uRevData; 
} 

Calc ваш CRC32, как это:

u32 uwCRCValue = CRC32_ForBytes(&test, 4); 
+0

Благодарим вас за код. Моя основная цель заключалась в использовании аппаратного калькулятора. Я успешно сгенерировал такой же результат с этим алгоритмом на стороне ПК [код CRC32 C#] (https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DispForm.aspx?ID=44842&Source=/public/STe2ecommunities /mcu/Tags.aspx?tags=CRC32) На аппаратном сайте он работает с: 'uint32_t test [] = {49,50,51,52};' Но если я перехожу на: 'uint8_t test [] = {49,50,51,52};' результат изменился и до сих пор не может найти правильный алгоритм. Это может быть проблема с заполнением, но я использовал 4 байта для тестирования. Я закончил использовать контрольную сумму. –

0

Использование CubeMX, я сгенерировал с этими настройками:

hcrc.Instance = CRC; 
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE; 
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE; 
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE; 
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE; 
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES; 

Вычислить CRC так:

uint32_t crc = HAL_CRC_Calculate(&hcrc, (uint32_t *)address, length); 

И окончательно инвертировать:

crc = ~crc; 
+0

Привет! Спасибо вам за ваши предложения. К сожалению, я не могу попробовать ваше решение, проект уже не на моем столе. Насколько я помню, моя проблема заключалась в том, что я не могу воспроизвести тот же результат (CRC) как STM для того же входа на ПК. Пытался вычислить результат, например, с этого сайта http://www.sunshine2k.de/coding/javascript/crc/crc_js.html, но не может получить тот же результат. –

+0

И еще одна мысль пришла мне в голову. Я попытался использовать массив uint8_t как вход с параметром CRC_INPUTDATA_FORMAT_BYTES. Я не могу получить тот же результат, что и на ПК.Затем я использовал uint32_t массив с теми же 8-битными данными в нем и правильным результатом. Поэтому я закончил использовать более крупный параметр uint32_t [] вместо uint8_t [], и я мог бы использовать стандартный алгоритм вычисления на стороне ПК. –

+0

@hamzox У меня нет проблем, я опубликовал решение. С этими настройками вы получите тот же CRC, что и на ПК. Я знаю, что по умолчанию CRC с HAL отличается. –