cancel
Showing results for 
Search instead for 
Did you mean: 

STM32Foxx CRC: usage of HAL Drivers

stanzanim
Associate III
Posted on April 15, 2016 at 14:34

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)

thanks
11 REPLIES 11
Nesrine M_O
Lead II
Posted on April 15, 2016 at 15:26

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 –

stanzanim
Associate III
Posted on April 15, 2016 at 15:47

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)

stanzanim
Associate III
Posted on April 18, 2016 at 14:27

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 :(
stanzanim
Associate III
Posted on April 18, 2016 at 14:43

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

Posted on April 18, 2016 at 15:16

 hcrc->Init.InitValue ?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stanzanim
Associate III
Posted on April 18, 2016 at 15:23

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 CRC

Here is a bit of code

static 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;

}
Posted on April 18, 2016 at 18:40

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);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 18, 2016 at 18:48

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&currentviews=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

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on April 18, 2016 at 18:50

Saving the overhead of a call, pushing one byte to the CRC hardware is done thusly

*((volatile unsigned char *)&CRC->DR) = byte_to_accumulate;
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..