Home arrow Support arrow Forums

Luminary Micro Forums

<< Start < Prev 1 2 Next > End >>

dereksoftstuff

Expert Boarder

2008/07/25 05:00

HowTo : get malloc to work

To get dynamic memory allocation to work (malloc, free ...), means understanding the folowing 3 things :-
a) where's the heap
b) where's the stack
c) what's sbrk

I'm using an open-source tool-chain (codesourcery lite).

a) The heap is the region of RAM on your stellaris that isn't being using by your program.
So for example, on the LM3S6965 - 64k SRAM starts @2000 0000 and ends @ 2001 0000 (-1).
If you look in your map file, you'll find that you are only using say 2000 0000 to
2000 4000. This means that the RAM from 2000 4000 to 2001 0000 is unused (the heap) -
free for dynamic memory allocation. The heap grows upwards (increasing address).
You need to modify your linker script standalone.ld as follows :-
(only the last part of bss and the two provides are different from the standard)


Code:

  MEMORY {     FLASH (rx) : ORIGIN 0x00000000LENGTH 256K     SRAM (rwx) : ORIGIN 0x20000000LENGTH 64K } SECTIONS {     .text :     {         KEEP(*(.isr_vector))         *(.text*)         *(.rodata*)         _etext = .;     } > FLASH     .data AT (ADDR(.text) + SIZEOF(.text))     {         _data = .;         *(vtable)         *(.data*)         _edata = .;     } > SRAM     .bss :     {         _bss = .;         *(.bss*)         *(COMMON)         _ebss = .;         . = ALIGN (8);        _end = .;     } > SRAM } /* end of allocated ram _end */ PROVIDE_HEAP_START _end ); /* end of the heap -> align 8 byte */  PROVIDE _HEAP_END ALIGN(ORIGIN(SRAM) + LENGTH(SRAM) - ,8) );





This gives us access to the start and end address of the heap - on any Stellaris.
Note that the start address can change each time you rebuild, but we have it.


b) The stack is the region of RAM where the system puts all the function call parameter data & local data.
If you look in your startup.c file, you'll see something like this :-


#ifndef STACK_SIZE
#define STACK_SIZE 512
#endif
static unsigned long pulStack[STACK_SIZE];

__attribute__ ((section(".isr_vector")))
void (* const g_pfnVectors[])(void) =
{
(void (*)(void))((unsigned long)pulStack + sizeof(pulStack)), // The initial stack pointer

...

This is your stack start address and stack size. It's buried in your program's RAM.
You can find the real start address and end address in the map file if you want - but it's not important.
The stack grows downwards (decreasing address).
As long as the STACK_SIZE is big enough for your program, it will not overwrite your other RAM variables just preceeding it.
You could move your stack to the end of the heap and let it grow downwards - to one day meet your heap coming the other way,
but the above solution means that no collision is possible.


c) So, last time you tried to use malloc, it didn't compile because of an error - sbrk missing.

Malloc uses sbrk to get hold of the RAM addresses it will allocate back to you.
Note the use of our new PROVIDEs from the linker script, the memory addresses allocated can only be from our heap,
so there is no overlap with the program RAM. When all of the RAM is used, sbrk will tell malloc and malloc will tell you
- i.e. return NULL

Create a file called syscalls.c :-

Code:

  #include <sys/types.h> // linker (standalone.ld) sets heap start and end extern unsigned int  _HEAP_START; extern unsigned int  _HEAP_END; static caddr_t heap NULL; // low level bulk memory allocator - used by malloc caddr_t _sbrk int increment ) {       caddr_t prevHeap;     caddr_t nextHeap;          if (heap == NULL) {         // first allocation         heap = (caddr_t)&_HEAP_START;     }     prevHeap heap;                  // Always return data aligned on a 8 byte boundary      nextHeap = (caddr_t)(((unsigned int)(heap increment) + 7) & ~7);             // get current stack pointer      register caddr_t stackPtr asm ("sp");          // Check enough space and there is no collision with stack coming the other way     // if stack is above start of heap     if ( (((caddr_t)&_HEAP_START stackPtr) && (nextHeap stackPtr)) ||           (nextHeap >= (caddr_t)&_HEAP_END)) {             return NULL// error - no more memory      } else {         heap nextHeap;         return (caddr_tprevHeap;         }     }




Ready to go ...

login or register to reply

awneil

Gold Boarder

2008/07/25 16:01

Re:HowTo : get malloc to work

dereksoftstuff wrote:
c) what's sbrk

So, just out of idle curiosity, where does the name "sbrk" come from...?

login or register to reply

jrmymllr

Platinum Boarder

2008/09/17 06:38

Re:HowTo : get malloc to work

This is really a good post. Awhile back I was getting "_sbrk" errors and had no clue what this was. I searched for hours online with no resolution in sight. I finally figured out it was used by malloc, but I still didn't know what this function was supposed to do until someone in another forum provided a generic example. This one is just drop-in-and-go.

As a matter of fact, I think I'm going to use it. Mine doesn't check if I'm running off the RAM memory map.....

login or register to reply

dereksoftstuff

Expert Boarder

2008/09/19 10:25

Re:HowTo : get malloc to work

Hello JM

I just don't know how we can get by without dynamic memory ...

I've seen some of your posts on your project, are you going to share some of the good bits of code with us?

I'm putting together some building blocks that I'll post soon. There doesn't seem to be much about regarding simple generic code utilities etc.

The driverlib doesn't go far enough, and noone seems to be posting what they have done - is everyone building the same wheel? Or is everyone too shy ...

I'd like to see more development within the forum, so that newcomers can start off with some good stuff.
And we can create some solid flexible utilities.

Anyone else out there? or shall I continue making my own square wheel ...

login or register to reply

jrmymllr

Platinum Boarder

2008/09/19 19:39

Re:HowTo : get malloc to work

I have a routine that sets up PWM and SPI to generate signals for an audio DAC for 9 common sample frequencies, and code that processes Shoutcast audio streams....that one is still kinda beta. Useful to the right person, maybe.

I thought DriverLib is fairly decent at what it is intended to do, but sometimes, like with other things, something isn't obvious. Like how to set/clear a digital output. It took a few days to figure out why the outputs I was trying to control didn't work.

login or register to reply

awneil

Gold Boarder

2008/09/22 17:50

Re:HowTo : get malloc to work

dereksoftstuff wrote:
I just don't know how we can get by without dynamic memory ...
For embedded stuff - especially small embedded stuff - avoiding dynamic allocation is more the norm than the exception!

The thing is: by the time you've done all the work to determine how big your heap needs to be, and what to do if an out-of-memory happens, you might just as well have spent that time working out a suitable static allocation scheme...

login or register to reply
<< Start < Prev 1 2 Next > End >>