I have encountered a problem in a C program running on an AVR microcontroller (ATMega328P). I believe it is due to a stack/heap collision but I'd like to be able to confirm this.
Is there any way I can visualise SRAM usage by the stack and the heap?
Note: the program is compiled with avr-gcc and uses avr-libc.
Update: The actual problem I am having is that the malloc implementation is failing (returning NULL
). All malloc
ing happens on startup and all free
ing happens at the end of the application (which in practice is never since the main part of the application is in an infinite loop). So I'm sure fragmentation is not the issue.
You can check RAM static usage using avr-size
utility, as decribed in
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=62968,
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=82536,
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=95638,
and http://letsmakerobots.com/node/27115
avr-size -C -x Filename.elf
(avr-size documentation: http://ccrma.stanford.edu/planetccrma/man/man1/avr-size.1.html )
Follows an example of how to set this on an IDE: On Code::Blocks, Project -> Build options -> Pre/post build steps -> Post-build steps, include:
avr-size -C $(TARGET_OUTPUT_FILE)
or
avr-size -C --mcu=atmega328p $(TARGET_OUTPUT_FILE)
Example output at the end of build:
AVR Memory Usage
----------------
Device: atmega16
Program: 7376 bytes (45.0% Full)
(.text + .data + .bootloader)
Data: 81 bytes (7.9% Full)
(.data + .bss + .noinit)
EEPROM: 63 bytes (12.3% Full)
(.eeprom)
Data is your SRAM usage, and it is only the amount that the compiler knows at compile time. You also need room for things created at runtime (particularly stack usage).
To check stack usage (dynamic RAM), from http://jeelabs.org/2011/05/22/atmega-memory-use/
Here’s a small utility function which determines how much RAM is currently unused:
int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
And here’s a sketch using that code:
void setup () {
Serial.begin(57600);
Serial.println("\n[memCheck]");
Serial.println(freeRam());
}
The freeRam() function returns how many bytes exists between the end of the heap and the last allocated memory on the stack, so it is effectively how much the stack/heap can grow before they collide.
You could check the return of this function around code you suspect may be causing stack/heap collision.