Arduino programming means that at some stage you come across PROGMEM and EEPROM. While I understand in principle what these are, I wanted to get a more practical view of the memory in the Atmel processor in my Arduino Uno.
The information is not hard to find (Google was my friend), but after a bit a reading I decided to summarise it in case this can help someone else.
There are 3 types of memory on AVR microntroller CPU
- Static Random Access Memory (SRAM or RAM) is where a program’s dynamic variables are stored.
- Flash Memory where the Arduino sketch is stored.
- Electrically Erasable Read-Only Memory (EEPROM) which can be used as a long term data store.
Flash memory and EEPROM memory are non-volatile (the information persists after power-off). SRAM is volatile – lost when the power is cycled.
The ATmega328 chip used in the Uno has 32kb of Flash (approx 500 bytes is used for the bootloader), 2kb SRAM and 1kb EEPROM. Each type of memory is used for specific purposes and has its own address space, and hence method for access.
SRAM is the smallest amount of memory but the fastest and most versatile. It is used by a running program to store all ‘automatic’ variables. SRAM is not retained between CPU reset cycles and is initialise by the program code.
New objects, dynamic memory and other programmatic memory requests/requirements are generally satisfied from the SRAM pool. This makes it a very scarce resource and very valuable. Programmers need to take this into consideration and think about how they can conserve RAM – constant data tables and string literals are best located in flash RAM.
SRAM memory is partitioned into a few distinct areas by the gcc compiler address allocation:
- At the beginning is an area called .data containing all static variables declared by the program.
- Next to it is the .bss area containing static variables that aren’t declared by the program.
- Following that is the Heap. This is where dynamically allocated memory is managed – allocating memory increases heap size, freeing memory decreases heap size. The heap may contain ‘holes’ of freed memory of memory is not allocated and freed in the same order (ie, the top of the heap is always the high tide mark). The heap grows upwards from the lowest address.
- The last area is the Stack, rooted at the highest address and growing downwards. The stack contains the return points subroutine jumps, function local local variables and system registers whilst servicing an interrupt.
An important point is that as the heap grows upwards and the stack grows downwards, they may meet in the middle and one will overwrite the other – there are no checks to prevent this happening! This is usually catastrophic and brings an immediate malfunction of the program. When a program runs out of SRAM, the program fails in unexpected ways; freezing, running strangely, continuously restart, etc.
Programmable flash memory (a type of EEPROM) is used to store the program code. It is erased and programmed as a single unit and is retained between power cycles. The technology used is similar to the more familiar USB flash drives (aka memory sticks).
Constants and strings that don’t change can be stored in flash memory instead of SRAM.
- For variables and data, use the PROGMEM keyword in front of the data type. Accessing the data requires the use of a special set of special functions prefixed with pgm.
- String constants can be stored in flash by using the F() macro. Library objects like Serial understand how to access these strings. Other objects may not and the strings need to be loaded into SRAM before being used by a program.
EEPROM is largely used for storing program-modifiable data that needs to remain available between power cycles. Readin EEPROM is much slower that accessing SRAM, and writing EEPROM is an order of magnitude slower.
EEPROM is used for setup and configuration parameters used by running code. In Arduino code, the EEPROM library can be used to access and change data in the EEPROM memory space.
An important consideration is that these parameters should be changed (written) very rarely. EEPROM has an unlimited life for reading but has a ‘limited‘ number of write cycles (around 100k) before the hardware at a specific memory address wears out and becomes unusable. While 100k may seem like a large number, it is easy to very rapidly exceed these limits if EEPROM changes are mistakenly located in a loop.