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
  • Code is below. Its simply, just trys to allocate increasing blocks:

    uint32_t get_stack_status(void)
    {
       uint32_t stack = 0;
       uint32_t offset = 0;
       uint32_t *address = (uint32_t *) &__StackLimit;
       
       for (; offset<((uint32_t)&__StackTop-(uint32_t)&__StackLimit); offset=offset+4)
       {
          if (*(address + offset) != 0xDEADBEEF )
          {
             break;
          }
       }
       
       stack = ((uint32_t)&__StackTop - (uint32_t)&__StackLimit) - offset;
       return stack;
    }
    
    uint32_t get_heap_usage(void)
    {  
       uint16_t mul  = 0;
       uint16_t size = 0;
       uint8_t *mem  = 0;
       
       for (mul=1; mul<200; mul++)
       {
          size = mul*16;
          mem = (uint8_t*)malloc(size);
          
          if (!mem)
          {
             break;
          }
          
          free(mem);
       }
       
       return mul;
    } 
    

    I also use a bootloader where the stack pointers are reset to that of the main image and jumps to the startup of main image.

       /* Set the vector table offset to main image. */
       LDR   R0, =0x20000000
       LDR   R1, =0x8000
       STRH  R1, [R0]
       
       /* Set the stack pointer and jump to main. */
       LDR   R2, [R1]
       MSR   MSP, R2
       LDR   R3, [R1, #0x4]
       BX    R3
    

    I dont use the heap in the bootcode but is there anything that needs to be done.

Reply
  • Code is below. Its simply, just trys to allocate increasing blocks:

    uint32_t get_stack_status(void)
    {
       uint32_t stack = 0;
       uint32_t offset = 0;
       uint32_t *address = (uint32_t *) &__StackLimit;
       
       for (; offset<((uint32_t)&__StackTop-(uint32_t)&__StackLimit); offset=offset+4)
       {
          if (*(address + offset) != 0xDEADBEEF )
          {
             break;
          }
       }
       
       stack = ((uint32_t)&__StackTop - (uint32_t)&__StackLimit) - offset;
       return stack;
    }
    
    uint32_t get_heap_usage(void)
    {  
       uint16_t mul  = 0;
       uint16_t size = 0;
       uint8_t *mem  = 0;
       
       for (mul=1; mul<200; mul++)
       {
          size = mul*16;
          mem = (uint8_t*)malloc(size);
          
          if (!mem)
          {
             break;
          }
          
          free(mem);
       }
       
       return mul;
    } 
    

    I also use a bootloader where the stack pointers are reset to that of the main image and jumps to the startup of main image.

       /* Set the vector table offset to main image. */
       LDR   R0, =0x20000000
       LDR   R1, =0x8000
       STRH  R1, [R0]
       
       /* Set the stack pointer and jump to main. */
       LDR   R2, [R1]
       MSR   MSP, R2
       LDR   R3, [R1, #0x4]
       BX    R3
    

    I dont use the heap in the bootcode but is there anything that needs to be done.

Children
No Data
Related