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.

How to store checksum at a permanent flash adress

Using Tiva TM4C123G development board I have implemented a CRC16 based calculation memory. All fine.

However I would like perform this checksum test on my internal flash and internal eeprom.

I am using Code Composer Studio v5.5. I have not found anyway that CCS can calculate the CRC and put it in a specific adress. So my idéa was the the MCU makes the first boot after software download and checks if we have a CRC that is other than 0xFFFF. If we read 0xFFFF at CRC adress we calc the new checksum and write it down to flash. All other times the checksum will be compared. New release will overwrite previous checksum adress with 0xFFFF.

I do already know how to calculate checksum. The problem is what linker commands or synthax do u use to allocate and get access to this CRC storage in my flash memory. 

What could I write in startup_css.c and main.c to save and read my crc "variable" at this static adress. Could you please provide a code example that also shows how to reach it from main.c

  • Hello Thomas

    You can define a section in the code where CRC variable is stored and map the same in the cmd file as a section of Flash Address

    Regards

    Amit

  • Hi,

    Please also check/search the forum, there is one example posted for someone else; this example computes the CRC at the link time and checks it at run time.

    I have no record of the link at the moment, no time to search until tomorrow.

    Petrei 

  • Since no working example or correct answer..

    Here comes my solution of how I solved it.

    I added this to linker_ccs.cmd:

    //(MEMORY)

    CRCFLASH (RX) : origin = 0x00039600, length = 0x00000400 //1024 bytes one single erasable sector

    //(SECTION)

    .flashcrc :> CRCFLASH

    I added this to my test_flash.c that is called from main.c, at bootup InitFlashCRC() and then -------CheckFlashCRC(SysCtlFlashSizeGet()

    #include <stdio.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include "inc/hw_types.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/flash.h"
    #include "driverlib/debug.h"
    #include "test_flash.h"
    
    //*****************************************************************************
    //
    //! The CRC-16 table for polynomial 0xA001 (standard CRC-16, aka IBM CRC-16).
    //!
    //! This table should be loaded into FLASH memory.
    //
    //*****************************************************************************
    static const unsigned short g_usCRCTab16[256] =
    {
        0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
        0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
        0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
        0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
        0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
        0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
        0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
        0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
        0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
        0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
        0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
        0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
        0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
        0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
        0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
        0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
        0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
        0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
        0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
        0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
        0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
        0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
        0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
        0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
        0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
        0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
        0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
        0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
        0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
        0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
        0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
        0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
    };
    
    //*****************************************************************************
    //
    // The macro executes one iteration of the 16-bit CRC
    //
    //*****************************************************************************
    #define CRC_ITER(crc, data)     crc = ((crc >> 8) ^                         \
                                           g_usCRCTab16[(unsigned char)(crc ^   \
                                                                       (data))])
    //*****************************************************************************
    //
    //! Storage for the FLASH CRC, initialized to all ones so that it can be
    //! initialized either by a post-processing of the binary image, or at the
    //! first time the CRC code is run on the board after programming.
    //! We need 3 unsigned short values, but use 2 unsigned long values to ensure
    //! word alignment of the data in FLASH memory so that the subsequent
    //! programming of the actual CRC value will work properly.
    //*****************************************************************************
    
    #pragma DATA_SECTION (g_ulImageCRC, ".flashcrc")
    const unsigned long g_ulImageCRC[2] = { 0xffffffff, 0xffffffff };
    //*****************************************************************************
    //
    //! Macro to define the starting address of the CRC table.
    //
    //*****************************************************************************
    #define CRC_TABLE_START     ((unsigned long)&g_ulImageCRC[0])
    //*****************************************************************************
    //
    //! Macro to define the first address past the CRC table.
    //
    //*****************************************************************************
    #define CRC_TABLE_END       (CRC_TABLE_START + sizeof(g_ulImageCRC))
    //*****************************************************************************
    //
    //! Macro to define the size of the CRC table.
    //
    //*****************************************************************************
    #define CRC_TABLE_SIZE      (sizeof(g_ulImageCRC))
    #define CRC_SIGNATURE 0x01EC //Any valid 16 bits magic number
    //*****************************************************************************
    //
    //! Compute and check CRC for FLASH memory region.
    //!
    //! \param ulBytes is the number of bytes to be calculated during this
    //! iteration.
    //!
    //! This function will perform a check of the FLASH CRC for the specified
    // number of bytes.  A base address for the calculation is maintained and
    // updated each time the routine is called.  If the address being read is
    // in the range of the stored CRC table, it will be skipped.  If the address
    // reaches the end of the FLASH memory, the computed CRC value will be
    // compared against the stored value.  If the comparison matches, or if
    // the test loop has not yet reached the end of FLASH memory, the function
    // will return true for success.  Only if the end of FLASH memory has been
    // reached and the comparison fails will the function return a false for
    // failure. 
    //
    //! \return Returns true if the test passes, false otherwise.
    //
    //*****************************************************************************
    bool
    CheckFlashCRC(unsigned long ulBytes)
    {
        static unsigned short pusCrc3[4] = {0, 0, 0, 0};
        static unsigned long ulAddress = 0;
        unsigned long ulLoop, ulTemp;
        unsigned short *pusImageCRC;
    
        // Word-align the number of bytes, and calculate the ending
        // address for this transaction.
        ulBytes = ulBytes & ~3;
    
        // Check to see if we need to reset the CRC values.
        if(ulAddress == 0)
        {
            pusCrc3[0] = pusCrc3[1] = pusCrc3[2] = pusCrc3[3] = 0;
        }
    
        // Calculate CRC up to the CRC Table.
        for(ulLoop = 0; (ulLoop < (ulBytes/4)); ulLoop++)
        {
            // Check to see if we are inside the CRC Table.
            if((ulAddress >= CRC_TABLE_START) && (ulAddress < CRC_TABLE_END))
            {
                ulAddress += 4;
                continue;
            }
    
            // Check to see if we are past the end of FLASH.
            if(ulAddress >= SysCtlFlashSizeGet())
            {
                break;
            }
    
            // Preserve the current word in flash locally.
            ulTemp = *(unsigned long *)ulAddress;
    
            // Calculate the "full" CRC
            CRC_ITER(pusCrc3[0], ulTemp);
            CRC_ITER(pusCrc3[0], ulTemp>>8);
            CRC_ITER(pusCrc3[0], ulTemp>>16);
            CRC_ITER(pusCrc3[0], ulTemp>>24);
    
            // Calculate the "even" CRC
            CRC_ITER(pusCrc3[1], ulTemp);
            CRC_ITER(pusCrc3[1], ulTemp>>16);
    
            // Calculate the "odd" CRC
            CRC_ITER(pusCrc3[2], ulTemp>>8);
            CRC_ITER(pusCrc3[2], ulTemp>>24);
    
            ulAddress = ulAddress+4; //
        }
    
        // Check to see if we need to do a CRC comparison.
        if(ulAddress >= SysCtlFlashSizeGet())
        {
            // Reset the Address pointer for next time around.
            ulAddress = 0;
    
            // Setup the Image CRC pointer.
            pusImageCRC = (void *)&g_ulImageCRC[0];
     
            // Check the "full" CRC.
            if(pusCrc3[0] != pusImageCRC[0])
            {
                return(false);
            }
            
            // Check the "even" CRC.
            if(pusCrc3[1] != pusImageCRC[1])
            {
                return(false);
            }
    
            // Check the "odd" CRC.
             if(pusCrc3[2] != pusImageCRC[2])
            {
                return(false);
            }
            //Check signature
            if(CRC_SIGNATURE != pusImageCRC[3])
            {
               return(false);
            }
        }
         // CRC has passed if we get here, or we are still in the middle of a calculation.
         return(true);
    }
    
    //*****************************************************************************
    //
    //! Initialize FLASH CRC region table.
    //!
    //! This function will initialize the FLASH CRC data (if not already
    //! initialized) so that subsequent calls to CheckFlashCRC() will work
    //! properly.
    //!
    //! \note  In general, it would be preferable for a post-processing utility
    //! to fill in this information in the binary image.  This function is
    //! provided as an example of how to fill in this information.
    //
    //! \return None.
    //
    //*****************************************************************************
    void
    InitFlashCRC(void)
    {
        unsigned long ulAddress;
        unsigned long ulTemp;
        unsigned short usCrc3[4];
    
        // Check if we have a checksum, if not found create a new one
        if((g_ulImageCRC[0] != 0xffffffff) || (g_ulImageCRC[1] != 0xffffffff))
        {
            // Assume non-ff value(s) mean CRC has been programmed.
            return;
        }
    
        // Initialize the CRC array to 0 for the initial calculation.
        usCrc3[0] = usCrc3[1] = usCrc3[2] = usCrc3[3] = 0;
    
        // Calculate CRC up to the CRC Table.
        for(ulAddress = 0; ulAddress < SysCtlFlashSizeGet(); ulAddress += 4)
        {
            // Check to see if we are inside the CRC Table.
            if((ulAddress >= CRC_TABLE_START) && (ulAddress < CRC_TABLE_END))
            {
                ulAddress += 4;
                continue;
            }
            // Preserve the current word in flash locally.
            ulTemp = *(unsigned long *)ulAddress;
    
            // Calculate the "full" CRC
            CRC_ITER(usCrc3[0], ulTemp);
            CRC_ITER(usCrc3[0], ulTemp>>8);
            CRC_ITER(usCrc3[0], ulTemp>>16);
            CRC_ITER(usCrc3[0], ulTemp>>24);
    
            // Calculate the "even" CRC
            CRC_ITER(usCrc3[1], ulTemp);
            CRC_ITER(usCrc3[1], ulTemp>>16);
    
            // Calculate the "odd" CRC
            CRC_ITER(usCrc3[2], ulTemp>>8);
            CRC_ITER(usCrc3[2], ulTemp>>24);
        }
    
        // Write the calculated CRC values to FLASH memory, with a "magic"
        // number in the unused 16 bits.
        usCrc3[3] = CRC_SIGNATURE;
        FlashErase(CRC_TABLE_START);
        FlashProgram((uint32_t *)(&usCrc3[0]), CRC_TABLE_START, CRC_TABLE_SIZE);
    }

    THE END

  • Hi,

    If this work for you then OK. The posted code was here : http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/t/372271.aspx

    look at it, just for the info.

    Petrei