EEPROM Rotation for the ESP8266 and ESP32
The 90/10 rule of design says that, “…users will spend 90 percent of their time using only 10 percent of your product.” My own corollary to it is that all features seem esoteric right up to the point when you use them. For the longest time I was convinced I’d never have a use for the Arduino EEPROM support. Right up to the point when I had to figure out exactly how it worked, and what the limitations were, for a project I was putting together for a client.
It turns out that EEPROM support is not something I’ve needed all that often since. But when I did need it, it has proved absolutely essential. So I was rather pleased when it turned out that the Arduino Core for ESP8266 supported Arduino EEPROM calls by using an SPI flash memory sector to emulate the AVR EEPROM.
However due to the nature of flash memory, there are a couple of problems with the default configuration. Firstly, you’re going to get heavy wear on the sector being used to emulate the EEPROM, and if the power goes off during a sector write you’re going to lose data.
“When you initialise the EEPROM object (calling
begin) it reads the contents of the sector into a memory buffer. Reading a writing is done over that in-memory buffer. Whenever you call
commitit write the contents back to the flash sector. Due to the nature of this flash memory (NOR) a full sector erase must be done prior to write any new data. If a power failure happens during this process the sector data is lost.
…also, writing data to a NOR memory can be done byte by byte but only to change a 1 to a 0. The only way to turn 0s to 1s is to perform a sector erase which turns all memory positions in that sector to 1. But sector erasing must be done in full sectors, thus wearing out the flash memory faster.”
Pérez’s library solves these problems by wrapping the stock EEPROM library and rotating the sector being used to store the EEPROM data when it is updated. Using a sector “pool” to store data spreads the wear over the flash, alleviating the heavy wear on the individual sector.
With every commit, the library will move to the next sector in the pool. The library also calculates a CRC for the sector in use, so if there is a power outage in the middle of a commit, and the CRC for the current sector doesn’t match, it will fall back to the latest known-good sector.
The library is meticulously documented by Pérez, and it’s really nice to see this level of maturity in the Arduino-stack for the ESP8266 and ESP32 chips starting to surface. Both the ESP8266 and ESP32 libraries are available on GitHub, and they’re licensed under the GNU LGPL. If you make use of the stock Arduino EEPROM support I’d recommend switching out to Pérez’s version with rotation support.