If you want to see how much memory your app is using for code space and global variables then you can use the objdump utility provided with the IDE. If you go to the Arduino IDE's File -> Preferences dialog and turn on verbose output for compilation then the output window will display the location of the hex file it makes when it compiles your project, i.e. something like this:
- Code: Select all
C:\arduino-1.0.5\hardware\tools\avr\bin\avr-objcopy -O ihex -R .eeprom C:\Users\username\AppData\Local\Temp\build8635125389519731391.tmp\your_sketch.cpp.elf C:\Users\username\AppData\Local\Temp\build8635125389519731391.tmp\your_sketch.cpp.hex
The hex file is what gets uploaded to your Gambuino but the elf file contains information about the code that created it, and this info can be dump to a list file by running avr-objdump like this:
- Code: Select all
C:\arduino-1.0.5\hardware\tools\avr\bin\avr-objdump -h -S -j .data -j .text C:\Users\username\AppData\Local\Temp\build8635125389519731391.tmp\your_sketch.cpp.elf > dump.lst
This will dump a whole bunch of useful info in dump.lst including a disaasembly of all routines imported into your project. Of particular interest are the text and data sections listed at the top of the file which show how much memory is being used for global variables and code, respectively:
- Code: Select all
Sections:
Idx Name Size VMA LMA File off Algn
0 .data 0000040c 00800100 000056ac 00005740 2**0
CONTENTS, ALLOC, LOAD, DATA
1 .text 000056ac 00000000 00000000 00000094 2**1
CONTENTS, ALLOC, LOAD, READONLY, CODE
2 .bss 0000016b 0080050c 0080050c 00005b4c 2**0
ALLOC
This particular example is Rodot's AlienKiller demo, and we can see that there are 1036 (i.e. 0x40c) bytes used for global variables (half of which is the display buffer) and 22188 (i.e. 0x56ac) bytes of code. For comparison the Gamebuino has 2KB of usable RAM and 32KB for code (less 2KB being used by the boot loader). However it's also allocating 363 (0x16b) bytes for the .bss section which is globally allocated variables that aren't initialized to a particular value.
Looking at the lst file will tell you how much memory is allocated at the start-up, but you may also need to keep track of run-time usage. When a Gamebuino game starts up the global buffer is allocated at the very bottom of SRAM, the heap appears immediately after it and the stack is placed at the very top of RAM. Any calls to malloc() will cause the heap to grow "up", and any data allocated on the stack by calling functions etc will cause the stack to grow "down". If they meet up in the middle your program will either start acting weird or simply crash.
To help prevent this you can use code like this during development to keep track of the heap and stack pointers and if they get too close print an error message or something:
- Code: Select all
void mem_check()
{
void * heap_ptr = malloc(0);
if ((!heap_ptr) || ((int)heap_ptr + 100 >= SP))
{
Serial.println("Out of memory!");
while (1);
}
free(heap_ptr);
}
Here's an example to demonstrate this, the test() function calls itself recursively, increasing the stack a little each time, until finally we run out of memory:
- Code: Select all
void dump_mem()
{
void * heap_ptr = malloc(0);
if (heap_ptr)
free(heap_ptr);
Serial.print("heap: ");
Serial.print((int)heap_ptr);
Serial.print(", stack: ");
Serial.println(SP);
}
void test()
{
dump_mem();
mem_check();
test();
test(); // call test twice so that the compiler doesn't convert the first one to a tail call
}
void setup() {
Serial.begin(9600);
test();
}
void loop() {
}