11
votes

I am using a LPC 1768 board from mbed, (with cortex M3 cpu) and I am trying to achieve something here, mainly upgrade the user application from the SD Card, I am writing two programs, first a bootloader/nano-kernel, and a user-app (helloworld will do for a start):

  • Bootloader/nano-kernel at 0x00 address runs, it will do some checks and eventually grab the binary file on the SD card
  • Bootloader/nano-kernel will copy this binary at address 0x9000 (that might have to change later on, but this space is not used by bootloader/nano-kernel so should be ok)
  • Bootloader jumps to user application at 0x9000 + 4

The Sd card is quite easy to work-out, I am having issues with the jumping part. Here is the code of the jumping function.

void run(void) {

  void (*user_code_entry)(void);

  unsigned *p;   
  SCB->VTOR = (USER_FLASH_START & 0x1FFFFF80);

  // Load contents of second word of user flash - the reset handler address
  // in the applications vector table
  p = (unsigned *)(USER_FLASH_START +4); // USER_FLASH_START is 0x9000

  user_code_entry = (void (*)(void))p;

  // Jump to user application
  user_code_entry();

}

So I have compiled (I am using Keil uvision4) the user application changing the start address to 0x9000. If I program my board (using flashmagictool), and then manually jump (still using flashmagictool) to 0x9004 (0x9000 + 4), the user application will run so I believe the compilation has worked ok so user-app can run at 0x9000.

But If I run the bootloader/nano-kernel, this one does not jump to the user-application and unfortunately as I cannot debug, I am not sure of what is going on... I also have tried not to use the SD copy part, so I program the bootloader first with basically just the jump to 0x9004. I then program the user application that will sit at 0x9000. If I reboot the board, bootloader runs but does not jump to user-app. I have checked memory, and it seems that both programs (bootloader + user-app) are correct and at the right place.

I am sure I am missing something here, is there any low-level code I should be looking at ? I have read tones of docs online, and from the examples I have found, they are jumping to user code the same way as I do... Thanks a lot for any help.

2
this should work fairly similar on your PC too, but with virtual addresses, instead of physical - try it and see if it works, then move the code to KeilUlterior
Cortex M3 has no MMU, so there are no virtual addresses.Turbo J

2 Answers

8
votes

Cortex M3 can only run in Thumb mode. Thus you always have to jump to address +1, otherwise it will generate a fault.

Just try:

user_code_entry = (void (*)(void))(USER_FLASH_START +4 +1);

4
votes

Just read the AN10866 document on NXP Site. You have load the PC and Stack pointer and then jump to the reset interrupt:

__asm void boot_jump( uint32_t address ){
   LDR SP, [R0]     ;Load new stack pointer address
   LDR PC, [R0, #4] ;Load new program counter address
}

void execute_user_code(void)
{
    /* Change the Vector Table to the USER_FLASH_START 
    in case the user application uses interrupts */
    SCB->VTOR = USER_FLASH_START & 0x1FFFFF80;

    boot_jump(USER_FLASH_START);
}