1
\$\begingroup\$

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?

asked Mar 15, 2021 at 8:52
\$\endgroup\$
12
  • \$\begingroup\$ Can you check the return values of the functions? It might indicate where things go wrong. Have you modified EEPROM_START_ADDRESS such that if fits your particular MCU? How do you initialize VirtAddVarTab? \$\endgroup\$ Commented Mar 15, 2021 at 10:02
  • \$\begingroup\$ I defined these : uint16_t VirtAddVarTab[20]; uint16_t VarDataTab[20]; And this is the first page : #define ADDR_FLASH_PAGE_0 ((uint32_t)0x08000800) /* Base @ of Page 0, 1 Kbytes *///0x08000000 And I have two Iroms(IROM1 - IROM2) their addresses are (0x8000000(start address) - 0x400(size)) (0x8000800(start address) - 0xF800(size)) \$\endgroup\$ Commented Mar 15, 2021 at 10:22
  • 1
    \$\begingroup\$ I assume you have a debugger. If not, get yourself one. Single step through your code and the problem should become clear. There is some merit in stepping through all of your code to check for correct operation. \$\endgroup\$ Commented Mar 15, 2021 at 11:36
  • 2
    \$\begingroup\$ So there's your problem: The EEPROM library basically has the concept of reading and writing key/value pairs. VirtAddVarTab is supposed to contain the keys. Since you don't initialize it, all keys are 0. So whatever you read and write, it will always be to and from key 0. That's why you get 30 as a result. \$\endgroup\$ Commented Mar 15, 2021 at 11:37
  • 1
    \$\begingroup\$ @Codo yeah I suspected something like that. \$\endgroup\$ Commented Mar 15, 2021 at 11:47

1 Answer 1

2
\$\begingroup\$

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.

answered Mar 15, 2021 at 16:48
\$\endgroup\$
1
  • \$\begingroup\$ Thanks for all your useful information \$\endgroup\$ Commented Mar 25, 2021 at 17:12

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.