11

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.

tniles
  • 329
  • 1
  • 11
batmat
  • 225
  • 1
  • 5
  • 17
  • 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 Keil – Ulterior Oct 03 '12 at 20:15
  • 1
    Cortex M3 has no MMU, so there are no virtual addresses. – Turbo J Oct 03 '12 at 23:34

2 Answers2

8

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);

Turbo J
  • 7,563
  • 1
  • 23
  • 43
  • Can't believe that was it ! Thank you very much Turbo J :) – batmat Oct 04 '12 at 16:50
  • 3
    I realize that this probably worked but it doesn't make sense. The compiler should be generating Thumb instructions for you. I do the exact same thing as you did there (no +1) and it seems to work for me. Do you have the `thumb` flag set for the `arm-none-eabi-gcc` compiler? – nonsensickle Sep 05 '13 at 23:53
  • Thanks! This also worked for me on a M4. Everything compiled fine, the debugger ran through all the code just fine, with the one exception of this IAR debugger warning which would occur upon jump while stepping through the code: “T-bit of XPSR is 0 but should be 1. Changed to 1.” – tniles Mar 14 '16 at 15:25
4

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);
}
  • I would also like to add that http://infocenter.arm.com/help/topic/com.arm.doc.dui0056d/DUI0056.pdf on page 4-6 and 4-7 under the "Differences Between Inline Assembler and armasm" it states that you cannot store values to the PC. It also states that the `bx` instruction is not supported but I have code that is currently using it in inline asm that works (though I'm checking it again). – nonsensickle Jul 01 '13 at 04:39
  • My previous comment refers to inline assembly like the one @John Sinclair used. These are safe to use in a separate assembly code file however, I had a version doing the same in inline assembly and it also worked fine so I'm not sure what to make of ARM's recommendations. – nonsensickle Jul 01 '13 at 21:11