# How to Calculate CRC on a structure?

cancel
Showing results for
Show  only  | Search instead for
Did you mean:
SOLVED

## How to Calculate CRC on a structure?

6,225 Views
Senior Contributor II

Hi

I am using built in CRC PE component to calculate CRC32 of an array which is coming fine but how do I do it for structure ?

char buffer[10] = "abcdefghij";

CRC1_GetBlockCRC(crc1, buffer, sizeof(buffer)-1, &crc_val);          //  This syntax gives the actual CRC value which I compared with the online CRC calculator

Why do we have to subtract 1 from sizeof ??

Secondly , I want to calculate the CRC as following.

typedef struct

{

uint32_t name;

float weight;

int32_t marks;

float average;

int32_t value;

uint32_t crc;

}LDD_Test;

LDD_Test TEST;

int main(void)

{

TEST.name = 0x41424344;

TEST.weight = 59.23;

TEST.marks = 530;

TEST.average = 46.58;

TEST.value = 120;

CRC1_GetBlockCRC(crc1, &TEST, sizeof(TEST)-5, &TEST.crc);// Get 32 bit CRC last 4 bytes of struct is CRC so excluding that. I have tested for ARRAY

FAT1_write(&fp1, &TEST, sizeof(TEST), &bw);

}

The above code is just for illustration. The CRC calculated by this is incorrect. My Query is how do we do operations on structure as we do for any strings or array ? Kindly help

Kind Regards

Amit Kumar

Labels (9)

• ### USB

Tags (8)
1 Solution
3,301 Views
Contributor V

Hi Amit,

I don't know what algorithm you use for CRC32, nor the seed you use (the crc1 parameter to your CRC1_GetBlockCRC() I guess), but I don't get the same CRC that you for your 47 bytes of data :

CA D0 41 42 43 44 45 46 47 48 49 50 51 52 53 54 51 07 12 1A D6 FE 1A BF 42 4E 31 3F B5 8C E3 41 17 22 01 3E 2A A8 EC 3E 22 20 79 3F 7A A8 1B

I get  E1 A9 8B B9 while you get  BE 39 93 2B

I use a standard CRC32 algorithm with its standard seed.

The code I used to compute the checksum is :

#include <sys/types.h>

#include <stdio.h>

// CRC32 computation

static u_int32_t Crc32_ComputeBuf(u_int32_t crc32, const void *buf, int buflen)

{

static const u_int32_t crcTable[256] = {

0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,

0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,

0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,

0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,

0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,

0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,0x26D930AC,

0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,

0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,

0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,

0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,

0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,

0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,

0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,0x4DB26158,0x3AB551CE,

0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,

0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,

0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,

0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,0xF00F9344,0x8708A3D2,0x1E01F268,

0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,

0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,

0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,

0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,

0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,

0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,

0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,

0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,

0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,

0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,

0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,

0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,

0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,

0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D };

unsigned char *pbuf = (unsigned char*)buf;

int i;

int iLookup;

for (i=0; i < buflen; i++) {

iLookup = (crc32 & 0xFF) ^ (*pbuf++);

crc32 = ((crc32 & 0xFFFFFF00) >> 8) & 0xFFFFFF;  // ' nasty shr 8 with vb :/

crc32 = crc32 ^ crcTable[iLookup];

}

return crc32;

}

u_int32_t crc32_of_buffer(const char *buf, int buflen)

{

return Crc32_ComputeBuf(0xFFFFFFFF, buf, buflen) ^ 0xFFFFFFFF;

}

int main() {

char buf[] = {0xCA, 0xD0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 0x51, 0x52, 0x53, 0x54, 0x51, 0x07, 0x12, 0x1A, 0xD6, 0xFE, 0x1A, 0xBF, 0x42, 0x4E, 0x31, 0x3F, 0xB5, 0x8C, 0xE3, 0x41, 0x17, 0x22, 0x01, 0x3E, 0x2A, 0xA8, 0xEC, 0x3E, 0x22, 0x20, 0x79, 0x3F, 0x7A, 0xA8, 0x1B};

printf("size=%d, CRC32=%08X\n", sizeof(buf), crc32_of_buffer(buf, sizeof(buf)));

return 0;

}

7 Replies
3,301 Views
Contributor V

Hi Amit,

char buffer[10] = "abcdefghij";

the string "abcdefghij" is not 10 bytes long but 11 bytes with the null character at the end, so probably your compiler has increased the size of buffer to 11 bytes instead of 10. So you need to use - 1 to compute the CRC only on the first 10 bytes (a to j).

To check the size of buffer, try to add :

printf("size : %d\n", sizeof(buffer));

Now for your structure, the problem is that the compiler can add so padding to the structure so the offset of crc (= number of bytes before crc) may not be sizeof(TEST) - 4.

Instead of using sizeof, you can ask the compiler the address of the crc for a structure that would be located at offset 0; this gives the number of bytes before the crc :

CRC1_GetBlockCRC(crc1, &TEST, &((LDD_Test *)0)->crc, &TEST.crc);

Also take care that due to possible padding between fileds of the structure (for alignment reasons), even if you set each field to a value, some bytes of the structure may be uninitialized.

This is the case if you declare a local variable of type LDD_Test in a function : this wariable will be allocated on the stack and these padding bytes will be uninitialized.

A good practice is to always clear all the structure before using it with :

memset(&TEST, 0, sizeof(TEST));

3,301 Views
Senior Contributor II

Hi Buloz

