EEPROM Emulation using Flash on STM32F4xx

Since most STM32Fxxx doesn’t feature internal EEPROM. Hence, this guide we shall use the internal flash to emulate EEPROM.

In this guide, we shall cover the following:

  • What is EEPROM.
  • Develop the driver.
  • Code.
  • Results.

1. What is EEPROM:

EEPROMs (electrically erasable programmable read-only memories) are used for non- volatile storage of updatable application data, or to retain small amounts of data in the event of power failure in complex systems. To reduce cost, an external EEPROM can be replaced by on-chip Flash memory, provided that a specific software algorithm is used.

Difference between emulated EEPROM and real EEPROM:

As you can see, the endurance is way less compared to EEPROM. Hence, the usage of emulated EEPROM should be considered as last resort and dealt with it carefully.

2. Developing the Driver:

Since we need to read and write from/to flash, the basic driver to read/flash from/to flash can be found here:

  • Read from flash (here).
  • Write to flash (here).

We start by creating new header and source file with name of eeprom.h and eeprom.c respectively.

Within the eeprom.h, set the guard as following:

#ifndef EEPROM_H_
#define EEPROM_H_



#endif /* EEPROM_H_ */

Within the guard, declare the following enum:

typedef enum
{
	EEPROM_OK=0,
	EEPROM_ERROR=1
}EEPROMTypedefStatus;

This for error handling in your firmware.

The initializing function:

void eeprom_init(uint32_t st_add, uint16_t size);

Get the size function:

uint32_t get_eeprom_size();

Read and write from/to EEPROM:

EEPROMTypedefStatus eeprom_read(uint16_t add, uint32_t *pData );

EEPROMTypedefStatus eeprom_write(uint16_t add, uint32_t pData);

Hence, the entire eeprom.h as following:

#ifndef EEPROM_H_
#define EEPROM_H_


typedef enum
{
	EEPROM_OK=0,
	EEPROM_ERROR=1
}EEPROMTypedefStatus;

void eeprom_init(uint32_t st_add, uint16_t size);

uint32_t get_eeprom_size();

EEPROMTypedefStatus eeprom_read(uint16_t add, uint32_t *pData );

EEPROMTypedefStatus eeprom_write(uint16_t add, uint32_t pData);


#endif /* EEPROM_H_ */

Now, within the source file, include the header file for eeprom and flash as following:

#include "flash.h"
#include "eeprom.h"

Some required variables:

uint16_t e_size;

uint32_t start_address, end_add;

The initializing function:

void eeprom_init(uint32_t st_add, uint16_t size)
{
	/*Evaluate the end address*/
	end_add=st_add+(uint32_t)((size*4));
	
	/*Get the starting address*/
	start_address=st_add;
	
	/*Store the size*/
	e_size=size;

}

The function takes two argument:

  • Starting address within flash region.
  • Number of EEPROM block (multiple of 4byte).

Within the function:

Calculate the end address by adding the base address to the number of blocks by 4 (since the memory increment of Flash is 4byte).

Store the passed starting address to start_addres variable.

Store the passed size to e_size.

Get the size function:

uint32_t get_eeprom_size()
{
/*Return the size of EEPROM*/	
  return e_size;
}

Simply, it will return the e_size.

Read EEPROM function:


EEPROMTypedefStatus eeprom_read(uint16_t add, uint32_t *pData )
{
	/*Get the EEPROM address*/
	uint32_t address= ((add)*4)+start_address;
	/*Check if the address within the limit*/
	if(address > end_add) {return EEPROM_ERROR;}
	
	/*Read the content of the address*/
	else
	{
		flash_read32(address,pData,1);
	}
	
	/*Return OK*/
	return EEPROM_OK;
}

The function takes two argument:

  • EEPROM block address.
  • Pointer to variable to store the read data from flash.

Within the function:

First check if the address within the valid range, if it is not, return error.

Else, read the specific memory location in flash.

Return ok for success.

Write EEPROM function:

EEPROMTypedefStatus eeprom_write(uint16_t add, uint32_t pData)
{
	/*Variable to hold the read data*/
	uint32_t data;

	/*Get the EEPROM address*/
	uint32_t address= ((add)*4)+start_address;

	/*Check if the address within the limit*/
	if(address > end_add) {return EEPROM_ERROR;}



	/*Check if data is the same*/
	eeprom_read(add,&data);

	/*Same data, don't write new data*/
	if(data==pData)
	{
		return EEPROM_OK;
	}
	/*If it is not the same data, write the new data*/

	flash_unlock();
	flash_write32(address,&pData,1);
	flash_lock();

	/*Return ok*/
	return EEPROM_OK;
}

The function takes two arguments:

  • Address of eeprom block.
  • Data to be written.

Within the function:

Declare a variable to store the read data.

Get the address.

Check if the address is valid.

Read the address.

If the data is the same one as the one to be store, return from function.

Else, write the new data.

Return ok after writing the new data.

In main.c:

#include "stdio.h"
#include "delay.h"
#include "uart.h"
#include "eeprom.h"


uint32_t eeprom_data;

int main(void)
{
	uart2_tx_init(115200,16000000);

	systick_init_ms(16000000);

	eeprom_init(0x08010000, 10);

	printf("EEPROM size = %d\r\n",get_eeprom_size());
	eeprom_write(0, 0x11223344);
	eeprom_write(1, 0xbabababa);
	eeprom_write(2, 0xdeadbeef);
	eeprom_write(3, 0xFAFAFAFA);

	eeprom_read(0,&eeprom_data);
	printf("EEPROM data at address 0 is 0x%x\r\n",eeprom_data);


	eeprom_read(1,&eeprom_data);
	printf("EEPROM data at address 1 is 0x%x\r\n",eeprom_data);


	eeprom_read(2,&eeprom_data);
	printf("EEPROM data at address 2 is 0x%x\r\n",eeprom_data);


	eeprom_read(3,&eeprom_data);
	printf("EEPROM data at address 3 is 0x%x\r\n",eeprom_data);



	while(1)
	{



	}
}

3. Code:

You may download the entire project from here:

4. Results:

Successfully wrote and read the data.

Happy coding 🙂

Add Comment

Your email address will not be published. Required fields are marked *