- Mon Aug 29, 2011 11:09 pm
#132680
Hi all, I'm working with an LPC2148 and can't seem to get malloc working. I'm using the latest codesourcery package to build the project. Everything works fine, except I can't use malloc (not even 4 bytes). It's a bare metal project, so you have to define your own versions of the system calls; which for malloc, is apparently _sbrk_r(). So, here's what I have for that:
Code: Select all
Now when I step through it in the debugger (using OpenOCD), it ends up hitting the line "return (caddr_t) -1;" which I assume is what's causing malloc to fail. So my question is, what exactly does sbrk_r() do and is that check for (heap_end +inc) > stack_ptr correct? The stack grows downward (so the heap grows upward, right?), so it seems to me you would want to initialize heap_end to the very bottom of the stack. But instead, it's being initialized to the top of the stack. Here's my linker script:register char *stack_ptr asm ("sp");
caddr_t _sbrk_r(void *reent, size_t incr)
{
// Defined by the linker
extern char end asm ("end");
static char *heap_end = NULL;
char *prev_heap_end;
if(heap_end == NULL)
heap_end = &end;
prev_heap_end = heap_end;
if(( heap_end + incr ) > stack_ptr )
return (caddr_t) -1;
heap_end += incr;
return (caddr_t) prev_heap_end;
}
Code: Select all
...and the pertinent .map section:/* Reset vector for linker. */
ENTRY(_boot)
/* Stack sizes for C run-time as well as interrupts, supervisor, abort
and undefined conditions. NOTE: This is the only place you have to
change the stack size information. The crt.s assembler uses these values
to set and clear the stack. */
C_STACK_SIZE = 0x1000;
IRQ_STACK_SIZE = 0x400;
FIQ_STACK_SIZE = 0x100;
SVC_STACK_SIZE = 0x100;
ABT_STACK_SIZE = 0x100;
UND_STACK_SIZE = 0x100;
MEMORY
{
flash (rx) : ORIGIN = 0x00000000, LENGTH = 512K
ram_isp_low(a) : ORIGIN = 0x40000120, LENGTH = 223
ram(rw) : ORIGIN = 0x40000000, LENGTH = 0x7f00
ram_isp_high(a) : ORIGIN = 0x40007FE0, LENGTH = 32
ram_usb_dma(rw) : ORIGIN = 0x7FD00000, LENGTH = 8192
}
SECTIONS
{
/* Interrupt vectors must start at memory 0x00000000. */
.crt :
{
. = ALIGN(4);
*crt.o (.text)
. = ALIGN(4);
} >flash
/* Code (text) that is written to flash. */
.text :
{
*(.text) /* all .text sections (code) */
*(.rodata) /* all .rodata sections (constants, strings, etc.) */
*(.rodata*)
*(.glue_7); /* ARM/Thumb inter-networking glue functions */
*(.glue_7t);
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
} >flash
. = ALIGN(4);
/* Location in flash to save initialized data segment. */
.etext :
{
. = ALIGN(4);
_etext = .;
} >flash
/* All initialized data that is copied to RAM in the crt.s assembler file. */
.data : AT (_etext)
{
. = ALIGN(4);
_data = .;
*(.data)
_edata = .;
} >ram
/* BSS (Block Started by Symbol) block is the unitilized data segment. */
.bss :
{
__bss_start = . ;
*(.bss)
. = ALIGN (4);
__bss_end = .;
} >ram
/* Stack allocation for the application and interrupts and exceptions. */
.stack :
{
. = ALIGN(0x100);
__stack_start = . ;
. += IRQ_STACK_SIZE;
. = ALIGN (4);
__irq_stack_top__ = . ;
. += FIQ_STACK_SIZE;
. = ALIGN (4);
__fiq_stack_top__ = . ;
. += SVC_STACK_SIZE;
. = ALIGN (4);
__svc_stack_top__ = . ;
. += ABT_STACK_SIZE;
. = ALIGN (4);
__abt_stack_top__ = . ;
. += UND_STACK_SIZE;
. = ALIGN (4);
__und_stack_top__ = . ;
. += C_STACK_SIZE;
. = ALIGN (4);
__c_stack_top__ = . ;
__stack_end = .;
} >ram
end = .;
}
Code: Select all
If I set a breakpoint inside the _sbrk_r() function and dump the top 0x100 of the stack (stack top is at 0x40003900, I get the following:.stack 0x40001080 0x2880 load address 0x00014760
0x40001100 . = ALIGN (0x100)
*fill* 0x40001080 0x80 00
0x40001100 __stack_start = .
0x40001500 . = (. + IRQ_STACK_SIZE)
*fill* 0x40001100 0x400 00
0x40001500 . = ALIGN (0x4)
0x40001500 __irq_stack_top__ = .
0x40001600 . = (. + FIQ_STACK_SIZE)
*fill* 0x40001500 0x100 00
0x40001600 . = ALIGN (0x4)
0x40001600 __fiq_stack_top__ = .
0x40001700 . = (. + SVC_STACK_SIZE)
*fill* 0x40001600 0x100 00
0x40001700 . = ALIGN (0x4)
0x40001700 __svc_stack_top__ = .
0x40001800 . = (. + ABT_STACK_SIZE)
*fill* 0x40001700 0x100 00
0x40001800 . = ALIGN (0x4)
0x40001800 __abt_stack_top__ = .
0x40001900 . = (. + UND_STACK_SIZE)
*fill* 0x40001800 0x100 00
0x40001900 . = ALIGN (0x4)
0x40001900 __und_stack_top__ = .
0x40003900 . = (. + C_STACK_SIZE)
*fill* 0x40001900 0x2000 00
0x40003900 . = ALIGN (0x4)
0x40003900 __c_stack_top__ = .
0x40003900 __stack_end = .
0x40003900 end = .
Code: Select all
So clearly there's plenty of space at the bottom of the .stack section to allocate from. The problem seems to be that heap_end is initialized to 0x40003900, which will almost certainly *always* be larger than the stack pointer.... I must not understanding something. Any pointers would be greatly appreciated 0x40003800: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
0x40003820: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
0x40003840: deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef deadbeef
0x40003860: deadbeef deadbeef deadbeef deadbeef deadbeef 8000005f 000109ac 0000002e
0x40003880: 00000020 40000010 4000090c 40003900 40000a06 0000b028 4000090c 00000000
0x400038a0: e01fc040 12345678 16a3cf85 00000050 fb3bf9b3 673deee7 9e5a3e6d 000021a0
0x400038c0: 4000090c 0000d838 0000bdec 400038e0 16a3cf85 0000c270 0000ffff 0000c2c0
0x400038e0: 40000f08 40000a1c 4000090c 00000000 00000000 00000000 12345678 0000011c
0x40003900: b27d4d80 511d7980 47bb5f7b 33917c26 9fd11be2 1859a4b6 bb2fb47d 1398b400