Skip to main content
FRieb.1
Associate II
February 15, 2022
Solved

STM32G0 CRC16 mismatch.

  • February 15, 2022
  • 5 replies
  • 2199 views

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.

This topic has been closed for replies.
Best answer by Tesla DeLorean
#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);
}

5 replies

Tesla DeLorean
Guru
February 15, 2022

Sure you have the length loop right?

Shift direction and ending ordering?​

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
FRieb.1
FRieb.1Author
Associate II
February 15, 2022

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.

waclawek.jan
Super User
February 15, 2022

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
FRieb.1Author
Associate II
February 15, 2022

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

waclawek.jan
Super User
February 15, 2022

> 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

Tesla DeLorean
Guru
February 15, 2022

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

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