Monday, October 24, 2011

Cortex-M3 Exception Vector Checksum

The 7th entry of the Cortex-M3 exception vector is reserved for the 2's complement of the checksum of the exception vector. At run time the bootloader computes the checksum again and adds it to the one stored in the exception vector, if the result equals zero it starts executing the user code.

The checksum is usually computed by the software that flashes the binary like FashMagic or openocd, if you're using openocd like me, you may see this message every time you flash a binary:
Warn : Verification will fail since checksum in image (0x00000000) to be 
written to flash is different from calculated vector checksum (0xeffc59e6).
Warn : To remove this warning modify build tools on developer PC to inject 
correct LPC vector checksum.
The code will run normally, because openocd computes the checksum for you, but it's just too annoying, so I wrote the following small utility to compute the checksum and inject it into the binary, it's called from the Makefile before running openocd to flash the binary:
#include <stdio.h>
int main(int argc, char **argv)
{
    if (argc == 1) {
        printf("usage: cm3_checksum <bin>\n");
        return 1;
    }

    FILE *file;
    if ((file = fopen(argv[1], "r+")) == NULL) {    
        return 1;
    }

    /* The checksum of the exception vector */
    unsigned int i, n, checksum=0;
    for (i=0; i<7; i++) {
        fread(&n, 4, 1, file);
        checksum += n;
    }

    /* The 2's complement of the checksum */
    checksum = -checksum;
    printf("checksum: 0x%X\n", checksum);
    
    /* write back the checksum to location 7 */
    fseek(file, 0x1c, SEEK_SET);
    fwrite(&checksum, 4, 1, file);

    fclose(file);
    return 0;
}
Read more ...