2026-02-05 5:56 AM - last edited on 2026-02-05 6:17 AM by Andrew Neil
I am using below component tools
MCU: STM32H750IBT6
IDE: STM32CubeIDE Version: 1.20.0
GUI: TouchGFX Version: 4.26.0
SDRAM: IS42S32400J-6TLI
FLASH: MT25QL512ABB8ESF-0SIT (QUADSPI)
I have made my own external loader that proves works for the QUADSPI IC using this video: https://www.st.com/content/st_com/en/support/learning/stm32-education/stm32-moocs/external_QSPI_loader.html
Thank you in advance!
2026-02-06 12:39 AM
@AEng7 wrote:
Thanks for the quick reply.
Would there be any compatibility issues as the pinout of the example STM32H750B-DK in terms of the QUADSPI will be different to my STM32H750IBT6 based custom PCB I have created, so surly a different bootloader would be needed?
Of course there will be a difference. You need to adapt your application based on your hardware.
Either The flashloader or the application loader need to be inline with your hardware: QSPI pins and memory config.
Hope I answred all your questions.
2026-02-06 12:42 AM - edited 2026-02-06 12:43 AM
The 'External Loader' maps the QuadSP and memory config. Would that include the SDRAM too?
However, you are suggesting I can use this exact 'bootloader' provided at https://github.com/STMicroelectronics/STM32CubeH7/tree/master/Projects/STM32H750B-DK/Templates/ExtMem_Boot
with the exact same bootloader.bin file?
2026-02-06 12:47 AM - edited 2026-02-06 12:48 AM
Looking at the STM32H750-DK code which I have working with TouchGFX.
The structure of all the user code is under 'Application'. Could I use the exact same Bootloader.bin file and develop the 'Application' code of my custom PCB around this structure?
/*
******************************************************************************
**
** File : LinkerScript.ld
**
** Author : Auto-generated by STM32CubeIDE
**
** Abstract : Linker script for STM32H750XBHx Device from STM32H7 series
** 128Kbytes FLASH
** 128Kbytes DTCMRAM
** 64Kbytes ITCMRAM
** 512Kbytes RAM_D1
** 288Kbytes RAM_D2
** 64Kbytes RAM_D3
**
** Set heap size, stack size and stack location according
** to application requirements.
**
** Set memory bank area and size if external memory is used.
**
** Target : STMicroelectronics STM32
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1); /* end of "RAM_D1" Ram type memory */
_Min_Heap_Size = 0x1000; /* required amount of heap */
_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Memories definition */
MEMORY
{
DTCMRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K
RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
RAM_D2 (xrw) : ORIGIN = 0x30000000, LENGTH = 288K
RAM_D3 (xrw) : ORIGIN = 0x38000000, LENGTH = 64K
SDRAM (xrw) : ORIGIN = 0xD0000000, LENGTH = 8M
FLASH (xrw) : ORIGIN = 0x90000000, LENGTH = 2048K
ASSETS_FLASH (r) : ORIGIN = 0x90200000, LENGTH = 126M
BOOTLOADER (xrw) : ORIGIN = 0x08000000, LENGTH = 128k
}
TARGET(binary) /* specify the file format of binary file */
INPUT (../../ExtMem_Boot/bootloader.bin) /* bootloader bin file path (relative to the output folder)*/
OUTPUT_FORMAT(default) /* restore the out file format */
/* Sections */
SECTIONS
{
.bootloader :
{
. = ALIGN(4);
KEEP(../../ExtMem_Boot/bootloader.bin)
} > BOOTLOADER
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
__ICFEDIT_intvec_start__ = .;
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH
/* The program code and other data into "FLASH" Rom type memory */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >FLASH
/* Constant data into "FLASH" Rom type memory */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : {
. = ALIGN(4);
*(.ARM.extab* .gnu.linkonce.armextab.*)
. = ALIGN(4);
} >FLASH
.ARM : {
. = ALIGN(4);
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
. = ALIGN(4);
} >FLASH
.preinit_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
} >FLASH
.init_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
} >FLASH
.fini_array :
{
. = ALIGN(4);
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/* Used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections into "RAM_D1" Ram type memory */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM_D1 AT> FLASH
/* Uninitialized data section into "RAM_D1" Ram type memory */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss section */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM_D1
/* User_heap_stack section, used to check that there is enough "RAM_D1" Ram type memory left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM_D1
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
FontFlashSection :
{
*(FontFlashSection FontFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >ASSETS_FLASH
TextFlashSection :
{
*(TextFlashSection TextFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >ASSETS_FLASH
ExtFlashSection :
{
*(ExtFlashSection ExtFlashSection.*)
*(.gnu.linkonce.r.*)
. = ALIGN(0x4);
} >ASSETS_FLASH
BmpCacheSection (NOLOAD) : { *(BmpCacheSection) } >SDRAM
TouchGFX_Framebuffer (NOLOAD) : { *(TouchGFX_Framebuffer) } >SDRAM
TouchGFX_Framebuffer1 (NOLOAD) : { *(TouchGFX_Framebuffer1) } >SDRAM
TouchGFX_Framebuffer2 (NOLOAD) : { *(TouchGFX_Framebuffer2) } >SDRAM
Video_RGB_Buffer (NOLOAD) : { *(Video_RGB_Buffer) } >SDRAM
}
2026-02-06 12:49 AM
Please read the read me file of ExtMem_Boot:
Define "CODE_AREA" , "DATA_AREA" and "BINARY_AREA" in file memory.h are used respectively to select the Code execution area, the application data area and the binary storage area. The ExtMem_Boot program is located at 0x08000000 (Internal flash).
2026-02-06 12:59 AM - edited 2026-02-06 1:23 AM
My confusion here is how bootloader.bin is generated and linked to the ExtMem_Boot section of the code.
I get the ExtMem_Boot code will have to be modified as the pinout is different, but doesn't the bootloader.bin file need to be regenerated for the modified ExtMem_Boot code -> hence the IAR would be needed to regenerate this file.
load the Project.bin (application binary output file) to the QSPI memory at the address 0x90000000
What software would I need to use to generate the Project.bin file?
Alternatively, if I were to upgrade the MCU to a pin-to-pin alternative (such as the STM32H743IIT6 I will veirfy with STM32MX it is compatible) but with 1024KB ram, would I need a bootloader? Considering if TouchGFX is used?
2026-02-06 1:23 AM
As it is taking too much time to get to the TouchGFX GUI design phase, if I require an IAR(I do not have a licence) to modify the ExtMem_Boot to produce the Project.bin file. I will upgrade my MCU on my custom PCBs.