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.

BOOT ROM checksum code

Other Parts Discussed in Thread: TMS320F28335

We need to be able to calculate the BOOT ROM checksum for a TMS320F28335.

A previous post http://e2e.ti.com/support/microcontrollers/c2000/f/171/t/185956.aspx provides the code, which I have downloaded.

Is the checksum calculating function in the BOOT ROM iteself?  The post implies it is not.  However, if it is, it should be easier to call that, if it somehow returns the value.

Regards.

  • Giles,

    nope, the checksum calculation function is not ROM'd on this device, however the final checksum result is ROM'd. The same algorithm attached in this thread is used to calculate the checksum on this device - http://e2e.ti.com/support/microcontrollers/c2000/f/171/t/185956.aspx.

    you will have to implement the function (including data structures) as they are shown in the attachment in above thread as it is in your application and at the end the function it does a comparison of calculated checksum with the ROM'd checksum result.

    Users are free to come up with their own checksum algorithms to verify ROM, in such a case the checksum verification would be done comparing the calculated value with a built in golden result, all with in the application.

     

    hope it helps.

     

    Best Regards

    Santosh

     

  •  Using a TMS320F28335 I have built, loaded & run 7585.checksum.c.

    Breaking after setting currentVal in the code (i.e. at the first "if"):
       currentVal = (ui16 *)CHECKSUM_ADDR;
       if(*currentVal++ != (ui16)checksum.lowHalfLSW)  error(1);
       if(*currentVal++ != (ui16)checksum.lowHalfMSW)  error(2);
       if(*currentVal++ != (ui16)checksum.highHalfLSW) error(3);
       if(*currentVal   != (ui16)checksum.highHalfMSW) error(4);

    I get these values:
       checksum        struct ui64     {...} (Hex)
            highHalfMSW     unsigned long   0x00000000 (Hex) 
            highHalfLSW     unsigned long   0x00000752 (Hex) 
            lowHalfMSW      unsigned long   0x000040E5 (Hex) 
            lowHalfLSW      unsigned long   0x000089F3 (Hex) 

       currentVal[0]   unsigned int    0x557D (Hex)  
       currentVal[1]   unsigned int    0xAA58 (Hex)  
       currentVal[2]   unsigned int    0x08D9 (Hex)  
       currentVal[3]   unsigned int    0x0000 (Hex)  

    Clearly the result of the calculation is that the checksum test fails.

    Any idea what’s going on?

    Regrards.

     

  • could you cross check if you have defined the blocks as below?

     

    #define NUMBLOCKS 2

    MEMORY_BLOCK memblock[NUMBLOCKS] = {        (ui16 *)0x003FE000, (ui16 *)0x003FFFBB,        (ui16 *)0x003FFFC0, (ui16 *)0x003FFFFF };

     

    Best Regards

    santosh

     

  • I can validate on behalf of Giles (I am on the same team) that we have those memory locations. Below is the code I am using

    #include "TIBootChecksum.h"
    
    
    // Tell the routine where the checksum is stored such that it can be
    // compared with the calculated value.
    
    
    
    typedef struct {
           UINT16 *firstAddr;
           UINT16 *lastAddr;
    } MEMORY_BLOCK;
    
    
    // The memory blocks to include in the checksum must
    // be identified here.
    //
    // In the case of the F2810/12 boot ROM, the checksum
    // skips over the blocks reserved to store the checksum
    // itself.  Note that the pointers are to 16-bit values.
    // This is because the routine itself will take care of
    // the 32-bit addition using two 16-bit values.
    
    #define NUMBLOCKS 2
    
    MEMORY_BLOCK memblock[NUMBLOCKS] = {
           (UINT16 *)0x003FE000, (UINT16 *)0x003FFFBB,
           (UINT16 *)0x003FFFC0, (UINT16 *)0x003FFFFF
    };
    
    
    
    // This main function performs a very simple 64 bit checksum routine.
    // 4 32-bit values are used to calculate the checksum.  This is done so that
    // no overflow is lost.  After each addition, the value is checked to see if
    // it has overflowed the lower 16-bits.  If it has, then the overflow portion
    // in the upper 16-bits is added to the next most significant portion of the
    // checksum.
    //
    // When the routine completes, the upper 16-bits of each portion of the checksum
    // will be 0x000 - this portion should be discarded as it was only used to check
    // for overflow and the checksum is then formed from the lower 16-bits.
    //
    // For example:
    //     lowHalfLSW  = 0x00001111
    //     lowHalfMSW  = 0x00002222
    //     highHalfLSW = 0x00003333
    //     highHalfMSW = 0x00004444
    //
    //     would result in a 64-bit checksum of 0x44443333 22221111
    
    #define WDCR 0x7029
    
    BOOLEAN Checksum(UINT64 * checksum)
    {
          BOOLEAN result = FALSE;
          UINT16 errorCount = 0;
          UINT16 *currentVal;
          UINT16 *lastVal;
          UINT16 i;
          UINT16 count;
    
          count = 0;
    
          checksum->highHalfMSW = 0;
          checksum->highHalfLSW = 0;
          checksum->lowHalfLSW = 0;
          checksum->lowHalfMSW = 0;
    
        EALLOW;
        *(UINT16 *)WDCR = 0x68;
        EDIS;
    
        for(i = 0; i < NUMBLOCKS; i++) {
    
          currentVal = memblock[i].firstAddr;
          lastVal = memblock[i].lastAddr;
    
    
          // For each value in the block perform 32-bit addition.
          while(currentVal <= lastVal) {
    
              count++;
    
              // On C28x, the LSW of a 32-bit value is stored
              // in the lower memory address.  This portion of the
              // routine will add the LSW of the 32-bit value to
              // the checksum.  After the addition, each portion
              // is checked for overflow.  If overflow has occurred
              // then the overflow is added to the next most significant
              // word in the checksum.
    
              checksum->lowHalfLSW += *currentVal ^ ((unsigned long)currentVal & 0x0000FFFF);
              currentVal++;
    
              if(checksum->lowHalfLSW > 0xFFFF) {
    
                  checksum->lowHalfMSW += checksum->lowHalfLSW >> 16;
                  checksum->lowHalfLSW &= 0xFFFF;
              }
    
              if(checksum->lowHalfMSW > 0xFFFF) {
    
                  checksum->highHalfLSW += checksum->lowHalfMSW >> 16;
                  checksum->lowHalfMSW &= 0xFFFF;
              }
    
              if(checksum->highHalfLSW > 0xFFFF) {
    
                  checksum->highHalfMSW += checksum->highHalfLSW >> 16;
                  checksum->highHalfLSW &= 0xFFFF;
              }
    
    
              // On C28x, the MSW of a 32-bit value is stored
              // in the upper memory address.  This portion of the
              // routine will add the MSW of the 32-bit value to
              // the checksum.  Because it is the MSW it is added
              // to the lowerHalfMSW of the checksum. After
              // the addition, each portion is again checked for
              // overflow.  If overflow has occurred then
              // the overflow is added to the next most significant
              // word in the checksum.
    
    
              checksum->lowHalfMSW += *currentVal ^ ((unsigned long)currentVal & 0x0000FFFF);
              currentVal++;
    
    //        checksum.lowHalfMSW += *currentVal++;
    
              if(checksum->lowHalfMSW > 0xFFFF) {
    
                  checksum->highHalfLSW += checksum->lowHalfMSW >> 16;
                  checksum->lowHalfMSW &= 0xFFFF;
              }
    
              if(checksum->highHalfLSW > 0xFFFF) {
    
                  checksum->highHalfMSW += checksum->highHalfLSW >> 16;
                  checksum->highHalfLSW &= 0xFFFF;
              }
    
           }
       }
    
       // Check that the calculated checksum is stored in memory
       // where it should be.   The checksum is stored in memory
       // in the following order
       //
       // low address:   lowHalfLSW
       //                lowHalfMSW
       //                highHalfLSW
       // high address:  highHalfMSW
       //
    
       currentVal = (UINT16 *)CHECKSUM_ADDR;
        if (*currentVal++ != (UINT16) checksum->lowHalfLSW)
        {
            errorCount++;
        }
    
        if (*currentVal++ != (UINT16) checksum->lowHalfMSW)
        {
            errorCount++;
        }
        if (*currentVal++ != (UINT16) checksum->highHalfLSW)
        {
            errorCount++;
        }
        if (*currentVal != (UINT16) checksum->highHalfMSW)
        {
            errorCount++;
        }
    
    
        if (errorCount == 0)
        {
            result = TRUE;
        }
        else
        {
            result = FALSE;
        }
    
       return result;
    
    }
    
    
    
    

    4477.TIBootChecksum.h

    I have changed the UNIT64  struct to a pointer in this code, but I have tried it by keeping as a struct and I still get the same results as Giles posted.

  • can you check if you are not having the same problem as the mentioned in this thread with initialization of the mem block structure?

     

    http://e2e.ti.com/support/microcontrollers/c2000/f/171/t/185956.aspx

     

    Best Regards

    Santosh

  • I have debugged the code via the JTAG emulator and it picks the correct memory addresses. I did try changing the structure to a const and other suggestions in the thread. From the values we are getting which are quite far off it seems as if the algorithm is diffferent for the TMS320F28335.

  • Here is a zip/archive of the project I am using to calculate the checksum (and getting the results shown in my post of 20 Aug).  0257.checksum.zip

    The .c file is as given in the post http://e2e.ti.com/support/microcontrollers/c2000/f/171/t/185956.aspx, except for adding some definitions that must have been in the .h.

    As Ali has stated, using debig all the pointers, etc. are pointing to the right memory locations.

    Is it absolutely certain that the TMS320F28335 is using this algorithm?

    Regards, Giles

  • Giles / Ali,

    F28335 checksum algorithm is slightly different from F28035 algorithm. That is the reason why you don't get the same checksum as the one in F28335 bootrom.

    Please find F28335 checksum attached.

    //###########################################################################
    //
    // FILE:    checksum.c    
    //
    // TITLE:   F2810/12 boot ROM checksum generator
    //
    // Functions:
    //
    //
    // Notes:
    //
    //###########################################################################
    //
    //  Ver | dd mmm yyyy |     Who      | Description of changes
    // =====|=============|==============|=======================================
    //  0.1 |             | LH           | Original Release.
    //      |             |              | 
    //###########################################################################
    #include "checksum.h"
    
    void error(ui16 errorFlag);
    
    // Tell the routine where the checkum is stored such that it can be
    // compared with the calculated value. 
    
    #define CHECKSUM_ADDR 0x003FFFBC
    
    typedef struct {
           ui16 *firstAddr;
           ui16 *lastAddr;
    } MEMORY_BLOCK;
    
    
    // The memory blocks to include in the checksum must
    // be identified here. 
    // 
    // In the case of the F2810/12 boot ROM, the checksum
    // skips over the blocks reserved to store the checksum
    // itself.  Note that the pointers are to 16-bit values. 
    // This is because the routine itself will take care of
    // the 32-bit addition using two 16-bit values.  
     
    #define NUMBLOCKS 2
    
    MEMORY_BLOCK memblock[NUMBLOCKS] = {
           (ui16 *)0x003FE000, (ui16 *)0x003FFFBB,
           (ui16 *)0x003FFFC0, (ui16 *)0x003FFFFF
    };
    
    // Use 4 32-bit values to represent the 64-bit checksum.
    // This is done such that overflow can be monitored at 
    // each step in the summation.   If overflow from the lower
    // 16-bits occurs, then the overflow is added to the next
    // significant word. 
    
    typedef struct {
           ui32 highHalfMSW;
           ui32 highHalfLSW;
           ui32 lowHalfMSW;
           ui32 lowHalfLSW;
    } ui64; 
    
    
    // This main function performs a very simple 64 bit checksum routine.
    // 4 32-bit values are used to calculate the checksum.  This is done so that
    // no overflow is lost.  After each addition, the value is checked to see if
    // it has overflowed the lower 16-bits.  If it has, then the overflow portion
    // in the upper 16-bits is added to the next most significant portion of the
    // checksum.  
    //
    // When the routine completes, the upper 16-bits of each portion of the checksum
    // will be 0x000 - this portion should be discarded as it was only used to check
    // for overflow and the checksum is then formed from the lower 16-bits. 
    //
    // For example:
    //     lowHalfLSW  = 0x00001111
    //     lowHalfMSW  = 0x00002222
    //     highHalfLSW = 0x00003333
    //     highHalfMSW = 0x00004444
    //
    //     would result in a 64-bit checksum of 0x44443333 22221111
    
    #define WDCR 0x7029
    
    main()
    {
          ui16 *currentVal;
          ui16 *lastVal;
          ui64 checksum;
          ui16 i;
          ui16 count;
          
          count = 0;
          
          checksum.highHalfMSW = 0;
          checksum.highHalfLSW = 0;
          checksum.lowHalfLSW = 0;
          checksum.lowHalfMSW = 0;
    
        EALLOW;
    	*(ui16 *)WDCR = 0x68;
    	EDIS
             
        for(i = 0; i < NUMBLOCKS; i++) {
                                                                  
          currentVal = memblock[i].firstAddr;
          lastVal = memblock[i].lastAddr;
          
          
          // For each value in the block perform 32-bit addition.
          while(currentVal <= lastVal) {
    
              count++;
              
              // On C28x, the LSW of a 32-bit value is stored
              // in the lower memory address.  This portion of the
              // routine will add the LSW of the 32-bit value to 
              // the checksum.  After the addition, each portion
              // is checked for overflow.  If overflow has occurred
              // then the overflow is added to the next most significant 
              // word in the checksum.  
              
              checksum.lowHalfLSW += *currentVal++;
          
              if(checksum.lowHalfLSW > 0xFFFF) {
          
                  checksum.lowHalfMSW += checksum.lowHalfLSW >> 16;
                  checksum.lowHalfLSW &= 0xFFFF;
              }
          
              if(checksum.lowHalfMSW > 0xFFFF) {
          
                  checksum.highHalfLSW += checksum.lowHalfMSW >> 16;
                  checksum.lowHalfMSW &= 0xFFFF;
              }
    
              if(checksum.highHalfLSW > 0xFFFF) {
          
                  checksum.highHalfMSW += checksum.highHalfLSW >> 16;
                  checksum.highHalfLSW &= 0xFFFF;
              }
          
    
              // On C28x, the MSW of a 32-bit value is stored
              // in the upper memory address.  This portion of the
              // routine will add the MSW of the 32-bit value to 
              // the checksum.  Because it is the MSW it is added
              // to the lowerHalfMSW of the checksum. After 
              // the addition, each portion is again checked for
              // overflow.  If overflow has occurred then 
              // the overflow is added to the next most significant 
              // word in the checksum.  
              
              checksum.lowHalfMSW += *currentVal++;
          
              if(checksum.lowHalfMSW > 0xFFFF) {
          
                  checksum.highHalfLSW += checksum.lowHalfMSW >> 16;
                  checksum.lowHalfMSW &= 0xFFFF;
              }
    
              if(checksum.highHalfLSW > 0xFFFF) {
          
                  checksum.highHalfMSW += checksum.highHalfLSW >> 16;
                  checksum.highHalfLSW &= 0xFFFF;
              }
          
           }
       }
       
       // Check that the calculated checksum is stored in memory
       // where it should be.   The checksum is stored in memory
       // in the following order
       //
       // low address:   lowHalfLSW
       //                lowHalfMSW
       //                highHalfLSW
       // high address:  highHalfMSW
       //
       
       currentVal = (ui16 *)CHECKSUM_ADDR;
       if(*currentVal++ != (ui16)checksum.lowHalfLSW)  error(1);
       if(*currentVal++ != (ui16)checksum.lowHalfMSW)  error(2);
       if(*currentVal++ != (ui16)checksum.highHalfLSW) error(3);
       if(*currentVal   != (ui16)checksum.highHalfMSW) error(4);     
    
       // check passed!   
       asm("    MOV AH,#0");
       asm("    MOV AL,#0xC001");   
       asm("    ESTOP0");   
    
    }
    
    
    void error(ui16 errorFlag) {
    
       // if an error happens check the
       // AL register for the errorFlag.
       
       asm("    MOV AH,#0");
       asm("    MOV AL,#0xBAAD");   
       asm("    ESTOP0");
    }
    // EOF --------
    

    If you compare this checksum algorithm with your checksum algorithm you should be able to clearly see the difference.

    Regards,

    Manoj

  • This one works.  Thanks.

    Looking at the new code and going back to spru963a (BOOT ROM REF) section 4.1 which says “Taking a 64-bit summation of all addresses within the ROM, except for the checksum locations, generates this checksum” I tried the following:
    • Treat the BOOT ROM as a sequence of unsigned, 32-bit integers
    • Sum all these integers, except those at the checksum addresses, into a unsigned 64-bit integer
     This gives the checksum.

    I think this is what F28335_checksum.c is doing, i.e.
     checksum.lowHalfLSW += *currentVal++;
     :
     checksum.lowHalfMSW += *currentVal++;
    is effectively doing a 32-bit addition.

    Thus my simpler code below correctly re-calculates the checksum.  Is there any reason not to use it?

    Regards, Giles

    typedef unsigned long       UINT32;
    typedef unsigned long long  UINT64;
    typedef struct {
        UINT32 *firstAddr;
        UINT32 *lastAddr;
    } MEMORY_BLOCK;
    #define NUMBLOCKS 2
    const MEMORY_BLOCK memblock[NUMBLOCKS] = {
           (UINT32*)0x003FE000, (UINT32*)0x003FFFBB,
           (UINT32*)0x003FFFC0, (UINT32*)0x003FFFFF
    };
    int main(void)
    {
        UINT64 CHECKSUM = *(UINT64*)0x003FFFBC;
        UINT32 block;
        UINT64 SUMMATION = 0ULL;
        UINT32 *addr;
        for (block=0;block<2;block++)
        {
            for (addr = memblock[block].firstAddr; addr < memblock[block].lastAddr; addr++)
            {
                SUMMATION += (*addr);
            }
        }
        if ( SUMMATION == CHECKSUM )
            return +1;
        else
            return -1;
    }
  • I'm glad to note that you were able to verify the checksum. The algorithm I sent to you in my previous message is the authentic algorithm used by us to calculate the checksum. The algorithm sent is just an example checksum algorithm. Ofcourse, you are free to comeup with your own version of checksum algorithm.

    Regards,

    Manoj