Table of Contents
ARM Cortex-M7 for STM32H7xx
Vector table location
The bootloader itself occupies the location where normally the user program's vector table is located. The vector table in the user program therefore needs to be relocated. The bootloader implementation is such that the user program's vector table must be located at address 0x08020000 instead of the standard 0x08000000.
The vector table relocation can be achieved by changing the ROM start address in the linker descriptor file. Refer to the demo program for an example.
Note that the bootloader itself fits in way less than 128 kbyte. However, the smallest flash sector on the STM32H7 microcontroller is 128 kbyte. Therefore 128 kbyte needs to be reserved for the bootloader, otherwise the bootloader gets erased during a firmware update.
In case you want to manually change the size of the bootloader, make sure the size is aligned to the sectors as outlined in the flashLayout[] array in file flash.c. For the STM32H7xx targets, the sectors are 0x20000 (128 kbyte) in size, which is also the smallest erase size of the flash memory. This means that the reserved space for the bootloader should always be a multiple of 128 kbyte.
Before the bootloader starts your firmware, it automatically reconfigured the start address of the interrupt vector table. Unfortunately, the default system initialization function SystemInit() from ST's driver library, overwrites this change. This function is implemented in source file system_stm32h7xx.c. To correct this you need to explicitly set the start address of the interrupt vector table as the first thing in function main(). Here is an example of how this can be done when using STM32CubeIDE:
Add the following function to main.c:
static void VectorBase_Config(void) { /* The constant array with vectors of the vector table is declared externally in the * c-startup code. */ extern const unsigned long g_pfnVectors[]; /* Remap the vector table to where the vector table is located for this program. */ SCB->VTOR = (unsigned long)&g_pfnVectors[0]; }
And call this newly added function at the start of main():
int main(void) { /* Configure the vector table base address. */ VectorBase_Config(); ... }
Checksum location
A 32-bit checksum value is programmed by the bootloader at the end of a programming session. Upon startup, the bootloader verifies the correctness of this checksum to determine if a valid user program is present and can be started.
The bootloader programs this value at the end of the user program's vector table. Its exact location is configured by macro BOOT_FLASH_VECTOR_TABLE_CS_OFFSET in flash.c. The vector table size can vary based on the microcontroller derivative you are using. Please verify that the default value of BOOT_FLASH_VECTOR_TABLE_CS_OFFSET is correct. If not, you can simply override the value by adding the macro with the correct value to the blt_conf.h configuration header file.
The user program must reserve space for this 32-bit checksum value. To reserve this space, simply enter one extra dummy entry into the interrupt vector table. This reserves space for the checksum at memory address: flash base address + flash reserved for bootloader + FLASH_VECTOR_TABLE_CS_OFFSET. Refer to the demo program for an example.
Stackpointer initialization
On the ARM Cortex-M7 the first entry into the vector table holds the initialization value for the stackpointer, which is automatically loaded into the CPU's stackpointer register upon reset.
After reset, the bootloader gets started first and, if a valid user program is present, it is the bootloader's responsibility to start the user program. This unfortunately means that the automatic initialization of the CPU's stackpointer register does not work for the user program. The user program therefore needs to explicitly set the initial value of the CPU's stackpointer register in the reset interrupt service routine. Refer to the demo program for an example.
Multicore configuration
Certain STM32H7 devices feature a dual-core CPU consisting of a Cortex-M7 (CPU1) and a Cortex-M4 (CPU2). Each CPU has its firmware in its own flash region. By default, the first flash part is assigned to CPU1 and the second part to CPU2. The bootloader itself always runs on CPU1 after power-on and reset events.
The bootloader is able to reprogram the entire flash memory, including the part used by CPU2. For this to work properly, CPU2 should not access flash memory during firmware update operations. For this reason, the User Configuration Option Byte must be configured to disable the CM4 from booting.
Note that this is a different setting than the factory default. The easiest way to change this setting is by using the free STM32CubeProgrammer software in combination with an ST-Link debugger interface. This is what the BCM4 configuration bit should look like:
If you plan on using just CPU1 in your own user program, this is all that needs to be done. If you plan on using both CPU1 and CPU2, you need to now manually start the CPU2 core. The is best done in your CPU1 firmware at the start of function main():
When performing a firmware update on such a multicore device, you can either update the firmware on one core at a time or update them all at the same time (recommended). Note that you can use the free srec_cat tool to combine multiple firmware files into one large one, e.g.:
srec_cat firmware_cpu1.srec -Motorola firmware_cpu2.srec -Motorola -o firmware_all.srec -Motorola




