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.

TMS570LC4357: CRC Algorithm

Part Number: TMS570LC4357
Other Parts Discussed in Thread: TEST2

Hello,

I'm testing the CRC module and noticed, that the calculated values differ between the method using two 32 bit words and the 64 bit method implemented in the SafeTI Diagnostic Library. I compared the results with a SW-calculated method posted by Richard Burke in this thread ( https://e2e.ti.com/support/microcontrollers/hercules/f/312/p/104764/368714#368714 ), but the result also differs from the other methods.

Before every test using the CRC module, I reset the module, which sets the start value to 0, and sets the CRC unit to "Full CPU Mode".

Here is my Code:

#define CRC_CTRL0     (*(volatile uint32 *)0xFE000000U)
#define CRC_CTRL2     (*(volatile uint32 *)0xFE000010U)
#define CRC_SIGREG    (*(volatile uint64 *)0xFE000060U)

/* Function from SafeTI Diagnostic Library (sl_misc.c) */
/*SAFETYMCUSW 61 D MR: 8.10,8.11 <APPROVED> Comment_1*/
uint64 SL_CRC_Calculate (uint64* startAddr, const uint32 count64)
{
  volatile uint32 count = 0u; /* volatile in order to prevent from being optimised */

  CRC_CTRL0 |= 0x00000001U; /* Reset the CRC Module */
  CRC_CTRL0 &= 0xFFFFFFFEU;
  CRC_CTRL2 |= 0x00000003U; /* Configure to Full CPU Mode */

  /*SAFETYMCUSW 134 S MR: 12.2 <APPROVED> Comment_5*/
  /*SAFETYMCUSW 134 S MR: 12.2 <APPROVED> Comment_5*/
  for (count=0u; count < count64; count++) {
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> Comment_2*/
    /*SAFETYMCUSW 93 S MR: 6.1,6.2,10.1,10.2,10.3,10.4 <APPROVED> "LDRA Tool issue" */
    CRC_SIGREG = (uint64)(*startAddr);
    /*SAFETYMCUSW 45 D MR:21.1 <APPROVED> Comment_2*/
    /*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Pointer increment needed" */
    startAddr++;
  }
    return(CRC_SIGREG);
}

/* Example for manual implementation by Richard Burke */
typedef uint64 crc_t;
crc_t crc_update_word(crc_t crc, crc_t data)
{
    int i, j;
    crc_t nextCrc = 0;
    // for i in 63 to 0 loop
    for(i = 63; i >= 0; i--)
    {
        // NEXT_CRC_VAL(0) := CRC_VAL(63) xor DATA(i);
        nextCrc = (nextCrc & (crc_t)0xfffffffffffffffe) | ((crc >> 63) ^ (data >> i));
        // for j in 1 to 63 loop
        for(j = 1; j < 64; j++)
        {
            //case j is
            // when 1|3|4 =>
            if(j == 1 || j == 3 || j == 4)
            {
                // NEXT_CRC_VAL(j) := CRC_VAL(j - 1) xor CRC_VAL(63) xor DATA(i);
                nextCrc = (nextCrc & ~((crc_t)1 << j)) | ((((crc >> (j-1)) ^ (crc >> 63) ^ (data >> i)) & 1) << j);
            }
            else
            { // when others =>
                // NEXT_CRC_VAL(j) := CRC_VAL(j - 1);
                nextCrc = (nextCrc & ~((crc_t)1 << j)) | (((crc >> (j-1)) & 1) << j);
            }
            // end case;
        } // end loop;
        crc = nextCrc;
    } // end loop

    return crc;
}

void crc_test(void)
{
  uint64 crc_test_value = 0x8DF8A32C74B91F3E;

  uint64 result_crc_manual = 0U;
  uint64 result_crc_safe_ti_lib = 0U;
  uint64 result_crc_test1 = 0U;
  uint64 result_crc_test2 = 0U;

  crcInit();  /* Sets everything to zero and enables Full CPU Mode */

  result_crc_manual = crc_update_word(0U, crc_test_value);

  result_crc_safe_ti_lib = SL_CRC_Calculate(&crc_test_value, 1U);

  /* test1: words not swapped */
  crcInit();
  crcREG1->PSA_SIGREGH1 = (uint32)(crc_test_value >> 32);
  crcREG1->PSA_SIGREGL1 = (uint32)crc_test_value;
  result_crc_test1 = crcGetPSASig(crcREG1, 0);

  /* test2: words swapped */
  crcInit();
  crcREG1->PSA_SIGREGH1 = (uint32)crc_test_value;
  crcREG1->PSA_SIGREGL1 = (uint32)(crc_test_value >> 32);
  result_crc_test2 = crcGetPSASig(crcREG1, 0);

  while(1);
}

Here are the results:

result_crc_manual = 0x2646CED073922BFD
result_crc_safe_ti_lib = 0x2646CEB873922B5F
result_crc_test1 = 0x739225063C91C898
result_crc_test2 = 0x2646CBAC3105924B

I expected, that result_crc_manual, result_crc_safe_ti_lib and result_crc_test1 or ...2 should be the same, so what could be wrong with my test?


Thanks and regards,

Jens

  • Hello,

    does anyone have an Idea why my SW-calculated CRC differs from the HW-calculated CRC?

    Thanks and regards,

    Jens

  • Hi Jens,

    I am looking into this and trying to understand the difference between the two C functions and the test routine. I will get back to you today.

    Regards,
    Sunil
  • Hi Sunil,

    any news about this? Thanks in advance!

    Regards,

    Jens

  • Hi Jens,

    Sorry for taking so long to answer.

    I am not sure about the manual implementation from Richard Burke, as I have not tested it. I know for sure that the pycrc (https://pycrc.org/) generates a result that matches the output of the TMS570 CRC module.

    As for the crc_test1 and crc_test2, note that the PSA register computes a signature based on the content of the 64-bit value comprised of the PSA_SIGREGLx and PSA_SIGREGHx registers any time the CPU writes to these registers. In your tests you write two separate 32-bit values to these individual registers. Each of these writes triggers a signature computation that overwrites the contents of the signature register, thereby overwriting that you just wrote to the particular register. This is why you end up computing a signature completely different from what is generated using a 64-bit write to the PSA signature register.

    Regards,
    Sunil