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-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 }
};
2026-02-11 2:31 AM - edited 2026-02-11 2:39 AM
Hello,
You've located these sections to the Flash
} > EXT_SRAM_DATA AT> FLASH
Remove > FLASH from these sections:
.ext_sram_data :
{
. = ALIGN(8);
KEEP(*(.ext_sram_data))
KEEP(*(.ext_sram_data*))
. = ALIGN(8);
} > EXT_SRAM_DATA
2026-02-11 3:23 AM
Hello,
I have two section, one for DATA and other for MODULES, so my expectation is if I can be able to move complete object to external RAM then it will be useful. So, I have updated the .ld file as explain in the description.
I have tried to remove AT FLASH from MODULES and DATA section both but still I can't see the global or static variable at the top in the external RAM memory still I can see they have used the internal RAM address.
So, what configuration I missed here to achieved this, to move complete module to external SRAM.
Thanks,
Nitin
2026-02-20 4:29 AM - edited 2026-02-20 4:41 AM
Hello,
I have tried to remove FLASH but looks like it can see in. map file at the address, but I can't see it has any size allocated, why? And code is running.
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
EXT_FLASH (rx) : ORIGIN = 0x64000000, LENGTH = 16M
EXT_SRAM_HEAP (xrw) : ORIGIN = 0x60000000, LENGTH = 256K
EXT_SRAM_STACK (rw) : ORIGIN = 0x60040000, LENGTH = 256K
}
.ext_sram_stack :
{
. = ALIGN(8);
*(.ext_sram_stack*) /* Use for __attribute__((section(".ext_sram_stack"))) */
*(.ext_sram_stack)
*testModule.cpp.obj(.text .text.* .rodata .rodata.*)
. = ALIGN(8);
} >EXT_SRAM_STACK
Here is .map file
.ext_sram_stack
0x60040000 0x0
0x60040000 . = ALIGN (0x8)
*(.ext_sram_stack*)
*(.ext_sram_stack)
*testModule.cpp.obj(.text .text.* .rodata .rodata.*)
0x60040000 . = ALIGN (0x8)
Other section of .map file
Memory Configuration
Name Origin Length Attributes
RAM 0x20000000 0x00080000 xrw
FLASH 0x08000000 0x00200000 xr
EXT_FLASH 0x64000000 0x01000000 xr
EXT_SRAM_HEAP 0x60000000 0x00040000 xrw
EXT_SRAM_STACK 0x60040000 0x00040000 rw
*default* 0x00000000 0xffffffffThanks
2026-02-23 12:34 AM
Hi @npatil15 !
You could also check the output from the ELF file with arm-none-eabi-size directly, like the following example:
$ arm-none-eabi-size -A -x test.elf
test.elf :
section size addr
.text 0x1474 0x8000000
.rodata 0x26 0x8001474
.data 0x0 0x24000000
.bss 0x8 0x24000000
.heap 0x7eff8 0x24000008
.stack 0x1000 0x2407f000
.ARM.attributes 0x2f 0x0
.comment 0x24 0x0
Total 0x814ed
$I doesn't calculate the usage in percent and also doesn't show the name from the memory region, but should show all section addresses and sizes from the ELF file as defined in the linker script.
2026-02-24 3:57 AM - edited 2026-02-24 4:06 AM
Hello @mƎALLEm & @JohannesK ,
Somehow, I got success in small thing. I can be able to load .data section of testModule to external SRAM. Now I need support on to load .text section so that I can store code section in external sram.
Check below, where I have tried to add all the things related to testModule, thinking it should not miss anything while loading any function or data, and when I just keep (.data .data.*) then it works as it does not need to load any function here.
.ext_sram_stack :
{
. = ALIGN(4);
/* Option A: attribute-tagged entities */
*(.ext_sram_stack)
*(.ext_sram_stack.*)
/* Use wildcard to be resilient to path differences */
*testModule*(.text .rodata .ARM.extab .preinit_array .init_array .fini_array .data .tdata)
*testModule*(.text.* .rodata.* .ARM.extab.* .preinit_array.* .init_array.* .fini_array.* .data.* .tdata.*)
. = ALIGN(4);
__ext_stack_start__ = ADDR(.ext_sram_stack);
__ext_stack_end__ = .;
} > EXT_SRAM_STACK AT> EXT_FLASH
__ext_stack_load__ = LOADADDR(.ext_sram_stack);
__ext_stack_size__ = SIZEOF(.ext_sram_stack);And here below just after FMC_Iinit() I have write this logic to load the EXT_FLASH data to EXT_SRAM_STACK, currently I'm not sure does the location is correct or not.
extern uint8_t __ext_stack_start__, __ext_stack_end__, __ext_stack_load__;
uint8_t *dst = &__ext_stack_start__;
uint8_t *end = &__ext_stack_end__;
uint8_t *src=&__ext_stack_load__;
size_t n = (size_t)(end - dst);
for (size_t i = 0; i < n; ++i)
dst[i] = src[i];
__DSB();
__ISB();Here is .map file
0x60040000 __ext_stack_start__ = ADDR (.ext_sram_stack)
0x60051d98 __ext_stack_end__ = .
0x64000000 __ext_stack_load__ = LOADADDR (.ext_sram_stack)
0x00011d98 __ext_stack_size__ = SIZEOF (.ext_sram_stack)Here below the function, I'm trying to access
.text.testModuleTaskWrapper
0x600498cc 0x1c CMakeFiles/MCU_Configuration.dir/Classes/TestModule/src/testModule.cpp.obj
0x600498cc testModuleTaskWrapperI can see all the function are not pointing to external sram address range.
For information:
MCU_Configuration.elf :
section size addr
.isr_vector 0x1f8 0x8000000
.ext_flash_code 0x0 0x64000000
.ext_sram_stack 0x11d98 0x60040000
.text 0x32f50 0x8000200
.rodata 0x3c7c 0x8033150
.ARM.extab 0x0 0x8036dcc
.ARM 0x8 0x8036dcc
.preinit_array 0x0 0x8036dd4
.init_array 0x18 0x8036dd4
.fini_array 0x4 0x8036dec
.data 0x1dc 0x20000000
.tdata 0x0 0x200001dc
.tbss 0x0 0x200001dc
.bss 0x1cecc 0x200001e0
._user_heap_stack 0x604 0x2001d0ac
.ext_sram_heap 0x0 0x60000000
.ARM.attributes 0x2e 0x0
.comment 0x43 0x0
.debug_info 0x1426fb 0x0
.debug_abbrev 0x1fe93 0x0
.debug_aranges 0x8808 0x0
.debug_rnglists 0x6756 0x0
.debug_macro 0x6ae7f 0x0
.debug_line 0x888f4 0x0
.debug_str 0x179e41 0x0
.debug_frame 0x25c84 0x0
.debug_line_str 0x16b 0x0
.debug_loclists 0x232b 0x0
Total 0x46ce57So, help me out what I'm missing here?
Thanks,
Nitin
2026-02-24 5:53 AM
Hello,
Sorry, for my maybe *** question. But what do you mean with that the code from testModule.cpp.obj is not pointing to external SRAM?
As I can see in your posted extract from the map file it's located in EXT_RAM_STACK as you defined in linker script:
.text.testModuleTaskWrapper
0x600498cc 0x1c CMakeFiles/MCU_Configuration.dir/Classes/TestModule/src/testModule.cpp.obj
0x600498cc testModuleTaskWrapperThe entry point from the function testModulTaskWrapper should be at address 0x600498CC in the range from EXT_RAM_STACK according your linker script. You have defined it here:
} > EXT_SRAM_STACK AT> EXT_FLASH
You have defined these memory sections above:
EXT_FLASH (rx) : ORIGIN = 0x64000000, LENGTH = 16M EXT_SRAM_HEAP (xrw) : ORIGIN = 0x60000000, LENGTH = 256K EXT_SRAM_STACK (rw) : ORIGIN = 0x60040000, LENGTH = 256K
You have placed all sections from testModule.cpp.obj in EXT_RAM_STACK loaded from EXT_FLASH currently.
What behavior do you want exactly? Do you want that the code from testModule.cpp.obj is located EXT_SRAM_HEAP which you defined as executable (xrw) too? Or should the code (.text) from testModule.cpp.obj execute from external flash? Sorry, I don't know exactly what you need.
BTW: Your copy function (FLASH to SRAM) should be okay. But you might to need call the function pointers from preinit_array, init_array and fini_array by yourself to get the main code work. So I would suggest to modify your current linker script and add start/end symbols for each sections. I can help you with an example, but first I need to know what behavior do you exactly need.
2026-02-24 6:11 AM
Hello @JohannesK ,
I want the testModule .text .text.* section to run from external SRAM. Currently when I tried it crashed and jump to Hardfault. So what I'm missing ?
In previous, it was working only with when I move testModule .data .data.* section to external SRAM.
Thanks,
Nitin
2026-02-24 6:22 AM
Hello @npatil15 ,
Okay, from EXT_RAM_HEAP or EXT_RAM_STACK? (You have defined EXT_RAM_STACK as read/write only.)
And according the Hardfault: Can you provide more debugging information? I mean the reason for the Hardfault.
Here is a good thread for debugging Hardfaults:
How to debug a HardFault on an Arm® Cortex®-M STM32
2026-02-24 6:37 AM
Hello @JohannesK ,
I was trying to run from EXT_RAM_STACK. And yes, it is read/write and that may be the reason it was failing?
I will try to make it executable permissions and update. And if still I got hardfault then I will come with debug information as per suggested link.
Thanks,
Nitin