This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

GNU GCC Stack and Heap Size Issues

The end of memory bss is @ 0x20002DAC (11692B). The start of the heap is @ 0x20002DB0 with a size of 2560B. The heap ends at 0x200037B0. The stack works back from the end 0x20004000 to 0x20003800 (14336B).

So there should be enough room and I should be able to allocate 2560B....?

BUT,

I have written two routines to check the stack and heap.

The stack checks memory for 0xDEADBEEF. This gives: Stack=1596B

That iterates through increasing block sizes (16B) until the heap fails. This gives: Heap=576B

So what am I missing?

And whats this object doing in the heap?
0x20002db0 0xa00 build/gcc_startup_nrf51.o

Is it overflow, and If so why does the compiler not complain and how can I get it to be more verbose about problems like this?

LINKER SCRIPT (NORDIC GCC) - Relevant code of the script:

    .syntax unified
    .arch armv6-m

    .section .stack
    .align 3
    .equ    Stack_Size, 2048
    .globl    __StackTop
    .globl    __StackLimit
__StackLimit:
    .space    Stack_Size
    .size __StackLimit, . - __StackLimit
__StackTop:
    .size __StackTop, . - __StackTop

    .section .heap
    .align 3
    .equ    Heap_Size, 2560
    .globl    __HeapBase
    .globl    __HeapLimit
__HeapBase:
    .if    Heap_Size
    .space    Heap_Size
    .endif
    .size __HeapBase, . - __HeapBase
__HeapLimit:
    .size __HeapLimit, . - __HeapLimit

MAP FILE - Relevant output of the map file:

.bss           0x20001da8        0x0 ../../tools/gccarm/arm-none-eabi/lib/armv6-m\libnosys.a(_exit.o)
 *(COMMON)
 COMMON         0x20001da8     0x1000 build/fifo.o
                0x20001da8                uFifoTxMem
                0x200025a8                uFifoRxMem
 COMMON         0x20002da8        0x4 ../../tools/gccarm/arm-none-eabi/lib/armv6-m\libc.a(lib_a-reent.o)
                0x20002da8                errno
                0x20002dac                . = ALIGN (0x4)
                0x20002dac                __bss_end__ = .

.heap           0x20002db0      0xa00
                0x20002db0                __end__ = .
                0x20002db0                end = __end__
 *(.heap*)
 .heap          0x20002db0      0xa00 build/gcc_startup_nrf51.o
                0x20002db0                __HeapBase
                0x200037b0                __HeapLimit = .

.stack_dummy    0x20002db0      0x800
 *(.stack*)
 .stack         0x20002db0      0x800 build/gcc_startup_nrf51.o
                0x20004000                __StackTop = (ORIGIN (RAM) + 0x3ff8)
                0x20003800                __StackLimit = (__StackTop - SIZEOF (.stack_dummy))
                0x20004000                PROVIDE (__stack, __StackTop)
                0x00000001                ASSERT ((__StackLimit >= __HeapLimit), region RAM overflowed with stack)
OUTPUT(build/main_xxab.out elf32-littlearm)
Parents
  • Post the code you're using to determine that the stack and heap only have 1596 and 576 bytes respectively. You clearly have a whole load more than that so unless something else is using heap on startup, like a linked-in library etc, you have close to 0xa00 bytes available. Close to as the heap itself will have some overhead book-keeping the allocations.

    That object isn't 'in the heap', those global symbols are defined in gcc_startup_nrf51.s in the .heap section and are then used in startup to initialize the heap. Those 0xA00 bytes are your heap.

  • No it's not allocating words, it's allocating bytes (on a nice pointer boundary of 4 bytes, but still it's contiguous bytes from there). Stuff like this is really frustrating when it doesn't work.

    Basic startup goes like this. reset handler calls SystemInit and then calls _start. _start is defined in whichever crt is linked into your code and that takes all the globals the linker set and zeros memory, sets up the stack, sets up the heap etc. The source of gcc malloc is available but last time I looked at it it was horrible. I had this feeling that gcc doesn't just set up the heap as you'd expect and zero it but uses a dynamic page-on-demand (sbrk) to do the job. It's possible that actually does think you are running out of mem.

    I can't help much more - I stopped with gcc a while ago and moved to Crossworks and that gives me the source of crt0 and of malloc and its' all very simple.

Reply
  • No it's not allocating words, it's allocating bytes (on a nice pointer boundary of 4 bytes, but still it's contiguous bytes from there). Stuff like this is really frustrating when it doesn't work.

    Basic startup goes like this. reset handler calls SystemInit and then calls _start. _start is defined in whichever crt is linked into your code and that takes all the globals the linker set and zeros memory, sets up the stack, sets up the heap etc. The source of gcc malloc is available but last time I looked at it it was horrible. I had this feeling that gcc doesn't just set up the heap as you'd expect and zero it but uses a dynamic page-on-demand (sbrk) to do the job. It's possible that actually does think you are running out of mem.

    I can't help much more - I stopped with gcc a while ago and moved to Crossworks and that gives me the source of crt0 and of malloc and its' all very simple.

Children
No Data
Related