Mbed ram offset


I know this topic got several question answered already but I also want to be sure I got the informations right

I use in my work two boards:

  • Development board NUCLEO-F439ZI, I added an external clock but no other modification
  • Custom Board with a STM32F439ZI, built by my coworker

We used the stm32cube environment and we’re looking to slowly migrate to mbed. This leads to having codes compiled in two build environment (I made sure to have them use the exact same compiler). The code has been made as minimal as possible during my digging and is as follows:

int main() {
	    HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_12);

Of course the code in the stm32cube make the initialization of clocks and pins explicit but I didn’t put them here for readability purpose.

I then saw strange behaviour. The NUCLEO could run the two codes but the custom board could run the stm32cube code while failing to run the mbed code.

I first made sure the two board were as close as possible and it turned out the pin BOOT0 was left unconnected on the custom board. Unconnecting it in the NUCLEO board gave the same behaviour as the custom board.

The datasheet gives the following table:

The NUCLEO has his pin BOOT0 connected to the ground leading to have the code starting in the main flash memory.
The custom board has his pin BOOT0 unconnected and the BOOT1 pin connected to the ground leading the code to start in the system memory.

Investigating more I have found that the start address for the RAM is not the same in stm32cube environment and mbed (next lines taken from respectives .map files):

  • stm32:
Name             Origin             Length             Attributes
CCMRAM           0x10000000         0x00010000         xrw
RAM              0x20000000         0x00030000         xrw
FLASH            0x08000000         0x00200000         xr
*default*        0x00000000         0xffffffff
  • mbed:
Name             Origin             Length             Attributes
FLASH            0x08000000         0x00200000         xr
CCM              0x10000000         0x00010000         xrw
RAM              0x200001b0         0x0002fe50         xrw
*default*        0x00000000         0xffffffff

This post (link) indicates that the mbed offset is to give the availability of dynamic vector table.
I think this offset is the reason why the code from st works on the custom board and no the code from mbed.

My first question is simple. Did I get something wrong?

Based on what I found and know I see several possibilities to solve the problem:

  1. Redesign the hardware to connect the BOOT0 pin. Easiest solution by farwith the big downside that a new board needs to be produced (long time before being able to manipulate the board, even longer with the current component shortage)
  2. Retarget the address jumped to from 0x2000 0000 to 0x2000 01b0. I’m not sure it’s possible
  3. Modify mbedOS to remove this dynamic vector table. This is out of the picture obviously but I’m putting it here anyway.

Second question now : Did I missed something?
Followed by : Are the solution 2 and 3 even possible? Is there any other way to solve my problem?

I’m sorry if the solution 3 seems a bit desperate. I’ve been non stop looking for this problem for the last 2 weeks and I’m starting to feel out of civilized option (outside of solution 1 of course).

Best regards,

Hello Adrien,

The datasheet in section 3.15 Boot modes says:

At startup, boot pins are used to select one out of three boot options:

• Boot from user Flash
• Boot from system memory
• Boot from embedded SRAM

The boot loader is located in system memory. It is used to reprogram the Flash memory
through a serial interface. Refer to application note AN2606 for details.

It means that your custom board enters the built-in bootloader program so I’m afraid that the second and third options will not solve the problem.

I would recommend to read the section 4.1 Bootloader activation of the application note AN2606. In Table 2 of that section you can find Bootloader activation patterns and the following note:

BOOT_LOCK implementation is product dependent, refer to reference manual for more

In addition to patterns described above, user can execute bootloader by performing a jump
to system memory from user code. Before jumping to bootloader user must:

• Disable all peripheral clocks
• Disable used PLL
• Disable interrupts
• Clear pending interrupts

System memory boot mode can be exited by getting out from bootloader activation
condition and generating hardware reset or using Go command to execute user code.

Maybe the highlighted sections can help you to prevent entering the built-in bootloader or to exiting it.

Sorry for the late reply

Your answer pointed me in the right direction and my problem is now solved.

Have a nice day.