cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G0 CRC16 mismatch.

FRieb.1
Associate III

Hi,

I am trying to run the CRC calculation with the STM32G031 but the results do not match. The result of the CRC16_CCITT_FALSE should be 0x29B1 according to http://www.sunshine2k.de/coding/javascript/crc/crc_js.html but I get 0x277F.

You can find my implementation below.

unsigned short CRC_16Bit_Polynom(unsigned char *Data, unsigned char Size);
void CRC_Init(void);
 
int main(void)
{
    unsigned char Buffer[] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
    CRC_16Bit_Polynom(Buffer, 9);
}
 
void CRC_Init(void)
{
    RCC->AHBENR |= RCC_AHBENR_CRCEN;
    CRC->CR = 0x00000000;
    CRC->CR |= CRC_CR_POLYSIZE_0;
    CRC->INIT = 0xFFFF;
    CRC->POL =  0x1021;
}
 
unsigned short CRC_16Bit_Polynom(unsigned char *Data, unsigned char Size)
{
    unsigned short Ergebnis = 0;
    CRC->CR |= CRC_CR_RESET;
    for(unsigned char i = 1; i <= Size; i++)
    {
	CRC->DR = (unsigned short) *Data;
	Data++;
    }
    Ergebnis = (unsigned short)CRC->DR;
    return Ergebnis;
}

Please kindly help to find the mistake.

1 ACCEPTED SOLUTION

Accepted Solutions
#include <windows.h>
 
#include <stdio.h>
#include <stdlib.h>
 
#define POLY 0x1021
#define INIT 0xFFFF
 
int main(int argc, char **argv)
{
  int i, j, k;
  unsigned short crc;
  unsigned char test[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
 
  crc = INIT;
 
  for(j=0; j<sizeof(test); j++)
  {
    crc = crc ^ (test[j] << 8);
 
    for(i=0; i<8; i++)
    {
      if (crc & 0x8000)
        crc = (crc << 1) ^ POLY;
      else
        crc = (crc << 1);
    }
  }
 
  printf("crc=%04X\n", crc);
 
  return(1);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

View solution in original post

7 REPLIES 7

Sure you have the length loop right?

Shift direction and ending ordering?​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
FRieb.1
Associate III

Yes, the loop length is correct.

Do you mean the order in which the bytes are written to CRC->DR? Then I am not sure.

The "Reverse Input Data" and the "Reverse Output Data" should be right.

unsigned short for your compiler means uint16_t?

CRC->DR is usually defined as *(uint32_t*) i.e. essentially uint32_t.

> CRC->DR = (unsigned short) *Data;

Data you have declared as unsigned char * so *Data picks a byte, extends it to unsigned short (whatever that is), and then stores it into uint32_t register, i.e. it adds up 3x 0x00 to the the read data.

Read CRC operation subchapter of CRC chapter in RM.

JW

FRieb.1
Associate III

That's right unsigned short means uint16_t. CRC->DR is the 32 bit CRC data register configured for 16 bit polynomial.

> That's right unsigned short means uint16_t.

You still read bytes from the array, and advance pointer, byte-by-byte. The cast to uint16_t extends the byte by 0x00.

> CRC->DR is the 32 bit CRC data register configured for 16 bit polynomial.

But that does not mean CRC->DR acts as a 16-bit register. Writing a 16-bit value to CRC->DR as it's defined in the device header, i.e. 32-bit, means that the 16 bits (which was a byte extended by 0x00) is extended by further 0x0000.

Read CRC operation subchapter of CRC chapter in RM.

If you want to write CRC->DR as 16-bit, in C you need to cast:

*(volatile uint16_t *)&CRC->DR = 16-bit-value;

but you still need to assemble the bytes into 16-bit values.

Or, write byte by byte

*(volatile uint8_t *)&CRC->DR = *Data;

Less efficient, but should work OK, without the problems with outstanding data in odd-length buffers.

JW

while(Size--) *(volatile uint8_t *)&CRC->DR = *Data++;

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
#include <windows.h>
 
#include <stdio.h>
#include <stdlib.h>
 
#define POLY 0x1021
#define INIT 0xFFFF
 
int main(int argc, char **argv)
{
  int i, j, k;
  unsigned short crc;
  unsigned char test[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
 
  crc = INIT;
 
  for(j=0; j<sizeof(test); j++)
  {
    crc = crc ^ (test[j] << 8);
 
    for(i=0; i<8; i++)
    {
      if (crc & 0x8000)
        crc = (crc << 1) ^ POLY;
      else
        crc = (crc << 1);
    }
  }
 
  printf("crc=%04X\n", crc);
 
  return(1);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..