Showing results for 
Search instead for 
Did you mean: 

Porting and using X-CUBE-EEPROM with any STM32

Community manager
Community manager


X-CUBE-EEPROM is an EEPROM emulation software package that works on a variety of STM32 MCUs. Upon downloading the package, there are premade examples that work with STMicroelectronics development kits. However, it is not obvious how you can use this package on any given STM32 with your custom hardware. The purpose of this article is to give a general guide on how to use this EEPROM emulation on any STM32 MCU.

1. Package Directory Structure

The package is broken up into three major folders: drivers, middlewares, and projects.


The drivers folder contains the HAL and LL drivers for the various devices. The middlewares folder contains that EEPROM emulation software. The projects folder contains premade projects that are ready to run on STMicroelectronics development boards.

The projects folder is useful for understanding how to interact with the EEPROM emulation API.  However, it does not provide insight into how to include the EEPROM emulation software into your particular project.

2. Porting 

Let us understand what the process of using the package in a custom application looks like. First, let us understand the directory structure of the EEPROM emulation middleware in the directory Middlewares\ST\EEPROM_Emul:

2 porting.png

The Core folder contains the hardware agnostic section of the middleware. This code is needed for any STM32 running the EEPROM emulation.

The porting folder contains subdirectories that contain the files necessary for working with a specific family of MCU:


Each one of these MCU specific folders contains two files, flash_interface.c/.h

4 flash interface.png

This defines how the package interacts with the internal flash memory, and thus is different different for each MCU family, unlike the source code found in the Core folder.

To port the middleware into your project, you firstly need to copy all files from the Core folder into your project that is.

  • Copy eeprom_emul.h, eeprom_emul_conf_template.h, and eeprom_emul_types.h into an include directory in your project.
  • Rename eeprom_emul_conf_template.h to eeprom_emul_conf.h
  • Copy eeprom_emul.c into a source code folder of your project and be sure it is included in the build.

Now, navigate to the relevant folder in the porting folder, depending on which MCU family you intend to use:

  • Copy flash_interface.h into your projects include directory
  • Copy flash_interface.c into your projects source folder and ensure it is included in the build.

It is also important that you modify the eeprom_emul_conf.h to fit the needs and constraints of your application and chosen MCU. Below you can find the relevant defines and their default values from the template configuration file:

#define START_PAGE_ADDRESS      0x08080000U
#define CYCLES_NUMBER               1U   
#define GUARD_PAGES_NUMBER      2U // must be multiple of 2
#define NB_OF_VARIABLES         1000U

The most important define to change is of course the START_PAGE_ADDRESS. This should be set to the beginning address of a flash page that is past the end of your firmware code.

The three remaining defines can be changed to fine tune the emulated EEPROM's endurance and allocated size. CYCLES_NUMBER and NB_OF_VARIABLES are the two most important in determining the allocated size and endurance of the emulated EEPROM. First, you enter the number of variables that you need to store in the NB_OF_VARIABLES. Then, you can modify the CYCLES_NUMBER to determine the endurance of your EEPROM in 10kcycles. For example, CYCLES_NUMBER = 1 means 10k cycle endurance, CYCLES_NUMBER = 2 means 20k cycles endurance etc. By increasing the CYCLES_NUMBER, the wear leveling algorithm used in the emulated EEPROM needs to increase the number of pages used to achieve the desired endurance. You can tune these two parameters that trade off endurance for saved flash memory space. 

The guard pages can be used to further increase endurance and reduce the frequency of erases needed after storing more variables than NB_OF_VARIABLES. If the chosen number of variables and endurance cycles is such that the last stored variable would lie close to a page boundary, it is recommended to make GUARD_PAGES_NUMBER = 2. This allow for extra writes to occur before incurring a significant delay in the cleanup process of the wear leveling algorithm. If your last variable does not lie close to a page boundary, set GUARD_PAGES_NUMBER = 0.

For more specific information on calculating exact memory usage, refer to AN4894 section 4.6 computing the required size of flash for EEPROM emulation (see link below.)

3. Using the emulated EEPROM in the application

With the device specific porting out of the way, we can get to the application level code, which looks the same for any STM32. Because the application level code looks the same, the examples provided in the project folder can be a useful way to understand how to interact with the middleware. The examples show detailed, full system level examples of integrating the EEPROM emulation. In this article, a demonstration of the most barebones use case is shown for the sake of easing understanding.

First, we unlock the flash memory interface and initialize the EEPROM:

  EE_Status status = EE_Init(EE_FORCED_ERASE);
  if (status != EE_OK)

Here we are using EE_FORCED_ERASE, which means upon initialization all used flash pages for the EEPROM will be erased. For systems where asynchronous system resets do not occur, this is the option that should be picked. In cases where asynchronous system resets occur, it is best to use the PVD peripheral to detect a falling voltage. Use capacitors or a battery to allow VDD to stay high long enough to finish a write. In this case only, it is OK to use EE_CONDITIONAL_ERASE instead, which prevents the emulation from needlessly erasing pages. If EE_CONDITIONAL_ERASE is used carelessly, you may incur data or page header corruptions. For more info, refer to AN4894.

Here is some basic, polling based sample code for reading and writing data:

uint16_t address = 0x0001;	// 16-bit virtual address between 0x0001 - 0xFFFE inclusive
  uint32_t data = 0x12345678; // Dummy Data
  status = EE_WriteVariable32bits(address, data);
  if (status != EE_OK)
  	if (status == EE_CLEANUP_REQUIRED)
  		if (EE_CleanUp() != EE_OK)

  uint32_t read_EE_variable;
  status = EE_ReadVariable32bits(0x1, &read_EE_variable);
  if (status != EE_OK)

The emulated EEPROM uses a virtual 16-bit address, but excludes the values 0x0000 and 0xFFFF. 

After any write, it is necessary to check if a cleanup is required. At some point, depending on the number of variables and endurance configured in eeprom_emul_conf.h, the emulation needs to clean up older pages of data and transfer the written data. Compared to typical, external EEPROM writes, writing to internal flash is quite fast, but when this cleanup is required, it can be time consuming to finish erasing.

Refer to the example found in the projects folder for more in depth demonstrations of the application level API.


Tim VanderMey
Associate II

Much needed information.  Thank you.

Version history
Last update:
‎2024-05-15 02:37 AM
Updated by: