Using the internal EEPROM of STM32L

Most STM32 microcontrollers feature an internal EEPROM. It is useful for storing settings or calibration data. Regular flash (that stores code) can also be used, but the EEPROM can be updated byte-by-byte and is independent from regular flash. This may come handy during application updating, as whole flash can be simply erased without affecting the EEPROM.

I wrote a generic driver for keeping settings in the EEPROM based on the standard peripherals library for STM32L, that is easier to understand than the official demos from ST. It was tested on an STM32L151RC.

The interface

Everything starts with a definition of a structure that will hold all the parameters, flags and settings. The structure is verified using CRC32 checksum that is placed at the end. There is also a revision counter that is incremented every time to keep track how many times the EEPROM was written.

The revision counter can also be used to implement a highly reliable two-bank storage protocol that always keeps a single valid copy of all settings, to protect against power failures in the middle of a write operation.

Besides the structure definition the interface exposes two functions (one to load and another to store the settings) and a global pointer to the structure. This is one of the very few occasions where I use global variables. Otherwise I would have to implement setter/getter functions specific to every field. For small and simple configuration structure it is not worth the effort.

The implementation

The code has to be compiled with -std=gnu11 for _Static_assert to work. The assert statements check if the settings will fit into the EEPROM and if they will align on a 4-byte boundary. This is needed by the hardware CRC generator (its input is a 4-byte word and its output is also a 4-byte word). The size varies across STM32 families, so check your datasheet.

Settings are mirrored from EEPROM to RAM at startup, so that other modules can update their own parameters at any time and simply call settings_write(). If computed CRC is different than the stored CRC the settings are reset to defaults (here: zeros).

Saving works in a similar way, just the revision counter is incremented, the CRC is recalculated and then the whole setting struct is copied from RAM to the the EEPROM (one word at a time).