How can I visualise the memory (SRAM) usage of an AVR program?

Matthew Murdoch picture Matthew Murdoch · Jun 6, 2009 · Viewed 29k times · Source

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 mallocing happens on startup and all freeing 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.

Answer

mMontu picture mMontu · Aug 25, 2011

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.