blog.hirnschall.net

Contents

Subscribe for New Projects

Introduction

Like on a PC, data stored in RAM is lost during a reboot or when power is lost. Similarly, data that is stored on flash memory (e.g. a USB-Stick) remains intact.

Thus, we will store data that cannot be lost during power loss in the esp8266's flash memory. This is similar to storing data in EEPROM on an Arduino. So, when we are talking about EEPROM, we are actually referring to EEPROM emulation using the esp's flash memory.

EEPROM Emulation

As the esp8266 does not come with real EEPROM we emulate it using the built-in flash memory.

Depending on the esp8266 model the amount of flash memory can vary from 512KiB to 4MiB.

While for example, the esp-01 comes with 512KiB or 1MiB flash memory, the esp-12f has 4MiB built-in. You can find the exact amount built-into the model you are using in the datasheet.

Note: The flash memory is also used to store the program code itself.

esp8266 EEPROM-Flash map
Figure 1: Simplified esp8266 flash map using EEPROM

EEPROM.begin

Unlike using an Arduino we have to start the EEPROM emulation (before reading and writing) with

EEPROM.begin(SIZE);

This allocates a SIZE-bytes large block of RAM and copies the data from flash. SIZE can be anywhere between a minimum of 4 and a maximum of 4096.

From now on we work with the copy in RAM like we would with a normal array.

Calculating Required EEPROM Size

We now have to decide how much flash memory we want to use for EEPROM emulation. The maximum amount of flash we can use is one sector (4096B).

If we want to store standard data types, we can use the cheatsheet below:

1 byte 2 bytes 4 bytes 8 bytes
bool short int double
char uint16_t long long long
byte float uint64_t
uint8_t uint32_t

However, the size of these data types can vary.

So, in general, the \(sizeof()\) function should be used to determine the amount of memory (in bytes) required to store a variable of a given type.

Example

If we want to store an int we need the EEPROM size to be at least \(sizeof(int)\) bytes.

If we want to store an int and a 20 character long char array (string), we need \(sizeof(int)+20\cdot sizeof(char)\) bytes.

Note: As we will later see it is also important to remember which variable is stored at which address in EEPROM. For the second example, we could store the int at \(addr_1=0\) and the string at \(addr_2=sizeof(int)\).

To simplify reading and writing to EEPROM, we can use structs as shown in the next section.

Read and Write to/from EEPROM

Now that we know the required EEPROM size, we can use the Arduino EEPROM library to read and write bytes to and from EEPROM (flash memory).

As an example, we will now store the wifi SSID and password in EEPROM:

struct { 
    char mySSID[MAX_STRING_LENGTH] = "";
    char myPW[MAX_STRING_LENGTH] = "";
} settings;

To start we will include the EEPROM library and use EEPROM.begin to allocate the required amount of memory.

#include <EEPROM.h>
[...]
EEPROM.begin(sizeof(settings));

Note: You can download the complete example below.

 

How to Read from EEPROM

EEPROM.get

The simplest way to read data from EEPROM is using the EEPROM.get() function.

unsigned int addr = 0;
EEPROM.get(addr, settings); //read data from array in ram and cast it into struct called settings

EEPROM.read

If necessary, we can also read individual bytes from EEPROM using EEPROM.read():

unsigned int addr = 0;
for(int i=0; i<MAX_STRING_LENGTH; ++i){
    settings.mySSID[i] = EEPROM.read(addr + i); //read individual byte from ram at (addr + i) and copy it to settings.mySSID[i]
}

addr += MAX_STRING_LENGTH;
for(int i=0; i<MAX_STRING_LENGTH; ++i){
    settings.myPW[i] = EEPROM.read(addr + i); //read individual byte from ram at (addr + i) and copy it to settings.myPW[i]
}

How to Write to EEPROM

As mentioned above, we are working with an array in RAM, not directly with the data stored in flash/EEPROM. We, therefore, have to use the EEPROM.commit() function to save changes in RAM to flash.

This will get clearer as you take a look at the two examples below:

EEPROM.put

The simplest way to store data in EEPROM is using the EEPROM.put() function:

unsigned int addr = 0;
EEPROM.put(addr, settings); //write data to array in ram 
EEPROM.commit();  //write data from ram to flash memory. Do nothing if there are no changes to EEPROM data in ram

EEPROM.write

We can write individual bytes using EEPROM.write():

unsigned int addr = 0;
for(int i=0; i<MAX_STRING_LENGTH; ++i){
    EEPROM.write(addr + i, settings.mySSID[i]); //write individual byte from settings.mySSID[i] to ram at (addr + i)
}

addr += MAX_STRING_LENGTH;
for(int i=0; i<MAX_STRING_LENGTH; ++i){
    EEPROM.write(addr + i, settings.myPW[i]); //write individual byte from settings.myPW[i] to ram at (addr + i)
}

EEPROM.commit();  //write data from ram to flash memory. Do nothing if there are no changes to EEPROM data in ram

EEPROM.commit

Write changes to the EEPROM data in RAM to flash memory.

If there are no changes in RAM, this function does nothing. If a single byte is changed in RAM, the complete EEPROM array in RAM is written to flash memory.

EEPROM.end

Calling EEPROM.end() is not required to read or write from/to EEPROM. All EEPROM.end is doing, is removing the cache array from RAM.

Erase EEPROM

If for some reason, you want to "erase" the EEPROM, you can overwrite it with e.g. zeros.

The code is very simple:

for (int i = 0; i < SIZE; EEPROM.write(i++,0));

where \(\text{SIZE}\) is the EEPROM size.

Get Notified of New Articles

Subscribe to get notified about new projects. Our Privacy Policy applies.

Downloads

Sebastian Hirnschall
Article by: Sebastian Hirnschall
Updated: 01.06.2021

References

Visited on 04.06.2021:
[1] https://github.com/esp8266/Arduino/tree/master/libraries/EEPROM

License

The content published on this page (with exceptions) is published under the CC Attribution-NonCommercial 3.0 Unported License. You are free to share on commercial blogs/websites as long as you link to this page and do not sell material found on blog.hirnschall.net/* or products with said material.