cancel
Showing results for 
Search instead for 
Did you mean: 

Bootloader and jumping to flash location

jdcowpland
Associate II
Posted on March 13, 2014 at 16:18

Hi guys,

I've been working on a bootloader program which is loosely based around the FW_Upgrade demo for the STM32F4 discovery board. My Bootloader so far correctly finds a file on a USB stick and downloads it to flash in the right location(0x0800C000), but I'm having issues jumping to that location to run my downloaded program once I'm done putting it in flash. The demo from ST has the MCU reset after it has downloaded to flash and then jumps to the program. Is the reset necessary or can I just jump straight to the location in flash? Also, how do I actually do the jump. I'm using the code from st which looks like this, but it doesn't seem to work:

/* Check Vector Table: Test if user code is programmed starting from address
''APPLICATION_ADDRESS'' */
if (((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000 ) == 0x20000000)
{
/* Jump to user application */
JumpAddress = (APPLICATION_ADDRESS + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
Jump_To_Application();
}

25 REPLIES 25
Posted on March 13, 2014 at 16:36

You should be able to jump to ANY code you want, remember that the Thumb code will be an ODD address.

The example you refer too expects a Vector Table, where the first entry is the new Stack Pointer, and the second points to the ResetHandler. If you are jumping to arbitrary code without the vector table, you can do that too, loading the code at X, and jumping to X+1
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jdcowpland
Associate II
Posted on March 13, 2014 at 17:05

Thanks for the help Clive. Can't quite get my head around what I need to do though. Let's say I get rid of that code from the example that uses the vector table,and as you say, just jump to an arbitrary bit of code in flash, what would the code look like for doing that?

Posted on March 13, 2014 at 17:25

typedef int (*pFunction)(void);
void RamCode(void)
{
  static const uint16_t Code[] = { 0xF04F, 0x007B, 0x4770 }; // payload
  uint8_t Buffer[16]; // as big as required
  pFunction RunCode;
  memcpy(Buffer, Code, sizeof(Code)); // Copy code
  RunCode = (pFunction)&Buffer[1]; // +1 for Thumb code
  printf("%d\n",RunCode());
}

  MOV R0, #123
  BX LR

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
chen
Associate II
Posted on March 13, 2014 at 18:45

Hi

(I do not want to contradict clive1, since he has successfully helped so many.) '' My Bootloader so far correctly finds a file on a USB stick and downloads it to flash in the right location(0x0800C000)'' Is the vector table at 0x800c00? If so then the code snipet from ST should work, change the ''

APPLICATION_ADDRESS

'' to 0x800c00 Get rid of the 'if' statement (which is checking for the code being in RAM) and it should work. DO NOT ATTEMPT to just jump to 0x800c00 if the vector table resides at this address. Something else to check : Have you checked if 0x800c00 is on a valid boundary for the vector table? ''The demo from ST has the MCU reset after it'' Do not reset the processor - it will go back to your boot code. Your bootcode should start the application code. (I have managed to successfully do this in my own bootcode and it does pretty much what the ST code does)
Posted on March 13, 2014 at 19:01

Well you're likely to have to bring your own beer here, I'm trying to infer general methods which can be modified to suit.

typedef int (*pFunction)(void);
uint8_t *Buffer = (uint8_t *)0x0800C000;
RunCode = (pFunction)&Buffer[1]; // +1 for Thumb code
RunCode();

Now while you can jump to subroutines, application code might well have other run-time dependencies that the compile expects to get called first to initialize statics, copy/zero. So you'll have to consider the requirements and mechanics of what you want to achieve and what that will take.

startup.s (Keil, adjust syntax to taste)

..
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
..

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jdcowpland
Associate II
Posted on March 14, 2014 at 11:30

I'm not all that comfortable with assembler, so think I'm going to follow the vector table route you suggested Sung. So basically, you're saying I need to make sure my vector table is at location 0x0800C000. How do I do that? Is it a case of calling this?

NVIC_SetVectorTable(NVIC_VectTab_FLASH,0xC000);

Or does it need to be defined in the code I'm downloading? Location 0x0800C000 is the base address of Flash Sector 3 so I'm guessing that isn't going to be a problem.

chen
Associate II
Posted on March 14, 2014 at 12:02

Hi

''I'm not all that comfortable with assembler''

It has nothing to do with assembler.

''So basically, you're saying I need to make sure my vector table is at location 0x0800C000. How do I do that?''

Look at the map file that is (or can be) ouput during the build process.

In my project it is called ''.isr_vector''.

It is defined in the 'startup'.s file in my project. That is a good starting place to look for it.

''Or does it need to be defined in the code I'm downloading?''

Should already be done - or no interrupts will work!

''Location 0x0800C000 is the base address of Flash Sector 3 so I'm guessing that isn't going to be a problem.''

Sound OK but worth checking in the reference manual.

Posted on March 14, 2014 at 12:06

Suggest you also review the USART IAP app note and code.

The vector table is normally reconfigured in SystemInit() within system_stm32f4xx.c, the code and the project need to define the base address the App code is going to reside at. The base address typically comes from the target configuration or scatter/linker script. The App is basically built as a stand-alone image, with it's own vector/interrupt table, and the Boot Loader transfers control via a mechanism like that shown in the first port.

The vector table is stored in SCB->VTOR, you can check that, it should be the base 0x0800C000 when it leaves SystemInit()
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
jdcowpland
Associate II
Posted on March 14, 2014 at 14:56

clive, are you saying that I need to into my app code and define the IROM1 start address as 0x0800C000 instead of 0x08000000?