2016-04-15 05:34 AM
I want to make the CRC progress as soon as I receive bytes so I want to calculate partial CRCs as soon as the packet is entering the system. Should I use
HAL_CRC_Accumulate with buffer size =1?I also deal with bytes incoming and want to get a 16 bit CRC. Should I simply cast to (uint_16 the 32 bit results)I cannot fing so many C example on the web ... some initial questions - how can I setup the peripheral to work with 8 bit data and generating a 16bit CRC?- how can I set a generator polynomial for MODBUS (0xA01 16 bits)? It looks like Cube MX 4,13 does not allow to disable automatic poly generation from the MX GUI ... see separate post). Or maybe the STM32F030K6 (target device) does not allow manual poly assignment (which is crazy, IMO)thanks2016-04-15 06:26 AM
Hi stanzani.marco,
I recommend you to have a look to the CRC examples under the STM32F0 cube firmware package it may be helpful: STM32Cube_FW_F0_V1.5.0\Projects\STM32091C_EVAL\Examples\CRC-Syrine –2016-04-15 06:47 AM
Thank you so much
I see in *crc_ex.c file that poly settings is under conditional compilation and I cannot see the L0 (DM0009101 document say yes)#if defined (STM32F071xB) || defined (STM32F072xB) || defined (STM32F078xx) || defined (STM32F091xC) || defined (STM32F098xx)
/** * @brief Initializes the CRC polynomial if different from default one. * @param hcrc: CRC handle * @param Pol: CRC generating polynomial (7, 8, 16 or 32-bit long) * This parameter is written in normal representation, e.g. * for a polynomial of degree 7, X^7 + X^6 + X^5 + X^2 + 1 is written 0x65 * for a polynomial of degree 16, X^16 + X^12 + X^5 + 1 is written 0x1021 * @param PolyLength: CRC polynomial length * This parameter can be one of the following values: * @arg CRC_POLYLENGTH_7B: 7-bit long CRC (generating polynomial of degree 7) * @arg CRC_POLYLENGTH_8B: 8-bit long CRC (generating polynomial of degree 8) * @arg CRC_POLYLENGTH_16B: 16-bit long CRC (generating polynomial of degree 16) * @arg CRC_POLYLENGTH_32B: 32-bit long CRC (generating polynomial of degree 32) * @retval HAL status */ HAL_StatusTypeDef HAL_CRCEx_Polynomial_Set(CRC_HandleTypeDef *hcrc, uint32_t Pol, uint32_t PolyLength)2016-04-18 05:27 AM
if I disable 'DEFAULT_INIT_VALUE' how do I specify which value the CRC starts?
Simply initializing the crc repostiroy? uint16_t compCrc = -1; HAL_CRC_Accumulate (&hcrc, &compCrc, 1); (I got a warning since the HAL_CRC_Accumulate is expecting a pointer to 32 bit integer :(2016-04-18 05:43 AM
Thanks but this example shows just one configuration (32 bit CRC with 32 bit input data and NOT 'various CRC configuration as the associated readme assert :( and no init value user specifie
2016-04-18 06:16 AM
hcrc->Init.InitValue ?
2016-04-18 06:23 AM
That's fine, thanks. But I am trying to use the HAL driver as reccomended everywhere
I am also struggling on how to instruct the peripheral to accepy bytes and generate 16 bit CRCHere is a bit of codestatic void interProcCommMgr(void)
{ // todo: inter character timeout and ibnter packet timeout static size_t rxCnt =0; static uint32_t compCrc=0;// 16bit CRC??
// start of packet if(rxBuff == STX) { rxCnt = 0; hcrc.Init.InitValue=-1;// cannot do by an HAL API??
compCrc = 0; } if(rxCnt<=3) HAL_CRC_Accumulate (&hcrc, &compCrc, 1);// compCrc must be 32 bit?
switch(rxCnt) { static uint8_t rxCrc; static uint16_t _tmpTargetSpeed = -1; case 1: // if not addressed ignore if(rxBuff !=_addr) return; break; case 2: _tmpTargetSpeed = (uint16_t) rxBuff; break; case 3: _tmpTargetSpeed += (uint16_t)(rxBuff<<CHAR_BIT); break; case 4: rxCrc = rxBuff; break; case 5: rxCrc += (uint16_t)(rxBuff<<CHAR_BIT); if((uint16_t)compCrc == rxCrc) { userInterfaceRegs.SYS_CTRL.bits.TVRPM = _tmpTargetSpeed; } else { userInterfaceRegs.SYS_CTRL.bits.TVRPM = (uint16_t) -1; // invalid } break; } rxCnt++; return;}2016-04-18 09:40 AM
I'm not using this platform, but this looks to be the mechanics you need to be applying
/*##-1- Configure the CRC peripheral #######################################*/
CrcHandle.Instance = CRC;
CrcHandle.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
CrcHandle.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLED;
CrcHandle.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE; // User specified below
CrcHandle.Init.InitValue = 0xFFFF;
CrcHandle.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE; // User specified below
CrcHandle.Init.CRCLength = CRC_POLYLENGTH_16B;
CrcHandle.Init.GeneratingPolynomial = ????; // Your polynomial
CrcHandle.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
/* DeInitializes the CRC peripheral */
HAL_CRC_DeInit(&CrcHandle);
/* Initialise CRC */
HAL_CRC_Init(&CrcHandle);
if(HAL_CRC_Init(&CrcHandle) != HAL_OK)
{
/* Initialization Error */
Error_Handler();
}
/*##-2- Compute the CRC of ''aDataBuffer'' ###################################*/
uwCRCValue = HAL_CRC_Accumulate(&CrcHandle, (uint32_t *)aDataBuffer, BUFFER_SIZE);
2016-04-18 09:48 AM
The use of hardware seems to be overkill it you are faffing about with it one byte at a time.
There is a small, and fast, table driven example of MODBUS CRC about half way down [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/CRC%20computation&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=5086]this thread.Faster algorithm using nibble table lookup, trade off between speed and size.
WORD Crc16ModbusFast(WORD Crc, BYTE Data) // sourcer32@gmail.com
{
static const WORD CrcTable[16] = { // Nibble lookup for 0xA001 polynomial
0x0000,0xCC01,0xD801,0x1400,0xF001,0x3C00,0x2800,0xE401,
0xA001,0x6C00,0x7800,0xB401,0x5000,0x9C01,0x8801,0x4400 };
Crc = Crc ^ Data;
// Process 8-bits, 4 at a time, or 2 rounds
Crc = (Crc >> 4) ^ CrcTable[Crc & 0xF];
Crc = (Crc >> 4) ^ CrcTable[Crc & 0xF];
return(Crc);
}
Could use a 256 entry table, but would eat 512 bytes of ROM/FLASH
2016-04-18 09:50 AM
Saving the overhead of a call, pushing one byte to the CRC hardware is done thusly
*((volatile unsigned char *)&CRC->DR) = byte_to_accumulate;