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.

A question about CRC module of MSP430F5438

Other Parts Discussed in Thread: MSP430F5438, MSP430F5438A

Hi,

Currently, I have a problem with the on-chip CRC module of MSP430F5438.  After shifting data into CRC  data in register CRCDI, I am not able to obtain the correct result from the result register CRCINIRES.

My testing codes are listed below, and in my codes, I would like to use the CRC module to generate the checksum of a string "12".

 

(1) Testing code 1

    CRCINIRES = 0xFFFF;    // Initialize CRC module
    CRCDI = 0x31;                  // Put '1' into the data in register
    CRCDI = 0x32;                  // Put '2' into the data in register

The result from CRCINIRES register is equal to 0x5e6b.

(2) Testing code 2

    CRCINIRES = 0xFFFF;    // Initialize CRC module
    CRCDI = 0x3132;             // Put '1' and '2' into the data in register

The result from CRCINIRES register is equal to 0x05aa.

 

(3) Testing code 3

    CRCINIRES = 0xFFFF;    // Initialize CRC module
    CRCDI = 0x3231;             // Put '1' and '2' into the data in register

The result from CRCINIRES register is equal to 0xcab2.

None of above results is equal to the checksum calculated by a CRC 16 CCITT calculator, which I downloaded from a website. The checksum of string "12" from that calculator is 0x3DBA.

So, I think I made some mistakes about the sequence of putting data into the data in register.

Any help will be appreciated!

Thanks!

Liu

  • The CRC module is shifting the bits in the opposit direction of CRC16 CCITT.

  • Testing code 1-revised:

    CRCINIRES = 0xFFFF; // Initialize CRC module

    CRCDI_L = 0x8C; // Put '1' (in revers bit order) into the data in register

    CRCDI_L = 0x4C; // Put '2' (in revers bit order) into the data in register

    Note: your compiler might complain that CRCDI_L is undefined. In that case, you need to dig out how CRCDI is declared any try to declare CRCDI_L similarly -- instead of something something int CRCDI, make it something something char CRCDI_L.

    Note also that '1' is hex 31 or binary 00110001. When you reverse the order of the binary, it becomes 10001100 or hex 8C. Similarly, '2' is hex 32 or binary 00110010. When you flip the order of the binary, it becomes 01001100 or hex 4C.

  • FYI, our upcoming MSP430F5438A (and other) devices will support the bit order that is commonly used via two new registers called CRCDIRB and CRCRESR. See the MSP430F5xx Family User's Guide for more details.

    Regards,
    Andreas

  • Hi andre,

    will we also see CRC support in CCS4 in the future (like IAR has already)?
    Rgds
    aBUGSworstnightmare

  • Adding this feature is on our radar screen however it isn't likely to happen in near future. In the meantime, there are ways to work around this. For example, if you want to use a CRC checksum to do a memory check at run-time you could do the following:

    1) Create a global const variable to hold your checksum and give it some arbitrary initial value (e.g., const unsigned int flashChecksum = 0x0000). Locate it outside the memory area you want to cover with the checksum. You could create and use a dedicated linker section for this.

    2) Add a checksum routine to your code that uses a combination of the MSP430F5438's CRC and DMA module (for efficiency) to calculate the checksum, and compare the result against flashChecksum. This should fail the first time you run since flashChecksum doesn't match the calculated CRC. Simply set a breakpoint there to obtain the value that flashChecksum should have had.

    3) Then, hard-code the CRC value calculated by the MSP430 during the debug session into your application code and re-compile the project making no other changes.

    4) From now on, the checksums should match. Of course this procedure needs to be repeated after any change you make to the source code. But during development you could use some #if/#endif statements to ignore the checksum mismatch in your code, and only go through the procedure for the final build.

    There are other ways of doing this as well, but you get the point.

    Thanks and Regards,
    Andreas

  •   Follow up  example:

    CRCINIRES = 0xFFFF; // Initialize CRC module

    CRCDI_L = 0x80;  // Put 1 (in revers bit order) into the data in register

    CRCINIRES  register  value  might   equal  '0x1021'    ;

    but  infact  value is ' 0xF1D1'

    why ?

     

     

  • I too was happy to see the CRC module in the 54xx, jus tto learn that it is pretty much useless if you want to be CCITT compatible.

    I implemented several different algorithms for the bit-reversing and found that the plain software solution isn't much slower than any small bitreversing solution.

    What I did:

    Plain software CRC: 100% (86 bytes/41 clock cycles per databyte)
    Hardware CRC with software inversion: 146% (62 bytes, 28 clock cycles per databytes)
    Hardware CRC with nibble table inversion: 152% (60 bytes + 32 bytes table, 27 clock cycles per databyte)
    Hardware CRC with full table inversion: 273% (36 bytes + 256 bytes table, 15 clock cycles per databyte)
    Hardware CRC assuming the inverse registers in the 54xxA: 410% (26 bytes, 10 clock cycles per databytes)

    You see, the hardware CRC isn't that big a step if you cannot use the 'right' bit order.

    Here's the software implementation, fi you want it.

    unsigned short crc16(volatile unsigned char *sbuf,unsigned char len){
        unsigned short crc=0xFFFF;

        while(len){
            crc=(unsigned char)(crc >> 8) | (crc << 8);
            crc^=(unsigned char) *sbuf;
            crc^=(unsigned char)(crc & 0xff) >> 4;
            crc^=(crc << 8) << 4;
            crc^=((crc & 0xff) << 4) << 1;
            len--;
            sbuf++;
        }
        return crc;
    }//crc16()

    bo-fu fuxiaobo said:
    but  infact  value is ' 0xF1D1' why ?

    Well, are you sure you di the right test? The result might be correct for 0x0001 (writing 0x8000 to CRCDI) but not for 0x01 (I haven't checked).

    With my functions, I always got the correct result.

     

**Attention** This is a public forum