Hi everyone,
I’m trying to run and debug my STM32 application from a custom Flash address in Keil, and I’m currently stuck.
I need to reserve around 136 KB of Flash for the bootloader, so my application should start at:
Application start address: 0x08022000
0x08022000
The same bootloader and application setup works correctly in STM32CubeIDE. I can flash and debug the application at both the default address and the custom offset. However, due to project requirements, I need to migrate the project to Keil MDK.
To isolate the issue, I tested with a simple Blinky application:
0x08000000
So far, I have tried the following:
#define VECT_TAB_OFFSET 0x22000U
.map
Even after going through many forum posts and trying the suggested solutions, I haven't been able to get this working. While debugging, the PC eventually jumps outside the valid Flash region.
Current behavior
STM32CubeIDE
Keil MDK
The same bootloader is used in both cases.
I’ve attached screensh;Scatter file LR_IROM1 0x08022000 0x001DE000 { ; load region size_region ER_IROM1 0x08022000 0x001DE000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } RW_IRAM1 0x20000000 0x0009FA00 { ; RW data .ANY (+RW +ZI) } ARM_LIB_HEAP 0x2009FA00 EMPTY 0x00000200 { } ARM_LIB_STACK 0x2009FC00 EMPTY 0x00000400 { } } Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x080241e8, Size: 0x00000418, Max: 0x0009fa00, ABSOLUTE) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x20000000 0x080241e8 0x00000004 Data RW 898 .data.SystemCoreClock system_stm32h5xx.o 0x20000004 0x080241ec 0x00000001 Data RW 856 .data.uwTickFreq stm32h5xx_hal.o 0x20000005 0x080241ed 0x00000003 PAD 0x20000008 0x080241f0 0x00000004 Data RW 855 .data.uwTickPrio stm32h5xx_hal.o 0x2000000c 0x080241f4 0x00000004 PAD 0x20000010 - 0x00000004 Zero RW 857 .bss.uwTick stm32h5xx_hal.o 0x20000014 0x080241f4 0x00000004 PAD 0x20000018 - 0x00000400 Zero RW 3 STACK startup_stm32h563xx.o Execution Region ARM_LIB_HEAP (Exec base: 0x2009fa00, Load base: 0x080241f8, Size: 0x00000200, Max: 0x00000200, ABSOLUTE) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x2009fa00 - 0x00000200 Zero RW 1 ARM_LIB_HEAP.bss anon$$obj.o Execution Region ARM_LIB_STACK (Exec base: 0x2009fc00, Load base: 0x080241f8, Size: 0x00000400, Max: 0x00000400, ABSOLUTE) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x2009fc00 - 0x00000400 Zero RW 2 ARM_LIB_STACK.bss anon$$obj.o SystemCoreClock 0x20000000 Data 4 system_stm32h5xx.o(.data.SystemCoreClock) uwTickFreq 0x20000004 Data 1 stm32h5xx_hal.o(.data.uwTickFreq) uwTickPrio 0x20000008 Data 4 stm32h5xx_hal.o(.data.uwTickPrio) uwTick 0x20000010 Data 4 stm32h5xx_hal.o(.bss.uwTick) __initial_sp 0x20000418 Data 0 startup_stm32h563xx.o(STACK) Image$$ARM_LIB_HEAP$$ZI$$Base 0x2009fa00 Number 0 anon$$obj.o ABSOLUTE Image$$ARM_LIB_HEAP$$ZI$$Limit 0x2009fc00 Number 0 anon$$obj.o ABSOLUTE Image$$ARM_LIB_STACK$$ZI$$Limit 0x200a0000 Number 0 anon$$obj.o ABSOLUTE ============================================================================== Memory Map of the image Image Entry point : 0x0802224d Load Region LR_IROM1 (Base: 0x08022000, Size: 0x000021f8, Max: 0x001de000, ABSOLUTE) Execution Region ER_IROM1 (Exec base: 0x08022000, Load base: 0x08022000, Size: 0x000021e4, Max: 0x001de000, ABSOLUTE) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x08022000 0x08022000 0x0000024c Data RO 5 RESET startup_stm32h563xx.o 0x0802224c 0x0802224c 0x00000008 Code RO 913 * !!!main c_w.l(__main.o) 0x08022254 0x08022254 0x00000034 Code RO 1098 !!!scatter c_w.l(__scatter.o) __Vectors_Size 0x0000024c Number 0 startup_stm32h563xx.o ABSOLUTE __Vectors 0x08022000 Data 4 startup_stm32h563xx.o(RESET) __Vectors_End 0x0802224c Data 0 startup_stm32h563xx.o(RESET) __main 0x0802224d Thumb Code 8 __main.o(!!!main)ots of my Keil target settings, scatter file, and relevant parts of the .map file.
;Scatter file LR_IROM1 0x08022000 0x001DE000 { ; load region size_region ER_IROM1 0x08022000 0x001DE000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) .ANY (+XO) } RW_IRAM1 0x20000000 0x0009FA00 { ; RW data .ANY (+RW +ZI) } ARM_LIB_HEAP 0x2009FA00 EMPTY 0x00000200 { } ARM_LIB_STACK 0x2009FC00 EMPTY 0x00000400 { } }
Execution Region RW_IRAM1 (Exec base: 0x20000000, Load base: 0x080241e8, Size: 0x00000418, Max: 0x0009fa00, ABSOLUTE) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x20000000 0x080241e8 0x00000004 Data RW 898 .data.SystemCoreClock system_stm32h5xx.o 0x20000004 0x080241ec 0x00000001 Data RW 856 .data.uwTickFreq stm32h5xx_hal.o 0x20000005 0x080241ed 0x00000003 PAD 0x20000008 0x080241f0 0x00000004 Data RW 855 .data.uwTickPrio stm32h5xx_hal.o 0x2000000c 0x080241f4 0x00000004 PAD 0x20000010 - 0x00000004 Zero RW 857 .bss.uwTick stm32h5xx_hal.o 0x20000014 0x080241f4 0x00000004 PAD 0x20000018 - 0x00000400 Zero RW 3 STACK startup_stm32h563xx.o Execution Region ARM_LIB_HEAP (Exec base: 0x2009fa00, Load base: 0x080241f8, Size: 0x00000200, Max: 0x00000200, ABSOLUTE) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x2009fa00 - 0x00000200 Zero RW 1 ARM_LIB_HEAP.bss anon$$obj.o Execution Region ARM_LIB_STACK (Exec base: 0x2009fc00, Load base: 0x080241f8, Size: 0x00000400, Max: 0x00000400, ABSOLUTE) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x2009fc00 - 0x00000400 Zero RW 2 ARM_LIB_STACK.bss anon$$obj.o SystemCoreClock 0x20000000 Data 4 system_stm32h5xx.o(.data.SystemCoreClock) uwTickFreq 0x20000004 Data 1 stm32h5xx_hal.o(.data.uwTickFreq) uwTickPrio 0x20000008 Data 4 stm32h5xx_hal.o(.data.uwTickPrio) uwTick 0x20000010 Data 4 stm32h5xx_hal.o(.bss.uwTick) __initial_sp 0x20000418 Data 0 startup_stm32h563xx.o(STACK) Image$$ARM_LIB_HEAP$$ZI$$Base 0x2009fa00 Number 0 anon$$obj.o ABSOLUTE Image$$ARM_LIB_HEAP$$ZI$$Limit 0x2009fc00 Number 0 anon$$obj.o ABSOLUTE Image$$ARM_LIB_STACK$$ZI$$Limit 0x200a0000 Number 0 anon$$obj.o ABSOLUTE ============================================================================== Memory Map of the image Image Entry point : 0x0802224d Load Region LR_IROM1 (Base: 0x08022000, Size: 0x000021f8, Max: 0x001de000, ABSOLUTE) Execution Region ER_IROM1 (Exec base: 0x08022000, Load base: 0x08022000, Size: 0x000021e4, Max: 0x001de000, ABSOLUTE) Exec Addr Load Addr Size Type Attr Idx E Section Name Object 0x08022000 0x08022000 0x0000024c Data RO 5 RESET startup_stm32h563xx.o 0x0802224c 0x0802224c 0x00000008 Code RO 913 * !!!main c_w.l(__main.o) 0x08022254 0x08022254 0x00000034 Code RO 1098 !!!scatter c_w.l(__scatter.o) __Vectors_Size 0x0000024c Number 0 startup_stm32h563xx.o ABSOLUTE __Vectors 0x08022000 Data 4 startup_stm32h563xx.o(RESET) __Vectors_End 0x0802224c Data 0 startup_stm32h563xx.o(RESET) __main 0x0802224d Thumb Code 8 __main.o(!!!main)
Could anyone share a complete checklist for running an STM32 application from a custom Flash address in Keil?
Also, is there any important difference in how STM32CubeIDE and Keil handle the application entry point, vector table, scatter file, or debugger startup that could explain why the CubeIDE setup works while the equivalent Keil setup does not?
Any pointers on what I might be missing would be really helpful. Thanks!