Go Down

Topic: How much ram is being used? (Read 35316 times) previous topic - next topic

dnear1

I am trying to put together a few 18b20 temp sensors, an 8x2 LCD with the lcd4bit library and a DS1305 RTC.  my sketch size is about 10k of 16k..  I get to a certain point and something is corrupting the LCD stream..  I can't see how I am using up 1k of RAM..  is some of that lost to overhead?

How do I find how much RAM is in use?  What can I do to find out what is overlapping?

tehboii

I suspect that much AVR debuggers, like the Dragon, can give you the amount of ram your program is using, but this needs to be confirmed.

There are many reasons why data can get corrupted, like a buggy line writing too much data at some place... or many others ^_^
... could use some sleep

dnear1

The wierd part is if I comment out different lines of code, the problem goes away.

I didn't start having this problem until I got somewhere over 9k of sketch

tehboii

So probably your analysis is right... I'd considerer buying a Dragon or similar debugger to see what's happening, or just go study the libs I use to see how much ram they potentially consume...
... could use some sleep

bens

#4
Jun 16, 2008, 06:09 am Last Edit: Jun 16, 2008, 06:09 am by bens Reason: 1
You can write your own function to figure out how much free RAM you have on your mega168 at any point in your execution.  Please take a look at this thread for more information:

http://forum.pololu.com/viewtopic.php?f=10&t=989&view=unread#p4218

- Ben

mem

#5
Jun 16, 2008, 11:37 am Last Edit: Jun 16, 2008, 11:41 am by mem Reason: 1
Quote
You can write your own function to figure out how much free RAM you have on your mega168 at any point in your execution.  Please take a look at this thread for more information:

http://forum.pololu.com/viewtopic.php?f=10&t=989&view=unread#p4218

- Ben

Calculating memory availability is tricky. The test on that link  does not seem to give reliable results for the memory available to malloc, so if using code or libraries that call malloc then the memory test in the Arduino playground is better.  

If there are no calls to malloc then the Pololu code is better because that test consumes an insignificant amount of memory compared to the call to malloc just for the playground test.

I expect both tests suffer from inaccuracy if the memory pool gets fragmented

FYI, the Pololu code needed to be changed from
 [font=monospace]extern void __bss_end;[/font]
to
  [font=monospace]extern int __bss_end;[/font]  

to compile in my arduino environment

bens

I was probably unclear on the indended use of the function to which I linked.  The real point of this memory test function is to determine when your stack is about to overwrite your data, not to figure out how much space you have left for malloc (especially since malloc inherently provides this functionality itself by returning zero if the allocation fails).  Even if you've used malloc, if this memory test function returns a small number, you are in danger of having your stack overwrite your data (which can lead to data overwriting the stack), which in turn can lead to a corrupted program with unpredictable behavior and very frustrating bugs.  If you have a lot of nested functions or use a lot of RAM, you can call this test function often to make sure you are never having memory issues.

- Ben

dnear1

The Arduino is supposed to have 1k of RAM, right?
Usually, how much should be 'available' for Arduino sketch users?
I put it at the beginning of the program and after the first 4 voids that are called before my sketch seems to crash and it returns 271 each time.

dnear1

Well... possibly one of my problems was a missing () when calling a void.

dnear1

#9
Jun 17, 2008, 04:22 am Last Edit: Jun 17, 2008, 04:23 am by dnear1 Reason: 1
Then, I uncommented a bunch of serial.print("text blah"); statements and FreeMem reported -105 and the sketch crashed..

Does using "text" strings use up lots of ram?  Should I move them to progmem?

bens

The mega168 has 1k of RAM, and the Arduino environment takes up between 100 and 200 bytes of that for various globals and for the serial buffers (I don't off-hand know exactly how much).  Note that on the mega168, RAM is also used to hold the stack, so your global variables are at the beginning of RAM, the heap (the dynamically allocated variables created with malloc()) grows outwards from the end of the global variable space, and the stack grows from the end of RAM towards the heap/global space.

When you're writing a program, you need to make sure you leave plenty of RAM for the stack.  All non-static local variables are put on the stack, and nested functions will grow the stack.  If the stack ever overruns the data in the heap or the global space, you will run into problems, so one crucial thing to know about your program is the maximum amount of stack space it will use.

Local text strings of with N characters take up N+1 bytes of stack space.  Global text strings with N characters take up N+1 bytes of global space.  If you have many hundreds of characters in local text strings all in the same function or in the same branch of nested functions, you could very well cause your stack to overrun your global data.  If these text strings don't need to dynamically change, you should store them in and access them from program memory (i.e. in flash space).  They're in flash anyway, so having them occupy both flash and RAM is neither efficient nor helpful.

If you are getting a negative result from the function in the other thread I linked, you are almost certainly having memory issues.  Even if that function says you have a little bit of free space, you could still have memory issues in other parts of the program that grow the stack slightly farther.

- Ben

dnear1

So I moved those text strings to progmem and got them successfully in and only 'lost' a few bytes of RAM in the process.. but they no longer cause me to crash.
Are these functions considered nested?
if (xx==yy)
 {
   }
else if (xy==ya)
 {
   }
or only those that are like this?
if (xx==yy)
 {
  if (xy==ya)
     {
       }
 }

tehboii

#12
Jun 17, 2008, 01:50 pm Last Edit: Jun 17, 2008, 01:55 pm by tehboii Reason: 1
None of this is a nested function. This term refers only to the fact of encapsulating a function into another. Here's an example I stole from Wikipedia :

Code: [Select]

float E(float x)
{
   float F(float y)
   {
       return x + y;
   }
   return F(3);
}


This is basically used to limit the scope (and the encumbering of the namespace) of a very specific function, not supposed to be reused in other contexts. You don't often use such stuff.

It could be considered, imho, as a non-OO way of creating "private" functions.
... could use some sleep

bens

#13
Jun 17, 2008, 08:28 pm Last Edit: Jun 17, 2008, 08:33 pm by bens Reason: 1
By nested functions I mean neither what you nor tehboii are saying.  I mean simply something like:

void A(...)
{
 some stuff
 B(...);
}

void B(...)
{
 some stuff
 C(...);
}

void C(...)
{
 some stuff
}

void loop()
{
 some stuff
 A(...);
}

loop() calls A(), which calls B(), which calls C().  Every function called adds more data to the stack, and this data isn't removed from the stack until the function returns.  By the time you've reached C() you're now four levels deep.  If you try to figure out how much stack you're using by just looking at what C() requires, you could be severely underestimating your stack usage.  If you want to assess your program's stack usage, you need to look for locations that seem like they might require the most stack space and check your free memory there.  This will probably be inside one of your most deeply nested functions, or inside a function with a lot of local variables.

The same problem results from recursion.  Every level of recursion depth adds data to the stack, so recursing too deeply will cause problems.

- Ben

Daniel2

dnear1, do you mean that the LCD crashes, but the Arduino is OK? I had this problem recently, and it was due to sending too many strings to the LCD. A little delay(50) in between cured it.

D

Go Up