This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CRC module in CC430.

Other Parts Discussed in Thread: CC430F5137, MSP430F5438A

Hi there,

I'm doing experiments on CRC module in CC430F5137. I'm comparing Software generated CRC and Hardware (CC430's CRC module) generated CRC, Somehow they are not matching.

Please let me know where I'm wrong.

??

Here is code:

/**************************************************************************
//
// crc16.c - generate a ccitt 16 bit cyclic redundancy check (crc)
//
// The code in this module generates the crc for a block of data.
//
**************************************************************************/

/*
// 16 12 5
// The CCITT CRC 16 polynomial is X + X + X + 1.
// In binary, this is the bit pattern 1 0001 0000 0010 0001, and in hex it
// is 0x11021.
// A 17 bit register is simulated by testing the MSB before shifting
// the data, which affords us the luxury of specifiy the polynomial as a
// 16 bit value, 0x1021.
// Due to the way in which we process the CRC, the bits of the polynomial
// are stored in reverse order. This makes the polynomial 0x8408.
*/

#include<msp430.h>
#include <stdlib.h>
#include <inttypes.h>
#include "CC430F5137.h"

#define POLY 0x8408

/*
// note: when the crc is included in the message, the valid crc is:
// 0xF0B8, before the compliment and byte swap,
// 0x0F47, after compliment, before the byte swap,
// 0x470F, after the compliment and the byte swap.
*/

unsigned int result_crc_SW;
unsigned int result_crc_HW;
/**************************************************************************
//
// crc16() - generate a 16 bit crc
//
//
// PURPOSE
// This routine generates the 16 bit remainder of a block of
// data using the ccitt polynomial generator.
//
// CALLING SEQUENCE
// crc = crc16(data, len);
//
// PARAMETERS
// data <-- address of start of data block
// len <-- length of data block
//
// RETURNED VALUE
// crc16 value. data is calcuated using the 16 bit ccitt polynomial.
//
// NOTES
// The CRC is preset to all 1's to detect errors involving a loss
// of leading zero's.
// The CRC (a 16 bit value) is generated in LSB MSB order.
// Two ways to verify the integrity of a received message
// or block of data:
// 1) Calculate the crc on the data, and compare it to the crc
// calculated previously. The location of the saved crc must be
// known.
/ 2) Append the calculated crc to the end of the data. Now calculate
// the crc of the data and its crc. If the new crc equals the
// value in "crc_ok", the data is valid.
//
// PSEUDO CODE:
// initialize crc (-1)
// DO WHILE count NE zero
// DO FOR each bit in the data byte, from LSB to MSB
// IF (LSB of crc) EOR (LSB of data)
// crc := (crc / 2) EOR polynomial
// ELSE
// crc := (crc / 2)
// FI
// OD
// OD
// 1's compliment and swap bytes in crc
// RETURN crc
//
**************************************************************************/
unsigned short crc16(data_p, length)
char *data_p;
unsigned short length;
{
unsigned char i;
unsigned int data;
unsigned int crc;

crc = 0xffff;

if (length == 0)
return (~crc);

do {
for (i = 0, data = (unsigned int)0xff & *data_p++; i < 8; i++, data >>= 1)
{
if ((crc & 0x0001) ^ (data & 0x0001))
crc = (crc >> 1) ^ POLY;
else
crc >>= 1;
}
} while (--length);

crc = ~crc;

data = crc;
crc = (crc << 8) | (data >> 8 & 0xFF);

return (crc);
}
void main(void)
{
int i;
char arr[10] = {'0','1','2','3','4','5','6','7','8','9'};
// Call func. to calc. CRC-CCITT
result_crc_SW = crc16(&arr[0], 10); // S/w generated CRC
CRCINIRES = 0x0FFFF;
for(i=0; i<10; i++)
{
    CRCDI= arr[i];
}

result_crc_HW = CRCINIRES; // H/w generated CRC
}

 

Thank you,

Rahul

  • Can you post the two values that you get?

  • Expression           Type                   Value(dec)       Address 

    result_crc_SW   unsigned int      5692                    0x001C02

    result_crc_HW   unsigned int     23350                   0x001C00

  • Unfortunately, the hardware CRC module uses reverse bit order compared to CCITT, which leads to completely different results. On most MSPs with CRC module, there are additional reverse registers for both, data and result. On some (like the 5438 non-A), these aren't available and you'll need to manually reverse the bit order of the data bytes, which eats up most of the speed advantage of the hardware CRC. However, the CC430 has these registers.

    So use CRCDIRB and CRCRESR instead of CRC16DI and CRCINIRES.

  • Thanks Michael,

             But As per your suggestions I changed,

    CRCDI= arr[i]-----> To---->CRCDIRB_L= arr[i]

    CRCINIRES = 0x0FFFF----> To ----> CRCRESR 0x0FFFF

     

    result_crc_HW = CRCINIRES---->To----> result_crc_HW = CRCRESR 

     

    Still the results are not matching!!

     

    Results:

    Expressions: 

    Expression              Type                   Value                      Address 

    result_crc_HW    unsigned int        0x0000 (Hex)          0x001C00
    result_crc_SW       unsigned int      0x163C (Hex)          0x001C02

    Registers: 

    CRCDI = 0x009C  

    CRCDIRB = 0x009C  

    CRCINIRES = 0xBD8F

    CRCRESR = 0x0000

    Please help me in understanding it.

    Regards,

    Rahul

     

     

     

  • Rahul SU said:
    CRCDI = 0x009C  
    CRCDIRB = 0x009C  
    CRCINIRES = 0xBD8F
    CRCRESR = 0x0000

    That's strange. Writing 0x009c to CRCDIRB is the same as writing 0x3900 to CRCDI.
    If CRCINIRES gives you 0xBD8F, then CRCRESR should return 0xF1BD.


    I tried the CRC module with both, inverted values writing to the normal, and normal values writing to the inverted registers, on an MSP430F5438A and got the same results as with an online CCITT CRC16 calculator or our software algorithm.
    So I know the CRC module works on the 5438(A).
    Any known errata in the errara sheet of your MSP?

  • Dint find errata for CRC. 

    Errata link: http://www.ti.com/lit/er/slaz094i/slaz094i.pdf

  • I need to correct my previous posts.

    Digging through my CRC code, I found the following function that IIRC has been tested for correct results.

    (I'm not 100% sure because I made most of this code when having a 5438 non-A without the inverse registers)

    unsigned short crc16(volatile unsigned char *sbuf,unsigned char len){
      CRCINIRES = 0xffff;
      while(len){
        CRCDIRB_L = (unsigned char) *sbuf;
        len--;
        sbuf++;
      }
      return CRCINIRES;
    }
    
    

    So it seems you have to init with CRCINIRES and load the result from there, but put the bytes into the reverse CRCDIRB_L register.

    The code above calculates the CRC byte-wise, not word-wise (hence the usage of CRCDIRB_L). I'm not sure whether CCITT byte order for 16 bit writes is the same as the MSP's integer byte order.

**Attention** This is a public forum