Most of the modern microcontrollers are based on the Molti dei moderni microcontrollori sono basati sull’Harvard architecture, so that they have separated memory for program code, usually stored on non volatile Flash, and for program datas, that is volatile SRAM. Because of the limited amount of the latter memory, a sketch can fill up all the SRAM even if the sketch is using only a limited portion of the Flash memory.
By the way, the user can use a couple of methods to know the amount of SRAM that his sketch is occupying, before or after the code has been uploaded into the MCU.
People the usually write code on PCs can see this thing a little bit strange: a common computer stores programs and datas into the same RAM. If I have a system with a total of 100 kB of memory and my program occupies only 10 kB of it, I know that 90 kB of RAM are available for datas. Moreover, if I write a program that is 90 kB, I know that I only have 10 kB for datas. This is the von Neumann’s architecture.
On Harvard architectures is different: if I have a microcontroller that only has 32 kB of Flash memory and 2 kB of SRAM memory (like the Atmega328 of the Arduino UNO board), I can occupy 1 kB of Flash and fill up all the SRAM memory just by declaring a single array.
The memory saturation results in strange behaviour of the microcontroller because the CPU start retrieving the datas from the SRAM memory randomly: i.e., casual characters can be shown on an LCD display or on the serial monitor, or unexpected freezes can occur. The memory saturation is also a problem that the user cannot correctly diagnosticate: usually, he thinks that there’s something wrong in his circuit or in another part of the sketch.
Luckily, there are some methods to check the memory usage to understand if the symptons that occur can be related to a memory saturation. The first one is a non-invasive method and it can check the memory usage statically. It’s based on a software provided by the AVR toolchain, avr-size. This tool returns the memory occupation of the sketch before it is uploaded into the MCU. It is a non-invasive method as you don’t have to modify your program but it only analizes the memory consumption statically: it means that it cannot recognize if a dinamic array will fill up all the SRAM.
The second method is based on the use of a third-party library named MemoryFree that can returns the memory consuption at runtime. This is an invasive method because you have to modify your sketch; it also requires a serial communication between the microcontroller and the computer to receive the values computed by MemoryFree.
The third method uses a small function that simple does the difference between the starting address of the HEAP and the starting address of the STACK, returning the number of bytes of SRAM that are still available. The STACK and the HEAP are 2 structures created and constantly modified during the running of the program (we will analize them in a future article).
Altough I personally prefer the use of avr-size because I don’t have to modify my sketch nor I don’t have to set a serial line between MCU and PC (the latter could be a problem with MCUs that don’t have HW serial, i.e. the Attiny85, the Attiny84 or similar: with these MCUs you should use a software serial, with another library to load into your sketch), I present all the methods, leaving at the reader the choice between them.
Use of “avr-size”
This tool is part of the AVR toolchain. With Arduino 1.0.x, you find it into the folder /arduino-1.0.x/hardware/tools/avr/bin: its “avr-size.exe” on Windows systems, only “avr-size” on Linux boxes. It works on .elf files that are created during compiling process of the sketch. The Arduino IDE uses a temp folder in which it stores all the files that it creates during its activity. To know where the current temp folder is located, just open the menu in “File/Preferences” and then check the option “Show verbose output during: compilation”. Now, compile your sketch (without uploading it) and look at the terminal: it will show all the messages of the compilator. At the end, look into the terminal for a message similar at this one (on Linux):
/tmp/build3857425205743446753.tmp/name_of_your_sketch.cpp.hex
or at this one (on Windows):
C:\DOCUME~1\User\IMPOST~1\Temp\build3857425205743446753.tmp\name_of_your_sketch.cpp.hex
Copy the whole line except the “.hex” part. Now open a terminal (on Linux) or the command line (on Windows) and move to the folder that contains avr-size (see above). Now digit “./avr-size” (on Linux) or “avr-size.exe” (on Windows), then a space, then paste the line that you had copied before, then add the “.elf” extension after the name of the file, then another space, than insert “-C” (C in upper case). Finally the line must be look similar at this one:
./avr-size /tmp/build3857425205743446753.tmp/name_of_your_sketch.cpp.elf -C
or
avr-size.exe C:\DOCUME~1\User\IMPOST~1\Temp\build3857425205743446753.tmp\name_of_your_sketch.cpp.elf -C
The tool will return the memory consumption in a readible form, dividing the Flash occupation (“program”) from the RAM occupation (“data”) letting you understand if your sketch uses too much resources. Let’s try to compile the ArduinoISP sketch with Arduino IDE 1.0.1. Here is what I get on my Linux box:
AVR Memory Usage
----------------
Device: Unknown
Program: 5438 bytes (16.6% Full)
(.text + .data + .bootloader)
Data: 482 bytes (23.5% Full)
(.data + .bss + .noinit)
If you want to fix the “Device: Unknown” message, just add the type of microcontroller using the paramether “–mcu”. For example, for an Atmega328P, just digit “–mcu=Atmega328p”.
The library “memoryFree”
To use this method you need a way to visualize the datas computed by the library: the easiest way is to use the serial communication, sending them to the PC.
First of all, download the package that is attached at the bottom of this article: it contains the library and an example sketch. Decompress the package and copy its content, with the IDE closed, inside the folder /libraries. Start again the IDE and load up the sketch that you want to check. At the beginning of the sketch, insert the following code (to include the library):
#include "MemoryFree.h"
Now, put somewhere in your sketch the following line:
Serial.println(freeMemory());
It just sends to the PC the value of the free SRAM, so that you can know the memory usage in real time. Keep in mind that this method alters the SRAM usage because both the library and the serial communication increase the memory used by the sketch. This method also needs a way to communicate at the user the value of the available memory.
The function “freeRam”
The function is called “freeRam” and it was first presented on JeeLabs.org:
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
Just copy it and insert it anywhere in your sketch and call it: it will return an “int” value rapresenting the number of bytes still available in the SRAM – this value can be printed on the serial monitor or visualized on an LCD display.