2

I am working with the stm32f4 Discovery board and I am trying to jump to a section of flash where I will begin executing another program there.The variable ApplicationAddress is 0x08008000. When my code hits this section, the PC goes to 0x0000000 and the system freezes. I am not sure exactly what is going on. Thank you for your time. My code to jump is shown below.

    NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8000);  
    JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
    Jump_To_Application = (pFunction) JumpAddress;
    /* Initialize user application's Stack Pointer */
    __set_MSP(*(__IO uint32_t*) ApplicationAddress);
    Jump_To_Application();
Owl_Prophet
  • 362
  • 5
  • 15
  • A bunch of questions: What is the contents of the two words at 0x08008000? And are you saying that as soon as `Jump_To_Application()` is executed the PC ends up at 0? Do you have a debugger setup that can single step at the assembly level? Do you have a serial port that you can dump text to for debug writes? – Michael Burr May 10 '13 at 22:30
  • 1
    There is a solution common to any ARM Cortex-M device, detailed here: http://stackoverflow.com/questions/14393715/how-to-jump-between-programs-in-stellaris/14406706#14406706. This is therefore a duplicate. – Clifford May 11 '13 at 19:52
  • I apologize, Clifford, I searched for a similar post, but I did not see this one. – Owl_Prophet May 13 '13 at 15:05
  • So the assembly method works for returning back to the main program start address @ 0x08000000, but not another program's address @ 0x08008000. Do you know why this could be? – Owl_Prophet May 13 '13 at 16:16
  • Another thing guys, that I ran into; When you compile the program that you are going to jump to, make sure that you change the settings of that project to start at address 0x you are jumping to. – Owl_Prophet Jul 19 '13 at 20:57

2 Answers2

4

Presumably the bit of code that you posted int he question is actually using the MSP stack, so when you execute:

__set_MSP(*(__IO uint32_t*) ApplicationAddress);

that stack gets thrown away and if the Jump_To_Application variable is a local variable (which might have been on the stack if it's a local variable - especially if you're running a non-optimized/debug build) might suddenly be garbage.

to solve this problem, I've used:

void LoadStackAndGo( void* sp, void* entry)
{
    __asm (
        "mov sp, r0 \n"
        "mov pc, r1 \n"
    );
}

which should be easily adaptable to whatever toolchain you're using.

Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • A Cortex-M executable normally has the vector table at the start address, and the table contains an initial stack pointer and PC. It is therefore only necessary to pass the address of the vector table, and to load SP and PC from the first two 32-bit words. Before doing that it is also necessary to reset the SCB:VTOR register to point to the start address, and before even that to disable interrupts. – Clifford May 11 '13 at 20:01
1

I had the exact same problem, however my solution:

__set_MSP (*(__IO uint32_t*)ApplicationAddress);

__set_PSP (*(__IO uint32_t*)ApplicationAddress);

and declare the function pointer as static...

static Function jumpToApplication = (Function) * (__IO uint32_t*)(ApplicationAddress + 4);
DanUK86
  • 33
  • 6