EmbeddedRelated.com
Forums
Memfault Beyond the Launch

Program Code Checksum

Started by dehkordi2 August 23, 2011
I am trying to calculate the checksum of my program code. The routine that is doing the job:

//=============================#define CHECKSUM_BLOCK_SIZE 2048U

void CalcChecksum(){
// Update a global DWORD (unsigned long) dwChecksum

DWORD dwCheckAddr, dwBytesToGo; // (unsigned long variables)
WORD wCheckLen, wChecksumTemp; // (unsigned int variables)

// Init checksum
dwChecksum = 0L;

// The code bytes are divided between a root memory and xmem.
// Must calc the checksum in two chunks.
// ********** First the root memory part ************
// Set dwCheckAddr to the starting linear addr of the root memory

dwCheckAddr = (unsigned long) (0x000FFFFFL &
(((long) prog_param.RCB.aaa.a.base) << 12ul) +
(long) prog_param.RCB.aaa.a.addr);
// Set dwBytesToGo to the end of the code in root memory
dwBytesToGo = (unsigned long) (0x000FFFFFL &
(((long) prog_param.RCE.aaa.a.base) << 12ul) +
(long) prog_param.RCE.aaa.a.addr);
dwBytesToGo -= dwCheckAddr; // # of code bytes in root memory
// Calc the checksum for the code in root memory
while(dwBytesToGo){
wCheckLen = (dwBytesToGo > CHECKSUM_BLOCK_SIZE) ?
CHECKSUM_BLOCK_SIZE : (WORD)dwBytesToGo;
fs_checksum_x(&wChecksumTemp, dwCheckAddr, wCheckLen);

dwCheckAddr += (DWORD)wCheckLen; // Update addr of next chunk
dwBytesToGo -= (DWORD)wCheckLen; // Update remaining bytes
dwChecksum += (DWORD)wChecksumTemp; // Update the checksum
};

// ************* Incorporate the code bytes in xmem *****
dwCheckAddr = (unsigned long) (0x000FFFFFL &
(((long) prog_param.XCB.aaa.a.base) << 12ul) +
(long) prog_param.XCB.aaa.a.addr);
// Set dwBytesToGo to the end of the code in xmem
dwBytesToGo = (unsigned long) (0x000FFFFFL &
(((long) prog_param.XCE.aaa.a.base) << 12ul) +
(long) prog_param.XCE.aaa.a.addr);
dwBytesToGo -= dwCheckAddr; // # of code bytes in xmem
// Calc the checksum for the code in xmem
while(dwBytesToGo){
wCheckLen = (dwBytesToGo > CHECKSUM_BLOCK_SIZE) ?
CHECKSUM_BLOCK_SIZE : (WORD)dwBytesToGo;
fs_checksum_x(&wChecksumTemp, dwCheckAddr, wCheckLen);

dwCheckAddr += (DWORD)wCheckLen; // Update addr of the next chunk
dwBytesToGo -= (DWORD)wCheckLen; // Update remaining bytes
dwChecksum += (DWORD)wChecksumTemp; // Update the checksum
};
}

//=============================
The program to test this, saves the calculated checksum in an array in the battery-backed RAM. After programming the code once, the power to the board was turned on and off several times to compare the calculated checksums. When this array is examined, it is found while most of the values are the same, there are occasions when the calculated checksum is different than the rest.

Is the assumption that the code is divided between the root memory and xmem memory correct?

Is my method of calculating the starting address and size of each part of the code memory correct?

Is my method of calculating the checksum correct?

Thanks for helping.

If you're on a board that loads the image from flash and "runs in RAM", then this technique won't work. You end up checksumming some of the data ORGs which may change after boot.

If you're using DC 10.54 and later, I think there's an "fiVerify()" function in firmware_info.lib that will do what you're looking for.

In older versions of Dynamic C. you'll have to walk the org table to ensure that you're only checksumming ORGs with code and constants.

-Tom
On Aug 23, 2011, at 12:51 PM, dehkordi2 wrote:

> I am trying to calculate the checksum of my program code. The routine that is doing the job:
>
> //=============================> #define CHECKSUM_BLOCK_SIZE 2048U
>
> void CalcChecksum(){
> // Update a global DWORD (unsigned long) dwChecksum
>
> DWORD dwCheckAddr, dwBytesToGo; // (unsigned long variables)
> WORD wCheckLen, wChecksumTemp; // (unsigned int variables)
>
> // Init checksum
> dwChecksum = 0L;
>
> // The code bytes are divided between a root memory and xmem.
> // Must calc the checksum in two chunks.
> // ********** First the root memory part ************
> // Set dwCheckAddr to the starting linear addr of the root memory
>
> dwCheckAddr = (unsigned long) (0x000FFFFFL &
> (((long) prog_param.RCB.aaa.a.base) << 12ul) +
> (long) prog_param.RCB.aaa.a.addr);
> // Set dwBytesToGo to the end of the code in root memory
> dwBytesToGo = (unsigned long) (0x000FFFFFL &
> (((long) prog_param.RCE.aaa.a.base) << 12ul) +
> (long) prog_param.RCE.aaa.a.addr);
> dwBytesToGo -= dwCheckAddr; // # of code bytes in root memory
> // Calc the checksum for the code in root memory
> while(dwBytesToGo){
> wCheckLen = (dwBytesToGo > CHECKSUM_BLOCK_SIZE) ?
> CHECKSUM_BLOCK_SIZE : (WORD)dwBytesToGo;
> fs_checksum_x(&wChecksumTemp, dwCheckAddr, wCheckLen);
>
> dwCheckAddr += (DWORD)wCheckLen; // Update addr of next chunk
> dwBytesToGo -= (DWORD)wCheckLen; // Update remaining bytes
> dwChecksum += (DWORD)wChecksumTemp; // Update the checksum
> };
>
> // ************* Incorporate the code bytes in xmem *****
> dwCheckAddr = (unsigned long) (0x000FFFFFL &
> (((long) prog_param.XCB.aaa.a.base) << 12ul) +
> (long) prog_param.XCB.aaa.a.addr);
> // Set dwBytesToGo to the end of the code in xmem
> dwBytesToGo = (unsigned long) (0x000FFFFFL &
> (((long) prog_param.XCE.aaa.a.base) << 12ul) +
> (long) prog_param.XCE.aaa.a.addr);
> dwBytesToGo -= dwCheckAddr; // # of code bytes in xmem
> // Calc the checksum for the code in xmem
> while(dwBytesToGo){
> wCheckLen = (dwBytesToGo > CHECKSUM_BLOCK_SIZE) ?
> CHECKSUM_BLOCK_SIZE : (WORD)dwBytesToGo;
> fs_checksum_x(&wChecksumTemp, dwCheckAddr, wCheckLen);
>
> dwCheckAddr += (DWORD)wCheckLen; // Update addr of the next chunk
> dwBytesToGo -= (DWORD)wCheckLen; // Update remaining bytes
> dwChecksum += (DWORD)wChecksumTemp; // Update the checksum
> };
> }
>
> //=============================>
> The program to test this, saves the calculated checksum in an array in the battery-backed RAM. After programming the code once, the power to the board was turned on and off several times to compare the calculated checksums. When this array is examined, it is found while most of the values are the same, there are occasions when the calculated checksum is different than the rest.
>
> Is the assumption that the code is divided between the root memory and xmem memory correct?
>
> Is my method of calculating the starting address and size of each part of the code memory correct?
>
> Is my method of calculating the checksum correct?
>
> Thanks for helping.

Memfault Beyond the Launch