Electronic – STM32F0 EEPROM read problem with several variables

eepromstm32

I use st eeprom library to save my variables. When I save a single variable, I do not have any problem. I can save it, refresh it and after disconnecting the power, I can read that variable. Now I want to save three different variables in three different pages, when I want to read them, I see the latest value in all of them. With this code I save the variables:

HAL_FLASH_Unlock();
EE_Init();
EE_WriteVariable(VirtAddVarTab[0], 10);
EE_WriteVariable(VirtAddVarTab[1], 20);
EE_WriteVariable(VirtAddVarTab[2], 30);
HAL_Delay(10);
EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
EE_ReadVariable(VirtAddVarTab[2], &VarDataTab[2]);
HAL_FLASH_Lock();

After programing this code, I program this one:

HAL_FLASH_Unlock();
EE_Init();
EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
EE_ReadVariable(VirtAddVarTab[2], &VarDataTab[2]);
HAL_FLASH_Lock();

And I see "30" in all of the memory them instead of 10,20,30
What is my problem?

page addresses :

#define ADDR_FLASH_PAGE_0     ((uint32_t)0x08000800) /* Base @ of Page 0, 1 Kbytes *///0x08000000
#define ADDR_FLASH_PAGE_1     ((uint32_t)0x08001000) /* Base @ of Page 1, 1 Kbytes *///0x08000400
#define ADDR_FLASH_PAGE_2     ((uint32_t)0x08001800) /* Base @ of Page 2, 1 Kbytes *///0x08000800
#define ADDR_FLASH_PAGE_3     ((uint32_t)0x08002000) /* Base @ of Page 3, 1 Kbytes *///0x08000C00
#define ADDR_FLASH_PAGE_4     ((uint32_t)0x08002800) /* Base @ of Page 4, 1 Kbytes *///0x08001000
#define ADDR_FLASH_PAGE_5     ((uint32_t)0x08003000) /* Base @ of Page 5, 1 Kbytes *///0x08001400
#define ADDR_FLASH_PAGE_6     ((uint32_t)0x08003800) /* Base @ of Page 6, 1 Kbytes *///0x08001800
#define ADDR_FLASH_PAGE_7     ((uint32_t)0x08004000) /* Base @ of Page 7, 1 Kbytes *///0x08001C00
#define ADDR_FLASH_PAGE_8     ((uint32_t)0x08004800) /* Base @ of Page 8, 1 Kbytes *///0x08002000
#define ADDR_FLASH_PAGE_9     ((uint32_t)0x08005000) /* Base @ of Page 9, 1 Kbytes *///0x08002400
#define ADDR_FLASH_PAGE_10    ((uint32_t)0x08005800) /* Base @ of Page 10, 1 Kbytes *///0x08002800

And I have two IROM
IROM1 start address is 0x8000000 and its size is 0x400
IROM2 start address is 0x8000800 and its size is 0xF800

I define these in the beginning of the program :

uint16_t VirtAddVarTab[20];
uint16_t VarDataTab[20];

I did not initialize it. Do you mean I put for example 0 in the start and after that I use them?

Best Answer

STM's pseudo EEPROM library offers an interface to read and write key/value pairs. Keys are uint16_t values. The array VirtAddVarTab is supposed to contain all possible keys.

Your code does not explicitly initialize VirtAddVarTab. So all keys are 0. Therefore, the code always writes to and reads from key 0.

To fix it, initialize VirtAddVarTab, e.g.:

uint16_t VirtAddVarTab[NB_OF_VAR] = { 0x100, 0x0102, 0x0200 };

While VirtAddVarTab is needed, you don't need to use it for EE_WriteVariable() and EE_ReadVariable(). (I assume you have copied it from STM's strange example code.)

An improved approach would be:

#define EE_KEY_COLOR       0x0100
#define EE_KEY_BRIGHTNESS  0x0102
#define EE_KEY_MODE        0x0200

uint16_t VirtAddVarTab[NB_OF_VAR] = { EE_KEY_COLOR, EE_KEY_BRIGHTNESS, EE_KEY_MODE };

uint16_t color;
uint16_t brightness;
uint16_t mode;

...

EE_ReadVariable(EE_KEY_COLOR, &color);
EE_ReadVariable(EE_KEY_BRIGHTNESS, &brightness);
EE_ReadVariable(EE_KEY_MODE , &mode);

VirtAddVarTab is required when a flash page has filled up and the active key/value pairs have to be transferred to another flash page. It's an unfortunate design decision by STM as it results in a mutual dependency between the project code and the library code.

STM's approach for the pseudo EEPROM is robust: it reduces flash wear and can recover even if power failed during write. However, the API is more complex than necessary, and the documentation – while covering the implementation in detail – insufficiently describes the usage.