2026-02-11 1:57 AM
Hello,
Trying to move complete *.cpp.obj to external SRAM configure via FMC. Check the below .ld file for STM32F7 controller.
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
EXT_SRAM_DATA (rw) : ORIGIN = 0x60000000, LENGTH = 256K
EXT_SRAM_MODULES (rw) : ORIGIN = 0x60040000, LENGTH = 256K
}
/* ========== Section for Buffers / Variables (up to 256KB) ========= */
.ext_sram_data :
{
. = ALIGN(8);
KEEP(*(.ext_sram_data))
KEEP(*(.ext_sram_data*))
. = ALIGN(8);
} > EXT_SRAM_DATA AT> FLASH
.ext_sram_modules :
{
. = ALIGN(8);
KEEP(*(testModule.cpp.obj))
. = ALIGN(8);
} >EXT_SRAM_MODULES AT> FLASH
After code compile, I can see the build details as
Memory region Used Size Region Size %age Used
RAM: 119928 B 512 KB 22.87%
FLASH: 246444 B 2 MB 11.75%
EXT_SRAM_DATA: 0 B 256 KB 0.00%
EXT_SRAM_MODULES: 0 B 256 KB 0.00%And .map file as below
.ext_sram_data 0x60000000 0x0 load address 0x0803c2ac
0x60000000 . = ALIGN (0x8)
*(.ext_sram_data)
*(.ext_sram_data*)
0x60000000 . = ALIGN (0x8)
.ext_sram_modules
0x60040000 0x0 load address 0x0803c2ac
0x60040000 . = ALIGN (0x8)
*(testModule.cpp.obj)
0x60040000 . = ALIGN (0x8)
I have tried to add uint8_t var[1024] global array in testModule.cpp but still I can see space has used from external SRAM.
So am I correctly using the feature to move complete object to external SRAM or if it is correct, where I can check that the space has been utilized?
Thanks,
Nitin
Solved! Go to Solution.
2026-02-24 7:16 AM
Hello @npatil15 ,
Have you defined an external loader to program the external flash with STM32CubeProgrammer for your board?
How to implement and use your own external flash loader: An example using STM32U5A9J-DK
It's only a guess. But if the external isn't programmed (empty) then a Hardfault is definitely also possible. Because AFAIK STM32CubeProg doesn't program the external flash (if any) automatically. Or you need to program the external flash with a externally hardware, if you don't want to use STM32CubeProg.
According the R/W flags from EXT_RAM_STACK:
I could be possible that this cause the Hardfault, in the case the start-up code initialize the MPU for this.
2026-02-25 1:38 AM - edited 2026-02-25 1:39 AM
Hello @JohannesK ,
I have tried to set EXT_RAM_STACK to (xrw) but the issue is same. And I'm using FMC to configure the external memory, so I don't think I need external flash loader, as my purpose is to just move a complete module to external SRAM to execute to make internal RAM free.
And done tried debug and below are some findings,
SCB
CFSR = 65536
HFSR = 1073741824
DFSR = 1
MMFAR = 0
BFAR = 0
AFSR = 0
And bsed on the Fault Status Registers:
Hardfault --> FORCEDAnd tried to view disassembly where it was cause hardfault, so it looks like it has no instruction to execute. So, its oblivious that it doesnt have anything to execute, even it may have execution permissions.
So, from this what do you think, what cause this to not generate instruction.
Thanks,
Nitin
2026-02-25 4:01 AM - edited 2026-02-25 4:08 AM
Hello @JohannesK ,
I have investigated somes,
I got success when I use "> EXT_SRAM_STACK AT> FLASH"
and got Hardfault when I do "> EXT_SRAM_STACK AT> EXT_FLASH"
So I observed the external flash itself doesn't have any code in it and that's why even after copy logic, SRAM didn't get any instruction from external Flash and that cause this issue undefined instruction error (Hardfault).
As you suggest, I guess, I need to work on external loader to loader the program to eternal flash, so I tried the changes in .launch file (for "serverExtLoader") as below in debugger setting. I'm not sure is it correct or not. I have external NOR Chip (S29GL128_STM32F746G-EVAL)
"version": "0.2.0",
"configurations": [
{
"type": "stlinkgdbtarget",
"request": "launch",
"name": "STM32Cube: STM32 Launch ST-Link GDB Server",
"origin": "snippet",
"cwd": "${workspaceFolder}",
"preBuild": "${command:st-stm32-ide-debug-launch.build}",
"runEntry": "main",
"imagesAndSymbols": [
{
"imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}"
}
],
/* Add the section below to enable External Flash programming */
"serverExtLoader": [
{
/* Replace this path with the correct .stldr for your specific NOR Flash chip */
"loaderPath": "C:/ST/STM32CubeCLT_1.20.0/STM32CubeProgrammer/bin/ExternalLoader/N25Q128A_STM32F746G-DISCO.stldr",
}
]
},But in debug consol I didn't see any programming done at this level for external Flash to copy the testModule.
Memory Programming ...
File : ST-LINK_GDB_server_a35400.srec
Size : 223.10 KB
Address : 0x08000000
2
Erasing memory corresponding to segment 0:
Erasing internal memory sectors [0 4]And I didnt find any correct information to do this same in vscode.
Thanks,
Nitin
2026-02-25 8:11 PM
Hello @JohannesK & @mƎALLEm ,
As per the above reply, I just need to know does I'm going to right direction, do I need to use external loader only to achieve this?
And the major question that may arise if external loader needs to use, is that, how I can exactly move testModule.o or any list of objects to external NOR Flash, from the entire .elf file.
The idea is, does it is even possible for this requirement or not.
Please let me know your suggestion so that I can start work on this.
Thanks,
Nitin
2026-03-06 4:16 AM
Hello @JohannesK,
I have written the custom loader, and it is working fine, I can able to copy some object section to external flash. And now code is running fine.
I have issue with one section, whenever I tried to run code directly from External Flash, I got some issue and cause hard fault.
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
EXT_FLASH (xrw) : ORIGIN = 0x64000000, LENGTH = 16M
EXT_SRAM_HEAP (xrw) : ORIGIN = 0x60000000, LENGTH = 256K
EXT_SRAM_STACK (xrw) : ORIGIN = 0x60040000, LENGTH = 256K
}
.ext_flash_xip :
{
. = ALIGN(4);
/* BULK STORAGE: Most of your 15MB lives here */
*TestObject*(.text .text* .rodata .rodata*)
/* Read-only Tables and Exception Frames */
*TestObject*(.ARM.extab* .gnu.linkonce.armextab.* .ARM.exidx*)
*TestObject*(.preinit_array* .init_array* .fini_array*)
/* Manual Attribute: __attribute__((section(".ext_xip"))) */
*(.ext_xip*)
*(.ext_xip)
. = ALIGN(4);
} >EXT_FLASHI want to understand here; does it fail because some section here should be part of external flash? Currently this section I keep just after the .isr_vector, so do I need to move this at the end?
Please guid me here, I just need to understand about XIP to run code in external flash, so that I should not use internal or external sram to copy external flash unnecessary data.
Thansk,
Nitin
2026-03-09 5:02 AM - edited 2026-03-09 5:05 AM
Hello @mƎALLEm or @JohannesK,
I'm very close to solution, as I explain above I can be able to load TestObject module to external NOR Flash using FMC. and also, able to execute everything if I perform copy external FLASH code to Internal RAM manually during init. But if I tried to run code directly from external Flash (XIP) then it doesn't work, so tried simple task
.ext_flash_xip :
{
. = ALIGN(4);
/* *TestObject*(.text .text*) */
/* *TestObject*(.rodata .rodata*) */
*(.ext_flash_xip*)
*(.ext_flash_xip)
. = ALIGN(4);
} >EXT_FLASHTried to keep only *TestObject*(.rodata .rodata*) and it works.
But if I tried to use only *TestObject*(.text .text*) then it doesnt work, so I tried to search and found that, the issue cause due to long jump from external flash to internal ram.
Crosscheck in .map file for that the functions of TestObject's are place at external address range.
So, I used flag (-mlong-calls) and now didn't crash the code, but it didn't run the function (Thread) which belongs to the external Flash.
I have tried to enable I and D-Cache and done below configuration for MPU. But nothing helps it.
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
HAL_MPU_Disable();
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x0;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.BaseAddress = 0x64000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}Mostly this issue cause due to using cpp object which causing long jump from external flash to internal ram and maybe it goes timeout and ignore/close the thread? So, I increase the timing to keep big buffer, but again it didn't help it.
hnor2.Instance = FMC_NORSRAM_DEVICE;
hnor2.Extended = FMC_NORSRAM_EXTENDED_DEVICE;
/* hnor2.Init */
hnor2.Init.NSBank = FMC_NORSRAM_BANK2;
hnor2.Init.DataAddressMux = FMC_DATA_ADDRESS_MUX_DISABLE;
hnor2.Init.MemoryType = FMC_MEMORY_TYPE_NOR;
hnor2.Init.MemoryDataWidth = FMC_NORSRAM_MEM_BUS_WIDTH_16;
hnor2.Init.BurstAccessMode = FMC_BURST_ACCESS_MODE_DISABLE;
hnor2.Init.WaitSignalPolarity = FMC_WAIT_SIGNAL_POLARITY_LOW;
hnor2.Init.WaitSignalActive = FMC_WAIT_TIMING_BEFORE_WS;
hnor2.Init.WriteOperation = FMC_WRITE_OPERATION_ENABLE;
hnor2.Init.WaitSignal = FMC_WAIT_SIGNAL_DISABLE;
hnor2.Init.ExtendedMode = FMC_EXTENDED_MODE_DISABLE;
hnor2.Init.AsynchronousWait = FMC_ASYNCHRONOUS_WAIT_DISABLE;
hnor2.Init.WriteBurst = FMC_WRITE_BURST_DISABLE;
hnor2.Init.ContinuousClock = FMC_CONTINUOUS_CLOCK_SYNC_ONLY;
hnor2.Init.WriteFifo = FMC_WRITE_FIFO_ENABLE;
hnor2.Init.PageSize = FMC_PAGE_SIZE_NONE;
/* Timing */
Timing.AddressSetupTime = 15;
Timing.AddressHoldTime = 15;
Timing.DataSetupTime = 200;
Timing.BusTurnAroundDuration = 15;
Timing.CLKDivision = 16;
Timing.DataLatency = 17;
Timing.AccessMode = FMC_ACCESS_MODE_A;
/* ExtTiming */
if (HAL_NOR_Init(&hnor2, &Timing, NULL) != HAL_OK)
{
Error_Handler( );
}Please I need your guidance, what I'm missing here?
Thanks
2026-04-05 9:20 PM - edited 2026-04-05 9:42 PM
Hello,
I found the root cause; I was moving objects to external Flash and that I can ensure by reading the external Flash from STM32CubeProgrammer. But as I move complete object then it also moved global, static to external Flash. And those variables need access before main() (i.e., before __libc_init_array).
So, when object has globally created heap region, that causes fault, because we haven't ready for heap related initialization. To solve this, we need to call "vPortDefineHeapRegions(xHeapRegions)" before "__libc_init_array" available in startup file, where we have create a array of heap regions.
HeapRegion_t xHeapRegions[] =
{
#if !USE_EXTERNAL_HEAP_ONLY
{ internalHeap, sizeof(internalHeap) },
#endif
{ &ext_sram_start, (size_t)(EXTERNAL_HEAP_SIZE) },
{ NULL, 0 }
};