Table of Contents

EEPROM

Required knowledge: [HW] Kontrollermoodul

Theory

Atmel EEPROM memory chip

EEPROM (Electrically Eraseable Programmable Read Only Memory) is an electrically erasable memory device typically used for storing a small amount of data. The advantage of EEPROM is that the data remains even after power is lost. It is commonly used to keep various settings that are modified by the program. Otherwise EEPROM behaves like other memories, where bits are grouped into 8-bit bytes.

When using EEPROM, it is important to remember that the lifetime of memory bytes is about 100000 write cycles. Therefore you should write only the minimum necessary data to EEPROM.

Practice

AVR microcontrollers have a certain amount of EEPROM built in. The HomeLab III controller ATxmega128A1U has 2 KB of EEPROM. To work with EEPROM, it is recommended to use the library already built into AVR GCC. The library defines the main functions for EEPROM access:

Simple example code for EEPROM storage. It reads a byte from address 46 and a word from address 50. Writing uses the update function, which reads the EEPROM location before writing and does not overwrite when the value is already correct. This saves memory cells from wear, but writing takes a bit longer.

// AVR EEPROM byte and word save/read example
#include <avr/eeprom.h> 
 
// Main program
int main(void) { 
    uint8_t dataByte; 
    uint8_t dataWord; 
 
    // Write value 86 to EEPROM address 46
    eeprom_update_byte((uint8_t*)46, 86); 
    // Write value 860 to EEPROM address 50
    eeprom_update_word((uint16_t*)50, 860); 
 
    // Read byte from address 46 (should be 86)
    dataByte = eeprom_read_byte((uint8_t*)46); 
    // Read word from address 50 (should be 860)
    dataWord = eeprom_read_word((uint16_t*)50); 
}

To move more data at once, use block read/write. First define a data block in RAM:

// AVR EEPROM block save/read example
#include <avr/eeprom.h> 
 
// Main program
int main(void) { 
    uint8_t dataArray1[10] = "TestLause."; 
    uint8_t dataArray2[10];
 
    // First parameter is pointer to EEPROM block,
    // second parameter is pointer to RAM block
    // third parameter is dataArray length
    eeprom_update_block((const void*)&dataArray1, (void*)12, 10);
 
    // First parameter is pointer to RAM block,
    // second parameter is pointer to EEPROM block
    // third parameter is dataArray length
    eeprom_read_block((void*)&dataArray2, (const void*)12, 10);
}

It is not always practical to remember exact EEPROM addresses. For that there is a variable attribute called EEMEM. It frees the user from managing addresses and lets the compiler do it. Note that you still must use library functions to move data in EEPROM.

// AVR EEPROM EEMEM usage example
#include <avr/eeprom.h> 
 
uint8_t  EEMEM NonVolatileChar; 
uint16_t EEMEM NonVolatileInt; 
uint8_t  EEMEM NonVolatileString[10]; 
 
// Main program
int main(void) { 
    uint8_t  SRAMchar; 
    uint16_t SRAMint; 
    uint8_t  SRAMstring[10];    
 
    SRAMchar = eeprom_read_byte(&NonVolatileChar); 
    SRAMint  = eeprom_read_word(&NonVolatileInt); 
    eeprom_read_block((void*)&SRAMstring, (const void*)&NonVolatileString, 10); 
}