1

I have a STM32F103VCT6 microcontroller with 48kb of SRAM, and recently i've got a memory collision:

I have some static variable (lets call it A) located in heap with size of 0x7000 and I wrote some simple function to get info about stack and heap:

void check(int depth) {
    char c;
    char *ptr = malloc(1);
    printf("stack at %p, heap at %p\n", &c, ptr);
    if (depth <= 0) return;
    check(depth-1);
}

So I got something like this:

stack at 2000939b, heap at 20008fd0
stack at 20009383, heap at 20008fe0
stack at 2000936b, heap at 20008ff0
stack at 20009353, heap at 20009000
stack at 2000933b, heap at 20009010
stack at 20009323, heap at 20009020
stack at 2000930b, heap at 20009030
stack at 200092f3, heap at 20009040
stack at 200092db, heap at 20009050
stack at 200092c3, heap at 20009060
stack at 200092ab, heap at 20009070

All static variables (incliding A) already got their heap, so heap is located at 0x8fd0. And seems like, originally, stack pointer is located at 0x939b, that is far away from 48kb (0xc000)

And when I changed the A variable size to 0x4000 I've got this picture:

stack at 2000639b, heap at 20005fd0
stack at 20006383, heap at 20005fe0
stack at 2000636b, heap at 20005ff0
stack at 20006353, heap at 20006000
stack at 2000633b, heap at 20006010
stack at 20006323, heap at 20006020
stack at 2000630b, heap at 20006030
stack at 200062f3, heap at 20006040
stack at 200062db, heap at 20006050
stack at 200062c3, heap at 20006060
stack at 200062ab, heap at 20006070

So, seems like stack location is not located at the end of SRAM but, some how, rely on user defined variables.

How can I align the stack to be at the very end of SRAM (at the 48kb)?

I am using the CooCox IDE with GNU Tools ARM Embedded toolchain.

Thank you!

EDIT:

Sorry for some misunderstanding here, A isn't const, i've called it static only because of keyword:

static uint8_t A[A_SIZE];    
printf("A is at %p\n", &A);

This shows that A is located at the begginning of the memory:

A is at 20000c08
desertkun
  • 1,027
  • 10
  • 19
  • 1
    Why do you think the static variables are allocated on the heap? It seems more likely from your results that they are located at top-of-ram, with the stack starting below them. Trying printing the address of `A` as well. – caf Jun 15 '15 at 02:20
  • 1
    This is probably controlled by your linker script. Read that (and read the mapfile to see the result of it) – M.M Jun 15 '15 at 06:05
  • "I have some static variable (lets call it A) located in heap" This doesn't make any sense so neither does the question (why all these up votes?). Static variables and dynamic variables are pretty much each other's opposites, hence the words "static" and "dynamic". Static variables are allocated in `.data/.bss`, dynamic variables on the heap, and local variables on the stack. Now, are you talking about static variables or dynamic variables? Because they can't be both at once. Please show the variable declaration and initialization of "A". – Lundin Jun 15 '15 at 14:19
  • @Lundin sorry for misunderstanding, updated the question – desertkun Jun 15 '15 at 20:04

2 Answers2

3

The GNU toolchain uses a target specific linker script (conventionally with a .ld file name extension). That will describe the memory layout of your target and can be customised to suit.

The manner in which you have deduced stack and heap location is somewhat non-deterministic and over-complicated. It is far simpler and entirely accurate to simply look at the map file output generated by the linker (ld command line option -Map <mapfile>).

The heap is by definition for dynamic allocation, so implicitly not use to allocate static data; that is a misconception on your part. The linker will allocate static data locations at build time. The linker script is likely to then allocate a fixed size stack, and then allocate all that remains and not reserved for other purposes to the heap. A customised script may also allocate areas for other purposes such as DMA buffers or battery-backed domains for example.

Either way, placement of the stack is hardly likely to be a solution to your actual problem; that just moves things around; it won't increase available memory; any stack overflow will simply collide with something else.

Clifford
  • 88,407
  • 13
  • 85
  • 165
  • Why would I get the memory collision in the same place every time, no matters how big is `A`? I would be happy to be wrong, but from my point of view, memory map looks like [this image](http://prntscr.com/7hd0t7). – desertkun Jun 15 '15 at 20:20
  • @desertkun : I am not sure I understand your illustration, but there is no need to guess what the memory map is; the linker script will tell you the static organisation of memory, and the link map file will tell you the precise addresses. Your diagram does persist the fallacy that the static data exists on the heap; it does not. The link map will also tell you the precise address of the static data. I would guess however that the heap size is reduced to accommodate the larger static data - the heap base address increases, but the heap top remains the same because the stack is fixed. – Clifford Jun 16 '15 at 09:11
0

I've found the reason: that's because stack size is actually fixed and it is located in heap (if I could call it heap).

In file startup_stm32f10x*.c there is a section:

/*----------Stack Configuration----------*/  
#define STACK_SIZE       0x00000100      /*!< The Stack size suggest using even number     */

And at then very next line:

__attribute__ ((section(".co_stack")))
unsigned long pulStack[STACK_SIZE];    

I've changed this value to 0x00000500 and got everything working.

desertkun
  • 1,027
  • 10
  • 19
  • 1
    You still should be able to adjust the location of `.co_stack` via the linker script, if you wanted it at a different address. – M.M Jun 15 '15 at 20:41
  • @MattMcNabb, stack have fixed size anyway, so here is no point of placing it in specific position (even at the end of SRAM) since linker can place some other variable directly before the beginning of the stack. Thank you for notice anyway. – desertkun Jun 15 '15 at 22:27