Skip to main content
Gordon Madden
Associate III
June 23, 2017
Solved

How do execute a program from a location other than the beginning of flash memory?

  • June 23, 2017
  • 15 replies
  • 5804 views
Posted on June 24, 2017 at 00:04

Using STM32F417, programs uploaded to internal flash start executing at address 0x0800_0000.

I want to start the program at 0x0800_0010 instead. The reason for the extra bytes at the beginning of flash is to save status bytes that indicate the state of the startup or bootloader in case of a failure during firmware updates.

By going into flash options in KEIL uVison, I can change the ROM settings to program to flash starting at that address.

If I then go to the LINK Utility, I can see that the program does indeed start at the new address, but it will not execute.

The program is still probably still starting at the beginning of flash.

Searching through the files in the project, I find various #defines that may or may not affect where the program starts running. I have stepped through the startup sequence and did not see anything with that address that could be changed.

I tried changing the base address for the Ram fro 0x0800_0000 to the new address, thusly:

#define RamAddress        (IO_BASE+0x08000010)

How do I get the program to start executing at 0x0800_0010 instead of 0x0800_0000?

Thank you for your help!

    This topic has been closed for replies.
    Best answer by Tesla DeLorean
    Posted on June 24, 2017 at 01:45

    That's not how the processor works, you don't get to decide.

    Use the RAM, BKPRAM, or carve out one of the 16KB blocks at 0x08004000, 0x08008000, or 0x0800C000

    The Vector Table (via SCB->VTOR) can be relocated to another address on a 512-byte boundary later.

    Put a CRC or checksum around the Boot Loader or Application image so you can validate them. In the case of a corrupt application, don't jump into it, but fall back into a download or recovery mode. Past state from one reset to the next by placing data in RAM. ie Application sets ma-gic value in RAM, resets, boot loader sees this and erases application and downloads or updates new copy. Reset does not clear RAM, power cycling brings it up in a non-specific state.

    15 replies

    Tesla DeLorean
    Tesla DeLoreanBest answer
    Guru
    June 23, 2017
    Posted on June 24, 2017 at 01:45

    That's not how the processor works, you don't get to decide.

    Use the RAM, BKPRAM, or carve out one of the 16KB blocks at 0x08004000, 0x08008000, or 0x0800C000

    The Vector Table (via SCB->VTOR) can be relocated to another address on a 512-byte boundary later.

    Put a CRC or checksum around the Boot Loader or Application image so you can validate them. In the case of a corrupt application, don't jump into it, but fall back into a download or recovery mode. Past state from one reset to the next by placing data in RAM. ie Application sets ma-gic value in RAM, resets, boot loader sees this and erases application and downloads or updates new copy. Reset does not clear RAM, power cycling brings it up in a non-specific state.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Gordon Madden
    Associate III
    July 18, 2017
    Posted on July 18, 2017 at 00:32

    Hi Clive,

    What does 'carve out' mean in relation to the Flash pages (if that's what you mean by blocks)?

    Does that mean that I can start the application execution, somehow, at page 2 ( 0x08004000 )?

    From your answer, I thought that was not possible.

    I tried leaving a word in SRAM that I don't erase until the upgrade is finished, but in the case of a power interruption,

    and reset, there are (potentially) no files left. How can you tell the processor to do something if there is no code?

    One of my tests left the Flash completely erased and I am unsure how to recover from that scenario.

    Thanks for your insight on this!

    Tesla DeLorean
    Guru
    July 18, 2017
    Posted on July 18, 2017 at 02:27

    Carve out means to leave a hole, ie the code/text section runs from 0x08000000..0x08003FFF, and then 0x08008000..0x080FFFFF

    You do this via your scatter file, or linker script, so the linker leaves a unused hole at the 16KB sector located at 0x08004000..0x08007FFF, which you can then read/write/erase without disturbing your other code and data.

    In a robust implementation you'd build at 16KB loader that lives at 0x08000000..0x08003FFF, and place your application code at 

    0x08008000..0x080FFFFF, leaving 0x08004000..0x08007FFF for your calibration data. If you need more data, push the app deeper into the FLASH.

    Then you'd never ever erase the loader, and the loader would only transfer control to the application if the image is validated (checksum, crc, sha-256, or whatever). Leaving the loader alone means there's always something bootable, and the customer can't entirely brick the device.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Zt Liu
    Senior III
    June 23, 2017
    Posted on June 24, 2017 at 01:46

    If I understand correctly,

    the core always starts from 0x00000000 to fetch the initial value for main stack point, then  perform the reset handler routine. If you change the ROM setting in your project setting, it really will produce a memory map as you config for THIS Project.

    However, a power on reset always starts from 0x00000000. 

    You may store your status bytes in the image of your boot-loader, or just leave it in last page of ROM, or eeprom if you have it.

    Tesla DeLorean
    Guru
    June 24, 2017
    Posted on June 24, 2017 at 01:53

    Executes from table at zero, but the base of FLASH, RAM or ROM is mapped/shadowed there via the BOOTx pin settings. But it loads a PC from +4 and that address almost always points to the native address of the code, ie

    +0  0x20002000  Stack top in RAM

    +4 0x08000123 ResetHandler address in FLASH

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Zt Liu
    Senior III
    June 24, 2017
    Posted on June 24, 2017 at 02:03

    Nice catch!

    I forgot the remap mechanism!

    Gordon Madden
    Associate III
    June 24, 2017
    Posted on June 24, 2017 at 02:57

    Thanks for the answers, I'm trying to follow along.

    So, first I went to the flash options in KEIL uVision and set the IROM to 0x0800_0010, instead of 0x0800_0000 (below)

    0690X00000607RPQAY.png

    In the SystemInit() function in system_stm32f4xx.c file, there is a Vector Table setting for FlashBase

      /* Configure the Vector Table location add offset address ------------------*/

    #ifdef VECT_TAB_SRAM

     SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM*/

    #else

     SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in InternalFLASH*/

    #endif

    Then I set the #define for the FlashBase (Peripheral Memory Map in stm32f417xx.h) to 0x0800_0010U, instead of 0x0800_0000U (below)

    #define FLASH_BASE 0x08000010U /*!< FLASH(up to 1 MB) base address in the alias region*/

    I then compiled and loaded the program, but it does not run. Opening the ST-LINK Utility and connecting to the device shows that the program is loaded at 0x0800_0010 (below).

    0690X00000607L8QAI.png

    So, changing the #define for the FlashBase doesn't work and I don't understand exactly why.

    Above, CliveOne mentions that the VTOR could be changed to another address at a 512 offset.

    How would you set the program to start executing at 0x0800_4000 (the next page, 16K later)?

    If you can do that, why not at 0x0800_0010?

    I will look into using SRAM for saving the state as CliveOne suggests.

    Thanks again!

    Tesla DeLorean
    Guru
    June 24, 2017
    Posted on June 24, 2017 at 18:03

    You don't get to define the address, the processor isn't going to start at 0x08000010 or 0x08004000 just because you want it to. The silicon doesn't provide that functionality.

    Put the data some place else.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    henry.dick
    Associate II
    May 10, 2018
    Posted on May 10, 2018 at 14:13

    Many ways of doing it, like jumping to that address....

    The easiest in C would be to declare a function pointer, point it to that address, and execute that function pointer.

    From the cpus perspective it doesnt matter where the code is or if it is valid. It simply fetches and executes.