2026-02-01 2:45 AM
Hello everyone,
I’m working with the STM32U5G9J-DK2 and trying to implement a Bootloader + XIP (Execute-In-Place) application architecture using the external flash.
Target setup:
A minimal bootloader running from internal flash
The main application linked to and executing from external flash (memory-mapped at 0x90000000)
The main motivation is to free internal flash and validate this approach for a future MCU with very limited internal flash.
Proper CubeMX / .ioc configuration for the bootloader
Which peripherals must be enabled (RCC, PWR, ICACHE, OSPI, etc.)
Which peripherals should not be enabled to avoid conflicts with the XIP app
Any STM32U5-specific gotchas when initializing OSPI for XIP
Proper configuration of the application project
Recommended changes to the application .ioc
What initialization should be removed from the app (HAL_Init, clock, OSPI, FLASH, etc.)
Reference samples
STM32Cube examples that demonstrate a full bootloader + XIP app flow on STM32U5
Any internal / unofficial sample projects that ST recommends adapting
I’m mainly looking for end-to-end guidance on how ST recommends structuring and configuring both the bootloader and the application for this use case.
Any pointers, samples, or best-practice recommendations would be greatly appreciated.
Thanks in advance,
AJ
2026-02-01 1:21 PM
Hello,
I did exactly now on this devboard RTC with additional functions like pictures slideshow and so on.
Maybe will be helpful the code of RTC project.
https://github.com/wegi1/STM32U5G9J-DK2-RTC
What is the most significancy in support at this board and many other Discovery kit, that is the Examples pack shared in CubeMX. How I try to programming this boards it is not like you perfection setup peripherial one by one, just I use and look at the examples and copy BSP libraries. For example when I "wake up" external flash, I used BSP files and additionally in CubeMX set HSPI as enable without any settings made. All of this doing for me 1 line invoking BSP function:
status = BSP_HSPI_NOR_Init(0, &Hspi_NOR_Init);And thats it. Whole function which read RAW data of picture into the frame buffer looks:
void readPicFromFlash(uint32_t pic_nr) {
/* HSPI info structure */
int32_t status;
uint8_t* pFBaddr;
uint32_t flash_offs;
status = BSP_HSPI_NOR_DeInit(0);
#define FRAME_ADDRESS ((uint32_t)0x200C0000)
Hspi_NOR_Init.InterfaceMode = BSP_HSPI_NOR_SPI_MODE;
// Hspi_NOR_Init.InterfaceMode = BSP_HSPI_NOR_OPI_MODE; // if you want OPI
Hspi_NOR_Init.TransferRate = BSP_HSPI_NOR_STR_TRANSFER;
status = BSP_HSPI_NOR_Init(0, &Hspi_NOR_Init);
if (status != BSP_ERROR_NONE)
{
Error_Handler();
}
else
{
pFBaddr = (uint8_t *) FRAME_ADDRESS;
for(uint32_t i = 0; i < (800*480*2) ; i++) {
pFBaddr[i] = 0;
}
flash_offs = 800*960*pic_nr;
/* Read data from the HSPI NOR memory */
if(BSP_HSPI_NOR_Read(0, pFBaddr, flash_offs, 800*960) != BSP_ERROR_NONE)
{
Error_Handler();
}
}
status = BSP_HSPI_NOR_DeInit(0);
}
I'm not sure in this kit external flash can be mapped at 0x90000000 bcos external loader working at 0xA0000000:
The most important help I find in BSP example application in example pack.
This same way I did XIP and bootloader when I struggled with STM32H750B-DK - the example of bootloader is in the example pack, and rest is only change linker script file which have flash address changed. MEMBootloader take about 8KB and its doesnt matter when internal flash exists 128KB.
Most important in MEMbootloader is running external flash in memory mapped mode, what it doing without any problem bcos it exists in Bootloader example.
Other way is the "N" disco STM32N6570-DK
where internal flash absolutly doesn't exists. It have only PROM which was programmed from factory with all possible bootloaders where you need running own program as first or second stage bootloader or application loaded by bootloader.
So maybe my programs are not perfect and literally used peripherials, but it is the fastest way to acheve communication with this hardware via BSP libraries. I'm not sure it is for you most desired style of code but it is :)