Thanks for responding. I used your syntax but still it didn't seems to work. my actual data length is 51 bytes in which last 4 bytes are the CRC. all are in bigendian format. below is the hex value which I am getting.

CA D0 41 42 43 44 45 46 47 48 49 50 51 52 53 54 51 07 12 1A D6 FE 1A BF 42 4E 31 3F B5 8C E3 41 17 22 01 3E 2A A8 EC 3E 22 20 79 3F 7A A8 1B BE 39 93 2B

I am using  #pragma pack(1) // To align the structure to 1 byte

before initializing the structure so that padding doesn't happen. I used sizeof function for printing the size of the structure and got 51 bytes as response.

#pragma pack(1) // To align the structure to 1 byte

typedef struct

{

uint64_t data1;

uint64_t data2;

uint8_t data3;

uint16_t data4;

uint32_t data5;

float data6;

float data7;

float data8;

float data9;

float data10;

float data11;

uint32_t crc;

}LDD_Test;

This is how the above data is. Is the CRC correct?I checked with the online CRC calculator and it didn't matched.

Kind regards

Amit Kumar

3,302 Views
Contributor V

Hi Amit,

I don't know what algorithm you use for CRC32, nor the seed you use (the crc1 parameter to your CRC1_GetBlockCRC() I guess), but I don't get the same CRC that you for your 47 bytes of data :

CA D0 41 42 43 44 45 46 47 48 49 50 51 52 53 54 51 07 12 1A D6 FE 1A BF 42 4E 31 3F B5 8C E3 41 17 22 01 3E 2A A8 EC 3E 22 20 79 3F 7A A8 1B

I get  E1 A9 8B B9 while you get  BE 39 93 2B

I use a standard CRC32 algorithm with its standard seed.

The code I used to compute the checksum is :

#include <sys/types.h>

#include <stdio.h>

// CRC32 computation

static u_int32_t Crc32_ComputeBuf(u_int32_t crc32, const void *buf, int buflen)

{

static const u_int32_t crcTable[256] = {

0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,

0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,

0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,

0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4,

0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C,

0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,0x26D930AC,

0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F,

0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,

0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,

0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,

0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,

0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA,

0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,0x4DB26158,0x3AB551CE,

0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,

0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,

0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,

0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,0xF00F9344,0x8708A3D2,0x1E01F268,

0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0,

0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8,

0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B,

0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,

0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,

0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,

0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,

0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE,

0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242,

0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6,

0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45,

0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,

0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,

0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D };

unsigned char *pbuf = (unsigned char*)buf;

int i;

int iLookup;

for (i=0; i < buflen; i++) {

iLookup = (crc32 & 0xFF) ^ (*pbuf++);

crc32 = ((crc32 & 0xFFFFFF00) >> 8) & 0xFFFFFF;  // ' nasty shr 8 with vb :/

crc32 = crc32 ^ crcTable[iLookup];

}

return crc32;

}

u_int32_t crc32_of_buffer(const char *buf, int buflen)

{

return Crc32_ComputeBuf(0xFFFFFFFF, buf, buflen) ^ 0xFFFFFFFF;

}

int main() {

char buf[] = {0xCA, 0xD0, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 0x51, 0x52, 0x53, 0x54, 0x51, 0x07, 0x12, 0x1A, 0xD6, 0xFE, 0x1A, 0xBF, 0x42, 0x4E, 0x31, 0x3F, 0xB5, 0x8C, 0xE3, 0x41, 0x17, 0x22, 0x01, 0x3E, 0x2A, 0xA8, 0xEC, 0x3E, 0x22, 0x20, 0x79, 0x3F, 0x7A, 0xA8, 0x1B};

printf("size=%d, CRC32=%08X\n", sizeof(buf), crc32_of_buffer(buf, sizeof(buf)));

return 0;

}

3,301 Views
Senior Contributor II

Hi Gilles

Thanks a lot man. this thing worked now I am getting the same value i.e from online CRC calculator and crc from this code matches.

Kind Regards

Amit Kumar

3,301 Views
Contributor V

Hi Amit,

I wont answer your question as I do not use PE, I have just a (maybe useful) note concerning the performance. Supposing you work with a 32-bit MCU, it is always good to have the fields of a structure aligned naturally, i.e. at 32-bit addresses. If #pragma pack() is needed to be used for correct CRC computation, then it is of course a valid reason for loosing a bit of performance. But what I would definitely do is reordering the variables so that the larger data types are aligned properly, as below:

#pragma pack(1) // To align the structure to 1 byte

typedef struct

{

uint64_t data1;

uint64_t data2;

uint32_t data5;

float data6;

float data7;

float data8;

float data9;

float data10;

float data11;

uint16_t data4;

uint8_t data3;

uint32_t crc;

}LDD_Test;

To correct/incorrect CRC computation, the only thing I would say is that I never needed to perform on multiple architectures simultaneously. That is in my opinion, in most of embedded applications, the CRC is always computed by the same processor, so there is often no need to ensure that the CRC is the same as some web-based CRC calculator gives you - typically you only need to be sure that CRC computed by your processor on the same data is always the same. But that of course depends on your application, just consider it. Sorry for not really helping.

3,301 Views
Senior Contributor II

Hi Petr

Thanks for the response. In my project I will be storing values to SD card (using microcontroller) and for reading I would be reading on PC. So in this case there are different devices calculating the CRC Thats why I am concern in getting the standard CRC values.

Kind Regards

Amit Kumar

3,301 Views
Contributor IV

Amit,

You might try using a Union instead of a structure.

http://www.programiz.com/c-programming/c-unions

John Baker