Skip to main content
SBosc
Associate II
March 30, 2023
Question

How to putg all the code into RAM

  • March 30, 2023
  • 11 replies
  • 3662 views

Good morning,

I'm writing a bootloader and I need to put all the code in the RAM and execute from it (the microcontroller is a STM32F733).

The code is already working correctly from the flash.

How can I move it into the RAM?

Thanks in advance

This topic has been closed for replies.

11 replies

ST Employee
March 30, 2023

Hi @SBosc​,

What Type of IDE are you using ( IAR, STM32CubeIde or Keil )?

Regards

Diane

SBosc
SBoscAuthor
Associate II
March 30, 2023

Hi @Diane POMABIA​ ,

I'm using STM32CubeIde.

It seems that simply using the automatically generated linker script for RAM relocation is not enough...

Maybe not all the code is automatically copied by the startup routine?

Regards

Simone

Tesla DeLorean
Guru
March 30, 2023

Depends on the build options, most of the code can be relative if contained in one region.

You'll need to fixup the Vector Table content, as those have absolute addresses. And point SCB->VTOR at the appropriate location. Relocation shouldn't be unduly hard.

You'll likely need to at least walk the reset of the generated code to make sure there aren't any absolute addresses lurking, function pointers and the like.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
ST Employee
March 30, 2023

@SBosc​ 

yes, In system_stm32f7xx.c , you have also to uncomment "#define VECT_TAB_SRAM " and be sure that in your linker, you have selected correct linker script.

Regards

Diane

SBosc
SBoscAuthor
Associate II
March 30, 2023

@Diane POMABIA​ 

I've set the VECT_TAB_SRAM using the preprocessor.

It works when the execution is perfomed with the debugger connected (and continues to work even if I unplug the debugger on the fly) but it won't start if I try to boot without the debugger

@Community member​ 

Maybe you're right.

I think that there's a chance that program halts when an interrupt is generated.

I didn't remapped the vector addresses to the "new" RAM addresses!

There's a way to get the RAM addresses automatically? Or have I to rebuild "manually" the vector table?

Tesla DeLorean
Guru
March 30, 2023

Well the linker script defines where the code is expected to be parked, and the SystemInit() code has some dumb hard-coded method using defines rather than simply pulling the vector tables address symbolicly, and setting it into SCB->VTOR. If ST had done that from the outset you'd only need to change the base build address in ONE place.

>>There's a way to get the RAM addresses automatically?

Not sure how that'd work the linker frosts a particular build address because the content within this .ELF variant is expected to live at a fixed address in ROM. You can change that to RAM.

Automatic vs Manual, the processor doesn't do it, you'll likely need to automate the task yourself.

If the content starts in ROM/FLASH and you want to copy a runnable instance to RAM, you'd do the memcpy(), put the RAM image at a 512-byte aligned address, and then enumerate thru the 32-bit array that is the vector table, rebasing the address, ie subtract 0x08000000 then adding 0x20000000, if you use the base of RAM and it's unconflicted from other usage. Set the SCB->VTOR to the base address

Enter thru a control point, like the reset handler, and watch SystemInit() is a aware of the memory address it's running from, or leaves SCB->VTOR alone.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Pavel A.
March 30, 2023

As @Community member​ wrote, just set the VTOR.

The easiest way: don't fiddle with SystemInit(). Instead, in your main() just add this:

extern uint32_t g_pfnVectors[];
 SCB->VTOR = (uint32_t)g_pfnVectors;

 and use the linker script for RAM.

Now the question is, where you want to store this image: in the internal flash? some external memory?

Tesla DeLorean
Guru
March 30, 2023

This might be less helpful if the image is expected to reside in FLASH and RAM interoperably / interchangeably .

Also the RAM for variables/statics need to move to accommodate the firmware image.

Assumption here is that during updates the code needs to run from RAM so the FLASH stalling issue can be avoided.

When I copy code to RAM is typically a smaller self-contained blob, and it doesn't call other functions beyond the scope of the blob.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
SBosc
SBoscAuthor
Associate II
March 30, 2023

@Pavel A.​ 

The idea is to store bootloader into the internal flash, copy it on RAM and jump to RAM to execute the bootloader.

I need it because in my application there's an external watchdog circuit that resets the uC.

Erasing the internal flash sectors takes too long (and the flash stalls during the operation, so I can't execute code to kick the watchdog if sits in flash)

@Community member​ 

The BOOT option is correctly set to the start of the flash, where the bootloader is initially stored before the copy.

About the debugger, are you saying that it loads the content directly into RAM?

If it's true, it should set also the PC to execute directly from RAM...

Am I correct?

Pavel A.
April 2, 2023

>About the debugger

Yes you're correct. The debugger is smart, it knows how to load the program to RAM vs flash, and it knows how to set up the registers and start it. This is, btw, how it loads and executes the "external loaders". Of course you can copy this logic to your own project and load the STM32 code over the debugger interface.