RAM is precious on a microcontroller, PROGMEM (program memory) not quite as much so. On the Arduino Uno and the Nano (using an Atmega328P) you have:
- 1 kB of EEPROM
- 2 kB of RAM
- 32 kB of PROGMEM
Clearly, there is a lot more program memory than RAM.
Variables are copied into RAM at program startup
The problem with constants in general (including string constants like "hello") is that the compiler generates code to copy them into RAM at program startup, because most C functions do not expect to find data in PROGMEM. (It has to generate different instructions to access PROGMEM).
Benchmark memory use
To test memory use, I'll start off with a sketch that simply returns how much memory is free, without doing anything else. Tested on IDE 1.0.6, Arduino Uno, on Ubuntu.
#include "memdebug.h"
void setup ()
{
Serial.begin (115200);
Serial.println ();
Serial.print (F("Free memory = "));
Serial.println (getFreeMemory ());
} // end of setup
void loop () { }
Output:
Free memory = 1702
Since we started with 2048 bytes of RAM, already we have used 2048 - 1702 = 346 bytes. These are used as follows:
34 bytes for the HardwareSerial instance (Serial)
64 bytes for the Serial transmit buffer
64 bytes for the Serial receive buffer
4 bytes for the Serial transmit buffer head and tail pointers
4 bytes for the Serial receive buffer head and tail pointers
9 bytes for keeping track of millis / micros
4 bytes for memory allocation (__malloc_heap_start, __malloc_margin)
128 bytes for the heap safety margin
6 bytes for a few nested function calls (main -> setup -> getFreeMemory)
16 bytes for the compiler vtable for HardwareSerial
4 bytes for variables __brkval and __flp (used in memdebug)
2 bytes pushed onto the stack in main (to save registers)
2 bytes pushed onto the stack in setup (to save registers)
4 bytes pushed onto the stack in getFreeMemory (to save registers)
1 byte because the stack pointer starts at 0x8FF rather than 0x900
(That's 346 bytes accounted for)
Tips
The stack starts at the highest possible address and grows downwards. Each function call would add 2 bytes to the stack (the return address) plus any local (auto) variables would be allocated there.
The heap safety margin is a buffer between the top of the heap and the bottom of the stack. Without it, if you did a "malloc" and got all available memory, there would be no memory left for function calls and local variables in functions.
The vtable is used by the compiler to generate late bindings for virtual functions used by classes.
The compiler generates code to push registers onto the stack when you call a function (the registers used inside that function) so that if the same register was used by the calling function, it would not be corrupted.
Printing constants
Let's print a constant by adding this line:
Serial.println ("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo");
Output is now:
Free memory = 1630
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo
So the free RAM has gone down by 72 bytes, which happens to be be how long that string is (allowing one byte for the 0x00 terminator at the end).
Why? Because the string was copied from PROGMEM, where it must be when the Arduino is turned off, into RAM.
The first thing we can do is use the F() macro, which cunningly expands out to print directly from PROGMEM, thus saving RAM. So we change the line above to read:
Serial.println (F("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo"));
Output:
Free memory = 1702
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmo
Back to 1702 bytes of free memory. So, lesson #1 is to use the F() macro as illustrated above whenever printing constants.
More information
I have more information on my page about RAM usage which discusses putting arrays of constants into PROGMEM as well as what I mention above.
Serial.begin(9600);
and notice the difference. Your 1798 bytes are certainly used by some library. And yes, there`s a tool avrdump , but not that easy to use.Serial.print(F("Your message here.\n"));
will store the message text in flash instead of RAM. That will work for any object that uses Print library. Though your concern wasn't (yet) running out of RAM, in a larger program, adding text messages can cause various kinds of out-of-RAM crashes.