Beginner's Intro => EEPROM access
(Diese Seite in Deutsch:
Address modes in AVRs
All AVRs have at least 64 bytes and up to 4,096 bytes EEPROM on board. EEPROM
is a memory type that keeps its content, even if the power supply of the
device is down and, after a short or long period of time, is powered up again.
- accessing SRAM locations,
- accessing portregister locations,
- accessing EEPROM locations,
- Accessing EEPROM
- The .ESEG directive
- EEPROM port registers
- EEPROM address
- Reading EEPROM
- Writing EEPROM
- accessing flash memory locations.
Un-programmed EEPROM space contains all 0xFF. The content of the EEPROM can be
written in two modes:
Reading from EEPROM requires a different procedure. Reading EEPROM content is
fast and requires only a few clock cycles.
If you use EEPROM you might want to set the initial EEPROM content on the
first controller start-up to certain values. This requires a .ESEG directive.
The following places different content into the EEPROM.
- When assembling source code, anything that was written in the .ESEG
section of the source code, is copied into a hex file named *.eep. The
file's content can be programmed into the EEPROM using a burner software.
- Within the actively executed program, EEPROM locations can be cleared
and re-written with different content. The procedure to clear and re-write
a byte requires some time, the end of the write process can initiate an
interrupt, if so enabled.
After assembling and programming the .eep file to the controller, its EEPROM
looks like shown in the picture.
.CSEG ; Code segment
; Instructions to be executed
.ORG 0x0000 ; The start address of the EEPROM content, default=0
.db 1,2,3,4,'A','a' ; Bytes to be written
.dw 1234, 4567 ; 16-bit Words to be written
.db "Text to be written to EEPROM",0x00 ; Text string
; End of the ESEG
.CSEG ; Code segment
; ... Further code for execution
Normally programming the flash memory not only erases the flash but erases the
EEPROM content as well. If you want to keep the EEPROM content during programming
the flash, set the respective preserve fuse of the device. That prevents from
erasing the flash. And: if that fuse is set, do not write the .eep file again
to the EEPROM. It will fail verification in most of the cases, because zeros
in the EEPROM can not be overwritten by ones (only erasing produces ones).
Writing or reading EEPROM uses three or four port registers:
Please note that the addresses given are subject to changes, so always use the def.inc
names instead of fixed addresses.
If your program shall read or write a single byte to/from the EEPROM, the assembler
code to set the address should look like this:
- An address: The lowest 8 bit of the address are to be written to the
port register EEARL. If the device has more than 256 bytes EEPROM, the
most significant 8 bits of the address are to be written to port register
- A data port: When writing to the EEPROM the 8 bit data to be written
are written to the data port register EEDR, before the write process
is started. When reading from EEPROM, the data at the addressed location
is appearing in port register EEDR.
- A control port: Write to or read access from the EEPROM is controlled
in the control register EECR by manipulating bits in this register.
When writing, the EEPE-Bit is one, when reading the EERE-bit is
Note that changing the EEPROM address ALWAYS should check first that no
programming is in progress. These are the first two words, before any
settings can be made.
.equ EepromAddress = 0x0010
; First wait until any write procedure has finished
sbic EECR,EEPE ; Check EEPE byte
rjmp WaitEep ; Wait further
; Set the address
.ifdef EEARH ; If more than 256 bytes EEPROM
; Read or write procedure
; Read or write procedure here
The .IFDEF directive adds the MSB setting only if the symbol EEARH is defined
in the def.inc file, which is the case for all AVRs that have more than 256
If you want to read or write multiple EEPROM locations in a row, you'll have
to set the LSB of the address in a loop, and, if the MSB changes, the MSB as
well. As the check whether programming is finished has to be made prior to
entering any address changes and as the MSB has to be set in any case (if the
MSB is physically available), we cannot limit the MSB output only to cases
where the MSB changes. Here, we output the MSB in all cases, which are only
two additional instructions.
Reading from the EEPROM is initiated by setting the EERE-bit in the
control register EECR. This halts the CPU for four clock cycles and
then writes the EEPROM content at that address to port register EEDR.
That looks like this:
.equ EepStartAddr = 0x0010
.equ EepEndAddr = 0x001F
; Set the address to the double register in R1:R0
; Output the LSB of the address
; Output the MSB of the address
; Add Read or write procedure here
inc R0 ; Increase LSB
In case we have to read more than one byte, we have to have more storage
space. If a second byte is to be read, we'll need a second register. If
more than three or four bytes are to be read, we use an SRAM space to
write the bytes there, e.g. with a pointer to that in X, we would add the
instruction ST X+,R16.
.equ EepAddrs = 0x0010
sbic EECR,EEPE ; Wait until write operation finished
; Four clock cycles pause
in R16,EEDR ; Read byte to R16
This here shows how we read the complete EEPROM content into an area in
SRAM by using ST X+,R16. Note that the whole process needed close
to one millisecond, because of delays during access reads, the check of
the programming bit, the double byte check of the end and the pointer
To avoid unplanned write access to the EEPROM, the procedure to start
a write process is a bit more complicated:
This starts the programming of the location after two clock cycles.
- First check if the last write is finished by testing the
EEPE bit in the control register EECR. Otherwise
- Then write the correct address to EEARL/EEARH.
- Then write the data byte to be written to EEDR.
- Then set the Master Programming Enable bit EEMPE in
EECR, together with the programming mode bits EEPM0
(Erase only) and EEPM1 (Write only), if so desired, and
the interrupt enable EEPIE-bit, if desired.
- Within the following four clock cycles (make sure that no interrupt
can occur during these four cycles) set the Programming Enable
bit EEPE in EECR.
The programming of the byte lasts 3.4 ms. When finished, the
EEPE-bit is cleared and, if so enabled, starts an interrupt
and jumps to the EEPROM-READY vector.
An example: This text in the SRAM has to be copied to EEPROM. We can
do that preferably with the interrupt feature of EEPROM write or in
a discrete loop that checks whether the EEPE-bit is clear and
writes the next character in SRAM to the EEPROM.
This is the state of the EEPROM after few characters have been written
and the 16th character is currently written. In the first half of the
write process the location is erased, which means that all bits at that
location are set to one. In the second half, the data is written. As this
lasts roughly 3.4 ms, the bar shows the progress. Both, the master
write/program enable bit EEMPE and the write/program enable bit
EEPE are active (high). When the write process is finished, both
bits are cleared by the AVR.
As the whole process lasts more than 140 ms, it is not recommended
to perform EEPROM writes in this lengthy way. This was just an example.
One note on interrupts: if the interrupt-enable-bit EEIE is set,
the EEPROM READY interrupt re-triggers every time the EEPE-bit
gets clear and if no other higher-ranking interrupt is active. Your
whole program can be blocked by this, if you do not write the next byte
to the EEPROM in your interrupt service routine. If no more bytes are
to be written, clear the interrupt enable bit.
Finally a warning: the number of write operations to EEPROM is limited
to several thousand events. One day has over 80,000 seconds, a year
has more than 31 million seconds, so if you want to reach the
guaranteed number of write accesses in one year, you can write the same
EEPROM location every 3,100 seconds or every 53 minutes.
So do not unnecessarily re-write the EEPROM and limit write accesses to
several minutes or hours and do it whenever really needed (e.g. because
the user just pressed a key or because the controller has re-started).
It is a good idea to hold a copy of the EEPROM content in registers or
SRAM and to only re-write the EEPROM if the difference is large enough.
An example for this: if you want to keep the current state of a stepper
motor in two, three of four bytes in an EEPROM location, do not write
the position changes to EEPROM whenever one single step has been made.
Write the status only after the complete move has finished. And write
only the really changed bytes to EEPROM. And hope that the LSB of the
EEPROM lasts long enough.
Read accesses from EEPROM are very fast, but less fast than SRAM read
accesses or accesses to registers. So better read the needed EEPROM
content once to a location in SRAM and access this instead of the
Write accesses to EEPROM require longer times, are limited over the
life-time of the device and should be limited to the cases where they
are useful and really needed. Depending from the rest of your program
and from its overall timing considerations: better use the EEPROM
READY interrupt to avoid timing conflicts.
To the top of this page