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.

CCS/TMS570LS0432: CCS CRC for image

Part Number: TMS570LS0432


Tool/software: Code Composer Studio

I'm trying to do a CRC on the flash chip image that I can embed in the image itself. At bootup and at run time I would periodically recheck the CRC for validity.

I've done this before when working on STM32F407 chips but don't see how to do it on the Hercules.

I'm using CCS 8.1.0 and a TMS570LS0432 processor.

Thanks!

    ken

  • To understand the support built into the linker for CRC, please search the ARM assembly tools manual for the sub-chapter titled Linker-Generated CRC Tables.  Several different CRC algorithms are supported.  Consult the documentation for your device to see which algorithm to use.

    Thanks and regards,

    -George

  • Thank you for your reply.

    I have implemented a post-link CRC as documented in Using the CRC Module on Hercules™-Based Microcontrollers, For a sanity check I implemented the software CRC algorithm in that same document. I tested the CRC on my smallest .obj file, ESP_het.obj, 40 bytes. The linker generated CRC and the calculated CRC do not match.

    Here's my modification of sys_link.cmd:

    MEMORY
    {
        VECTORS (X)  : origin=0x00000000 length=0x00000020
        KERNEL  (RX) : origin=0x00000020 length=0x00008000
        FLASHCRC(RW) : origin=0x00008020 length=0x00000020
        FLASH0  (RX) : origin=0x00008040 length=0x00057FC0
        STACKS  (RW) : origin=0x08000000 length=0x00000800
        KRAM    (RW) : origin=0x08000800 length=0x00000800
        RAM     (RW) : origin=(0x08000800+0x00000800) length=(0x00007800 - 0x00000800)
        
    /* USER CODE BEGIN (2) */
    /* USER CODE END */
    }

    SECTIONS
    {
        .intvecs : {} > VECTORS
        /* FreeRTOS Kernel in protected region of Flash */
        .kernelTEXT   : {} > KERNEL
        .cinit        : {} > KERNEL
        .pinit        : {} > KERNEL
        /* Rest of code to user mode flash region */
        .text         : {} > FLASH0
        .const        : {} > FLASH0
        /* FreeRTOS Kernel data in protected region of RAM */
        .kernelBSS    : {} > KRAM
        .kernelHEAP   : {} > RAM
        .bss          : {} > RAM
        .data         : {} > RAM    
        .sysmem       : {} > RAM
        FEE_TEXT_SECTION : {} > FLASH0
        FEE_CONST_SECTION : {} > FLASH0
        FEE_DATA_SECTION : {} > RAM
        
    /* USER CODE BEGIN (4) */
        .section_to_be_verified: { ESP_het.obj (.text) } > FLASH0, palign=8, fill=0xffffffff, crc_table(link_crc_table_name, algorithm = TMS570_CRC64_ISO)
        .TI.crctab: > FLASHCRC palign=8
    /* USER CODE END */
    }

    in my application I call:

    ...

    CRC_TABLE * pCrcTable = (CRC_TABLE *)0x00008020;
    uint64 crcLinkerGenerated = 0;
    uint64 crcSoftwareGenerated = 0;
    uint64 crcFullCpuGenerated = 0;

            // check code space crc:
            uint64 crc64 = 0;
            uint64 * pData = (uint64 *) pCrcTable->recs[0].addr;
            int i = 0;
            int nSize = pCrcTable->recs[0].size/sizeof(uint64);
            for (i=0; i<nSize; i++ )
            {
                crc64 = crc_update_word(crc64, pData[i]);
            }
            crcLinkerGenerated = pCrcTable->recs[0].crc_value;
            crcSoftwareGenerated = crc64;

    ...

    Here's the crc_update_word() function that I copied from Using the CRC Module on Hercules™-Based Microcontrollers:

    uint64 crc_update_word(uint64 crc64, uint64 data)
    {
        int i, j;
        uint64 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 & 0xfffffffffffffffeULL) | ((crc64 >> 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 & ~(1ULL << j)) | ((((crc64 >> (j - 1)) ^ (crc64 >> 63) ^ (data >> i)) & 1) << j);
                }
                else
                {
                    // when others =>
                    // NEXT_CRC_VAL(j) := CRC_VAL(j - 1);
                    nextCrc = (nextCrc & ~(1ULL << j)) | (((crc64 >> (j - 1)) & 1) << j);
                } // end case;
            } // end loop;
            crc64 = nextCrc;
        } // end loop

        return crc64;
    }

    I have verified the contents of pCrcTable.

    crcLinkerGenerated     = 0x7F1C5537E7A6B66C

    crcSoftwareGenerated = 0x7FC9F101E774C99A

    Do you have any suggestions?

            ken

     

  • OK, issue resolved...

    I tried the software CRC check as a first attempt to validate the linker-generated CRC. My intention was to ultimately use the CPU-generated CRC. I went ahead and implemented the CPU-generated CRC and low and behold it matches! The software-CRC generation function that I copied verbatim from the TI documentation is faulty.

    Since I was unable to find a comprehensive description of CPU-generated CRC I figured it out myself. Here are step-by-step instructions:

    1. Create Linker-generated CRC:
    1.1. In sys_link.cmd, MEMORY {} create a memory region for the CRC structure:

               FLASHCRC(RW) : origin=0x00008020 length=0x00000020

               in my case I placed it at the address previously assigned to FLASH0, and moved
               the starting address of FLASH0 by 32 (0x20):

               FLASH0  (RX) : origin=0x00008040 length=0x00057FC0

    1.2. In sys_link.cmd, SECTIONS {} generate the CRC structure and do the calculation:

        .section_to_be_verified: { *(.text) } > FLASH0, palign=8, fill=0xffffffff, crc_table(link_crc_table_name, algorithm = TMS570_CRC64_ISO)
        .TI.crctab: > FLASHCRC palign=8

    2. in my run-time code:

            extern CRC_TABLE link_crc_table_name;
            CRC_TABLE * pCrcTable = &link_crc_table_name;
            uint64 crcLinkerGenerated = pCrcTable->recs[0].crc_value;
            uint64 crcFullCpuGenerated = 0;
            crcModConfig_t CrcModConfig;

            CrcModConfig.mode = CRC_FULL_CPU;
            CrcModConfig.crc_channel = 0;
            CrcModConfig.data_length = pCrcTable->recs[0].size/sizeof(uint64);
            CrcModConfig.src_data_pat = (uint64 *) pCrcTable->recs[0].addr;

            crcInit();
            crcChannelReset(crcREG, 0);
            crcSignGen(crcREG, &CrcModConfig);
            crcFullCpuGenerated = crcGetPSASig(crcREG, 0);

            if (crcLinkerGenerated != crcFullCpuGenerated)
            {
                // do error handling here!
            }

    I hope this step-by-step guide helps others out there...

    Best...

            ken