chipKIT® Development Platform

Inspired by Arduino™

Memory Allocation on MX250 devices

Created Thu, 03 Oct 2013 22:16:34 +0000 by caroper


caroper

Thu, 03 Oct 2013 22:16:34 +0000

How is the 32KB of SRAM on the MX250 allocated? Or to put it another way, what is the maximum memory available to the Sketch as opposed to Heap and Stack?

I tried to allocate 24KB to an array leaving 8KB free but I get a compiler error: address 0xa00080b0 of picaroon.cpp.elf section .stack' is not within region kseg1_data_mem'

If I reduce the array size to 16KB it clears the error but I would like to push it up to the Maximum allowed.

Is it possible to modify the Memory Allocation on a per script basis or would the Master linker Script have to be changed?

Cheers Chris


majenko

Thu, 03 Oct 2013 22:41:49 +0000

PROVIDE(_min_stack_size = 0x800) ;
PROVIDE(_min_heap_size = 0x800) ;

So, there is by default a minimum of 2K stack and 2K heap. Plus there is the other data use by the core, which depends on which chip / options your board uses (i.e., using USB serial adds about another 3K of RAM usage on top of everything else).

kseg1_data_mem       (w!x) : ORIGIN = 0xA0000000, LENGTH = 0x8000

Which equates to 32K of RAM as you already know.

So, compiling an empty sketch for the Fubarino Mini (USB serial) gives:

Program Size:
  Flash: 3% (4708 bytes out of 122880 bytes max)
    RAM: 4544 bytes
         (text: 4484, data: 224, bss: 4320)

If I add "Serial.begin(9600);" into startup:

Program Size:
  Flash: 9% (11784 bytes out of 122880 bytes max)
    RAM: 7924 bytes
         (text: 11548, data: 236, bss: 7688)

So, with USB serial in use on an MX250 you can expect a minimum of 7924 + 2048 + 2048 = 12010 bytes, which leaves 20758 bytes free.


caroper

Thu, 03 Oct 2013 23:15:20 +0000

Thanks majenko,

I had done my estimate on the basis of the Memory needed by my sketch but forgot that the Library calls would also require SRAM. I was way over optimistic on the memory available.

I can live with 16KB, it is a lot less than I thought I had, but a lot better than I could get on any other device in its class, so I can live with that, it nice round number and should ensure I still have SRAM available for any code additions.

Your breakdown of memory use was most enlightening, I learnt a lot, thanks again.

Cheers Chris


Jacob Christ

Wed, 23 Oct 2013 06:54:48 +0000

which leaves 20758 bytes free.

How do you get to the other 20K? Can we just bump up the stack value?

Say...

PROVIDE(_min_stack_size = 0x1000) ;

Jacob


majenko

Wed, 23 Oct 2013 10:29:58 +0000

The other 20K is available for static and global (eg bss) variables.

The heap and stack are minimum values - the stack and heap start with that amount of reserved space. If they need to grow they can - as long as there is space for them.

The typical memory map is (this is for a "standard" C program - the "text" is typically in flash and not part of this map for a uC):

When the stack and heap grow so big that they meet that's when you start getting problems. Allocate too much dynamic memory and you overwrite the stack. Recurse too deep into functions, or use too many local variables, and the stack can overwrite the heap.

You have protection against that kind of thing when you have a proper OS on there to deal with memory management, but you don't typically have that kind of thing on a uC. So things just go screwy.

The point of having a "minimum" amount of stack and heap is mainly for the compiler, so it knows if your static and global variables are likely to fit into the available memory or not. If you're not using any (or much) dynamic memory you could decrease the heap size and the compiler will be able to squeeze in more static and global variables.

Examples of the different types of variables:

char *myString = "This is my string"; // Initialized Data
unsigned long widget; // BSS

void function() { 
    static unsigned long timestamp = 49339284UL;  // Initialized Data
    int myVar; // Stack
    int myOtherVar = 23; // Stack
    char *scratchpad = malloc(80); // Heap
    String *myString = new String(); // Heap
}

The contents of the "Initialized Data" section are stored in Flash, and the "crt0" (or "C RunTime stage 0") copies the data from Flash to RAM when the program starts up. That is why the BSS is stored separate to the initialized data, so that a simple memcpy() can blast all the data across to RAM in one operation. BSS, being uninitialized, is not guaranteed to be any known state, and all variables should be initialized before use. A sane crt0 would first zero out all the RAM to ensure a clean, consistant starting point. Most uC compilers do that since the amount of memory is relatively tiny. Doing it on a PC though, where you may have large amounts of memory allocated to a program's BSS, could delay the startup of the program so is seldom done.

Local function variables that are initialized (int myOtherVar = 23) are treated the same as other local variables (stored on the stack) but the value is assigned when the function is entered.


Jacob Christ

Sat, 26 Oct 2013 09:44:33 +0000

Great explanation and mostly how I understood it. I think out little app is pushing the limits of the 32K of RAM in the MX795F512.

Thanks,

Jacob


majenko

Sat, 26 Oct 2013 09:46:03 +0000

Great explanation and mostly how I understood it. I think out little app is pushing the limits of the 32K of RAM in the MX795F512. Thanks, Jacob

But the '795 has 128KB of RAM... How else could it run RetroBSD so well? ;)


Jacob Christ

Sat, 26 Oct 2013 10:38:34 +0000

Hmmm, I don't see how we could be anywhere near 128K but I don't know how much space the ethernet lib is taking up. We are using the first Digilent lib.

When I inceased the min stack size some problems we were having went away, but after reading your explnation I am a bit worried that I just moved a problem some place I have yet to notice.

Jacob


majenko

Sat, 26 Oct 2013 10:43:34 +0000

Compile your sketch, then run "pic32-size" (it's in hardware somewhere) on the .elf file. That will tell you the text, data and BSS sizes.

Alternatively, compile it in UECIDE with verbose compilation turned on, and that will tell you the same thing ;)