Memory management: flash, eeprom, ram
published: 10 December 2019 / updated 11 December 2019
Memory organisation
There are three pools of memory in the microcontroller used on avr-based Arduino boards:
- Flash memory (program space), is where FlashForth and your words are stored.
- SRAM (static random access memory) is where FORTH creates and manipulates variables when it runs.
- EEPROM is memory space that programmers can use to store long-term information.
Flash memory and EEPROM memory are non-volatile (the information persists after the power is turned off). SRAM is volatile and will be lost when the power is cycled.
The ATmega328 chip found on the Uno has the following amounts of memory:
Flash | 32k bytes |
SRAM | 2k bytes |
EEPROM | 1k byte |
The ATmega2560 in the Mega2560 has larger memory space:
Flash | 256k bytes |
SRAM | 8k bytes |
EEPROM | 4k byte |
The word HERE
The word here
indicates the available memory address according to the memory context selected by
the words flash
, eeprom
or ram
.
We create a little word that will tell us at any time the state of the memory pointers:
: .memory ( ---)
cr ." flash: " flash here u.
cr ." eeprom: " eeprom here u.
cr ." ram: " ram here u.
cr ;
Using flash memory
flash
memory space is automatically used by the FORTH language and
the FORTH words that you define.
Except variables and other data explicitly stored elsewhere than in flash memory.
Words defined by :
are automatically stored in flash memory:
-tests marker -tests .memory \ flash: 12942 \ eeprom: 8716 \ ram: 1250 : test.loop 100 for r@ . next ; .memory \ flash: 12990 \ eeprom: 8716 \ ram: 1250
We see that the value delivered by here
for memory
flash changed from 12942 to 12990, an increase of
48 bytes.
For some types of data, you can force storage in flash memory:
-tests marker -tests .memory \ flash: 12942 \ eeprom: 8716 \ ram: 1250 flash create LIMIT 10 , .memory \ flash: 12958 \ eeprom: 8716 \ ram: 1250
The word LIMIT
marks a flash memory location whose contents can be retrieved:
LIMIT \ display 12956 @ \ display 10
If we reserve a memory zone whose contents are often changed, we must it is imperative to use another space than the flash memory.
All data stored in flash memory is retained after the shutdown ARDUINO card voltage.
Using ram memory
Ram memory should be used for variables whose value changes very often:
-tests marker -tests .memory \ flash: 12942 \ eeprom: 8716 \ ram: 1250 ram create BUFFER 256 allot .memory \ flash: 12958 \ eeprom: 8716 \ ram: 1506
The word BUFFER
is created in the flash memory, but the 256 bytes
buffer are reserved in ram memory:
BUFFER
\ display 1250
Running the word BUFFER
displays the address of the beginning of the buffer of
256 bytes reserved in RAM memory.
We will store in memory ram all the variables whose value will evolve in time.
All data stored in ram memory is lost after being put out ARDUINO card voltage.
Using eeprom memory
The eeprom memory is faster to access than the flash memory. Just like this memory flash is a non-volatile memory.
The eeprom memory is ideal for storing tables of data without cluttering the flash memory:
-tests marker -tests .memory \ flash: 12942 \ eeprom: 8716 \ ram: 1250 eeprom create SMILEYsprite ( --- addr) %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00100000 c, %01000010 c, %10000010 c, %10011000 c, %10011000 c, %10000010 c, %01000010 c, %00100000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, %00000000 c, ram .memory \ flash: 12964 \ eeprom: 8740 \ ram: 1250
We see that the pointer for the eeprom memory has changed from 8716 to 8740, an increase of 24 bytes.
Running SMILEYsprite
shows the address in memory
eeprom of the first byte of the placeholder where the description of the smiley sprite was stored.
To access the other bytes, simply increment this address the value corresponding to this memory position:
SMILEYsprite ( --- addr)
5 + c@
accesses the 5th octet after the address stacked by executing
SMILEYsprite
.
Memory selection in interpretation / compilation
At any time, while compiling a source code, you can change the memory context depending on the type of data to compile.
This selection should preferably be in interpretation. Example:
\ PORTB 37 constant PORTB \ Port B Data Register 36 constant DDRB \ Port B Data Direction Register \ 35 constant PINB \ Port B Input Pins - unused : defRELAY: ( PORTx mask ---| create flash , , \ compile PORT and min mask ram does> dup @ \ push pin mask swap 2+ @ \ push PORT ;--- mask port)
... is not a good solution!
Here, the selection eeprom
is done in the word defRELAY:
between
create
and does>
.
Here is the recommended solution:
: defRELAY: ( PORTx mask ---| create , , \ compile PORT and min mask does> dup @ \ push pin mask swap 2+ @ \ push PORT ; \ definition RELAYx flash PORTB %00000001 defRELAY: RELAY1 PORTB %00000010 defRELAY: RELAY2 PORTB %00000100 defRELAY: RELAY3 PORTB %00001000 defRELAY: RELAY4 ram--- mask port)
Here, the selection flash
occurs before the definition of
words RELAY1
to RELAY4
.