Relocating code in flash during runtime and branching there

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Relocating code in flash during runtime and branching there

1,433 Views
michaelkoller
Contributor III

Hey, folks!

I have a bootloader project, where I have all the code in the address space 0x0000-0x3999 and above that is the app space, which we can assume to be empty for now.

What I want to do is start the bootloader (which is flashed to the mcu like usual), make itself copy to another memory space, then jump to the copied code and run from there (and keep running, even if I erase everything in the original bootloader space).

I understand that there are different segments, where 0x0 to 0x399 are vectors, 0x410 to somewhere below 0x4000 is program code and so on.

What I want to do is to start the program in the bootloader space. I compile the project with the -fPIC (position independent code) flag and flash it to the mcu. I also have disabled interrupts (disable_irq()).

During runtime the code in the bootloader space gets copied one to one to the app space, starting at 0x4000.

The next thing is how I jump to the new app. Therefore I have another project, where I have set the segment addresses accordingly (0x4000 for vectors, 0x4410 for m_text, etc.). Then I also flash that program, but to the app space. In my bootloader program I now build a function call to enter the app from the value that is stored at the (app start adress +4), the initial program counter. then I execute that function and now I am in the app. So I know, that this is a way to branch to another application, that is stored in flash besides the bootloader.

But what do I have to change in the vector table of the copied bootloader in the app space so that I can successfully jump there? I tried adding the the app start adress to every vector, except the msp at 0x0 (0x4000 in app space).

I would appreciate any pointers in the right direction and hope that I have formulated my question somewhat understandably.

Cheers,

Michael

0 Kudos
6 Replies

1,230 Views
michaelkoller
Contributor III

UPDATE

I have made some progress and can copy and jump to the new bootloader in the app space, but found the encountered the following problem:

Before the programm enters the new main function, in the new system startup code, this happens

    256c(656c):    1fffcbb0     .word    0x1fffcbb0 is in a register at some point, and then

the PC value is added, then the program branches to the resulting adressvalue.

The problem is probably, that normally, 0x1fffcbb0+ 0x2b47 is an ok adress, but 0x1fffcbb0+ 0x6b47 is > 0x20000000, which is not an ok adress in this context anymore.

When the program uses the PC value to calculate jump adresses, it's fine if it happens only in the flash adress context, but it can result in problems, if this method is also used to create jump adresses in the SRAM adress space. Because in flash space, everything moves, but the SRAM adresses stay the same, yet the program uses the modified PC (which is 0x4000) bigger than expected.

EDIT: More exactly: ldr r2, [r3, r2] causes the problem, because r3+r2 is no valid adress anymore, so the program complains if I want to dereference this.

Can I somehow let the program compile in a way, that the code is position independent for flash space and not independent (not using the pc) for other spaces (SRAM, Peripherals, etc.)?

Thanks for any pointers,

Michael

0 Kudos

1,230 Views
bobpaddock
Senior Contributor III

You may want to use Position Independent Executable -fPIE with or in place of PIC.

You may need to write your own compiler functions (libGCC / newlib etc) or recompile them with -fPIE/-fPIC.

Wrting the bootloader in pure assembly language would avoid that.

Sadly in the ARM world there is little documentation on exactly what supports position independent code.

0 Kudos

1,230 Views
michaelkoller
Contributor III

Ok, thanks a lot,

I'll keep trying, then!

0 Kudos

1,230 Views
michaelkoller
Contributor III

Hi,

thanks for your answer!

By setting the vector base address do you mean something like

        SCB->VTOR = ((uint32_t) APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);

or do you mean setting the correct values at 0x0 (MSP) and 0x4 (inital PC)?

Regards,

Michael

0 Kudos

1,230 Views
mjbcswitzerland
Specialist V

Hi

I mean SCB->VTOR.
From your discussion you already set the initial SP and initial PC correctly.

Regards

Mark

0 Kudos

1,230 Views
mjbcswitzerland
Specialist V

Hi


I would expect position independent code to be able to operate as long as you add the 0x4000 offset to the reset vector and interrupt vectors when it is located at 0x4000. However don't forget that you will also need to be able to detect at which area you are operating and set the vector base address to either 0 or 0x4000 too.

Beware that any reset or power cycle that takes place when the flash is erased between 0..0x3fff will cause failure to the board and the need to un-secure the flash again and reprogram with JTAG/SWD/EzPort. The length of time that the 0..0x3fff area is thus left erased should be kept as short as possible to reduce the chance of this happening. The technique would generally be used only in exceptional circumstances (where some bricked products are acceptable) or where users have a programming tool (eg. for firmware enginers or hobby users).

Regards

Mark

0 Kudos