2022-06-01 01:34 PM
Hello,
I have a general question regarding the linker script generated by STM32CubeIDE.
Most of time the STACK and HEAP is placed together into the "same" internal SRAM (see section .user_heap_stack example for demonstration purpose).
Note: Yes, there is a chance that region can overlap, but this is something I don't want to discuss here.
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} > RAM_D1
I wanted to place some critical data, static variables, etc as well as the STACK pointer into the DTCRAM area. However, the heap is not used so heavily in our application therefore, I would like put it into a slower region e.g. RAM_D2/3.
I guess this should be possible , right ?
If I do so, I assume I can ge get rid of the ". = . + _Min_Stack_Size;"- statement in the linker script as the stack is now decoupled from the heap?
Furthermore, I assume that I need to modify the sbrk() function as well which is a fundamental part of the malloc call as there are some dependencies to linker symbols which are derived from the STACK handling . Is that correct?
Do we have a working example availble which cope with that decoupling of STACK and HEAP?
Solved! Go to Solution.
2022-06-08 12:56 AM
Hi,
Did you solve it?
To solve your issue you need to memory banks RAM_D1 for data/bss/stack, and maybe then RAM_D2 for heap. Split your linker script like this
Make sure stack pointer is set at the end of RAM_D1:
_estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1); /* end of RAM_D1 */
Split the output sections for heap and stack into two output sections:
._user_heap:
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = ALIGN(8);
} > RAM_D2
._user_stack :
{
. = ALIGN(8);
. = . + _Min_Stack_Size;
. = ALIGN(8);
} > RAM_D1
Caution: The _bsrk memory model assumes that the data is ordered like this:
LOWEST ADDRESS HIGHEST ADDRESS
.data .bss newlib heap stack
Have a look at line 68-73 in sysmem.c:
/* Protect heap from growing into the reserved MSP stack */
if (__sbrk_heap_end + incr > max_heap)
{
errno = ENOMEM;
return (void *)-1;
}
I assume that the RAM_D2 or RAM_D3 that you plan to use for the heap is located at a higher address in the memory space vs the RAM_D1? As a result the if-statement in the above code block will be true and _sbrk() will fail to allocate memory!
You need to remove/re-write this check.
I think that is all. Did not test on target.
Let us know if it worked or not and maybe we can make a small edit to this post if I missed something.
2022-06-08 12:56 AM
Hi,
Did you solve it?
To solve your issue you need to memory banks RAM_D1 for data/bss/stack, and maybe then RAM_D2 for heap. Split your linker script like this
Make sure stack pointer is set at the end of RAM_D1:
_estack = ORIGIN(RAM_D1) + LENGTH(RAM_D1); /* end of RAM_D1 */
Split the output sections for heap and stack into two output sections:
._user_heap:
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = ALIGN(8);
} > RAM_D2
._user_stack :
{
. = ALIGN(8);
. = . + _Min_Stack_Size;
. = ALIGN(8);
} > RAM_D1
Caution: The _bsrk memory model assumes that the data is ordered like this:
LOWEST ADDRESS HIGHEST ADDRESS
.data .bss newlib heap stack
Have a look at line 68-73 in sysmem.c:
/* Protect heap from growing into the reserved MSP stack */
if (__sbrk_heap_end + incr > max_heap)
{
errno = ENOMEM;
return (void *)-1;
}
I assume that the RAM_D2 or RAM_D3 that you plan to use for the heap is located at a higher address in the memory space vs the RAM_D1? As a result the if-statement in the above code block will be true and _sbrk() will fail to allocate memory!
You need to remove/re-write this check.
I think that is all. Did not test on target.
Let us know if it worked or not and maybe we can make a small edit to this post if I missed something.
2022-06-13 03:00 AM
> No need to touch startup code or sysmem.c (_sbrk).
> You need to remove/re-write this check
Hi Mattias these two statements are contradicting )) So there is a need to edit sysmem.c
to fix _sbrk()