Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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.

like image 625
Matthew Murdoch Avatar asked Jun 06 '09 19:06

Matthew Murdoch


People also ask

What type of memory has the AVR architecture?

There are three types of memory in the AVR architecture: Program Memory. Data Memory. EEPROM.

What is AVR memory?

The AVR microcontroller's memory is divided into Program Memory and Data Memory. Program Memory (ROM) is used for permanent saving program being executed, while Data Memory (RAM) is used for temporarily storing and keeping intermediate results and variables.

Which part of memory in AVR microcontroller is used as scratch pad?

Data Memory (RAM) of 8051 Microcontroller In this 256B, the first 128B i.e., memory addresses from 00H to 7FH is divided in to Working Registers (organized as Register Banks), Bit – Addressable Area and General Purpose RAM (also known as Scratchpad area).


2 Answers

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.

like image 103
mMontu Avatar answered Sep 28 '22 09:09

mMontu


You say malloc is failing and returning NULL:

The obvious cause which you should look at first is that your heap is "full" - i.e, the memory you've asked to malloc cannot be allocated, because it's not available.

There are two scenarios to bear in mind:

a: You have a 16 K heap, you've already malloced 10 K and you try and malloc a further 10K. Your heap is simply too small.

b: More commonly, you have a 16 k Heap, you've been doing a bunch of malloc/free/realloc calls and your heap is less than 50% 'full': You call malloc for 1K and it FAILS - what's up? Answer - the heap free space is fragmented - there isn't a contigous 1K of free memory that can be returned. C Heap managers can not compact the heap when this happens, so you're generally in a bad way. There are techniques to avoid fragmentation, but it's difficult to know if this is really the problem. You'd need to add logging shims to malloc and free so that you can get an idea of what dynamic memory operations are being performed.

EDIT:

You say all mallocs happen at startup, so fragmentation isn't the issue.

In which case, it should be easy to replace the dynamic allocation with static.

old code example:

char *buffer;  void init() {   buffer = malloc(BUFFSIZE); } 

new code:

char buffer[BUFFSIZE]; 

Once you've done this everywhere, your LINKER should warn you if everything cannot fit into the memory available. Don't forget to reduce the heap size - but beware that some runtime io system functions may still use the heap, so you may not be able to remove it entirely.

like image 31
Roddy Avatar answered Sep 28 '22 08:09

Roddy