chipKIT® Development Platform

Inspired by Arduino™

Free RAM

Created Mon, 15 Oct 2012 05:35:25 +0000 by Ian Billing


Ian Billing

Mon, 15 Oct 2012 05:35:25 +0000

Hello All

In transitioning from Arduino Mega to Max 32 I am trying to get the free RAM available, which was easy on the Mega by using the memoryFree.h library which I found on the Arduino forum. I cannot find a similar library or function for ChipKit mpide.

Please can someone assist with how to go about getting the amount of RAM used and the amount of free RAM remaining during a sketch?

Thanks

Ian


EmbeddedMan

Mon, 15 Oct 2012 12:18:30 +0000

I don't have the answer you're looking for - it would be really cool if we could come up with an equivalent function.

However, as I test, I just allocated a big, static, volatile variable in my sketch and filled it with 0xFFs. Then I keept bumping the size up until the sketch crashed. I got to 27KB on my UNO32 using the latest MPIDE. So that's about the amount of free RAM you have when you start. :-)

*Brian


majenko

Mon, 15 Oct 2012 15:39:15 +0000

That's pretty much the most common way - try allocating bigger and bigger chunks until malloc() fails, and that's the largest contiguous block of memory available. Note that this may be less than the real amount of free memory due to any holes there may be in the heap (unlikely if free() works right), and doesn't take into account any growing / shrinking of the stack in the process of running the test (local variables are put on the stack).

A more accurate way would be to use data from both the stack pointer (to find the "top" of free ram), the top of heap value (to find the bottom of free ram) and a total allocated heap value (to find the real size of the heap). The biggest contiguous block would be stack pointer - heap top, and the total free RAM would be stack pointer - (ram base + heap size).

How you'd get some of those values, though, I'm not too sure - I'd have to delve in to the memory management portions of the libs to work it out.


Ian Billing

Mon, 15 Oct 2012 16:00:58 +0000

That's great - thanks. I'll use that method until some kind soul ports the Arduino memoryFree() to mpide.

Appreciate the help. Ian


majenko

Mon, 15 Oct 2012 19:13:43 +0000

Here's some useful things for you:

Newlib has a mallinfo() function which returns a structure of information about allocated memory:

#include <malloc.h>

...

struct mallinfo m;

m = mallinfo();

You then have access to:

m.uordblks - the number of bytes actually allocated to variables. m.fordblks - the number of bytes free in the "arena" m.arena - the number of bytes set aside for dynamic variables - this will grow as needed - it is the total of uordblks+fordblks.

There are a few other variables too, but those are the most interesting.

RAM starts (on the '320 on my UNO32) at 0xA0000000, and there appears to be an offset of 0x00000d20 to the start of the heap (special variables / heap variables here?)

From that you can calculate that the top of the heap is 0xA0000d20 + m.uordblks (for actual allocated) or 0xA0000D20 + m.arena (for the top of arena).

Subtract that from the contents of the $sp register, and you have the amount of free RAM.

Note that by default there is a 2K limit on the amount of dynamically allocated variables imposed by settings in the mpide compiler configuration (one of the header files somewhere - not sure where, but I recall reading it somewhere on this forum).

Now - what's the best way of getting the contents of the $sp register into a C variable?


HunterR

Sun, 26 Apr 2015 15:53:40 +0000

Necroing for fun and profit :mrgreen: There's a function is SDFatUtils that needs this info."FreeRam()". I #defined a hollow function (return 0) but I want to do it the right way.

I just barely know enough to answer one of majenko's rhetorical questions:

  • How to get $sp stack pointer in a C variable
  • How to get the RAMstart variable (probably varies per board?)

Google-fu revealed the answer to #1 here: register int stackptr asm("sp"); http://www.microchip.com/forums/m651752.aspx -> http://www.microchip.com/forums/tm.aspx?m=572380

extern unsigned int _splim; 
     
     int CheckStackOverflow(void) 
     { 
         int overflowed; 
         register int stackptr asm("sp"); 
     
         if(stackptr <= (unsigned int) &_splim) 
            overflowed = 1; 
        else 
            overflowed = 0; 
     
         return overflowed; 
     }

However I do not know how to get the "RAM start" address from what you said. Can someone fill in the other half, or can complete the puzzle with what is provided?

Edit: I answered my own question... the below function apparently is meant for ARM but it works on PIC32.... I can't tell you why. Or if it is even accurate. Try it at your own risk....

extern "C" char* sbrk(int incr);
int SdFatUtil::FreeRam() {
  char top;
  return &top - reinterpret_cast<char*>(sbrk(0));
}

majenko

Sun, 26 Apr 2015 19:14:43 +0000

Well, "top" is a variable allocated on the stack - the last one allocated at that moment, so the address of it must be at the bottom of the stack. sbrk() allocates more space on the heap, returning the old top of heap. So sbrk(0) adds 0 more bytes to the heap and returns the top of the heap. Subtract one from the other and you get the space that's between them.