STM32F0 Problema de lectura de EEPROM con varias variables

Uso la biblioteca st eeprom para guardar mis variables. Cuando guardo una sola variable, no tengo ningún problema. Puedo guardarlo, actualizarlo y después de desconectar la alimentación, puedo leer esa variable. Ahora quiero guardar tres variables diferentes en tres páginas diferentes, cuando quiero leerlas, veo el último valor en todas ellas. Con este código guardo las 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();

Después de programar este código, programo este:

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();

Y veo "30" en todos los de la memoria en lugar de 10,20,30 ¿Cuál es mi problema?

direcciones de pagina:

#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

Y tengo dos IROM IROM1 la dirección de inicio es 0x8000000 y su tamaño es 0x400 IROM2 la dirección de inicio es 0x8000800 y su tamaño es 0xF800

Los defino al principio del programa:

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

No lo inicialicé. ¿Quiere decir que puse, por ejemplo, 0 al principio y luego los uso?

¿Puedes comprobar los valores de retorno de las funciones? Podría indicar dónde van mal las cosas. ¿Ha modificado EEPROM_START_ADDRESS de modo que se ajuste a su MCU en particular? ¿Cómo se inicializa VirtAddVarTab?
Definí estos: uint16_t VirtAddVarTab[20]; uint16_t VarDataTab[20]; Y esta es la primera página: #define ADDR_FLASH_PAGE_0 ((uint32_t)0x08000800) /* Base @ de la página 0, 1 Kbytes *///0x08000000 Y tengo dos Iroms (IROM1 - IROM2) sus direcciones son (0x8000000(dirección de inicio) - 0x400(tamaño)) (0x8000800(dirección de inicio) - 0xF800(tamaño))
¿Puede agregar esta información a su pregunta (en lugar de ponerla en un comentario)? ¿Inicializas VirtAddVarTab además de declararlo? Si no, esa es la causa probable.
Los agregué en la pregunta principal.
¿ Cuál es el propósito de la VirtAddVarTabmatriz?
Supongo que tienes un depurador. Si no, consíguete uno. Un solo paso a través de su código y el problema debería quedar claro. Hay algo de mérito en revisar todo su código para verificar que funcione correctamente.
Así que ahí está su problema: la biblioteca EEPROM básicamente tiene el concepto de lectura y escritura de pares clave/valor. VirtAddVarTabse supone que contiene las llaves. Como no lo inicializa, todas las claves son 0. Por lo tanto, cualquier cosa que lea y escriba, siempre será hacia y desde la clave 0. Es por eso que obtiene 30 como resultado.
@brhans: La biblioteca STM requiere VirtAddVarTabcontener todas las claves. Es necesario transferir las entradas activas a una nueva página flash cuando la página está llena.
@Codo, sí, sospechaba algo así.
@Codo: Muchas gracias. Inicialicé VirtAddVarTab y resolvió mi problema
@Kartman: uso el depurador y resuelve mi problema. No puedo pensar en codificar sin depurador :) es realmente útil
@brhans: VirtAddVarTab es una matriz para guardar direcciones

Respuestas (1)

La biblioteca pseudo EEPROM de STM ofrece una interfaz para leer y escribir pares clave/valor. Las claves son uint16_tvalores. Se supone que la matriz VirtAddVarTabcontiene todas las claves posibles.

Su código no se inicializa explícitamente VirtAddVarTab. Entonces, todas las claves son 0. Por lo tanto, el código siempre escribe y lee desde la clave 0.

Para solucionarlo, inicialice VirtAddVarTab, por ejemplo:

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

Si bien VirtAddVarTabes necesario, no necesita usarlo para EE_WriteVariable()y EE_ReadVariable(). (Supongo que lo ha copiado del extraño código de ejemplo de STM).

Un enfoque mejorado sería:

#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);

VirtAddVarTabse requiere cuando una página flash se ha llenado y los pares clave/valor activos deben transferirse a otra página flash. Es una decisión de diseño desafortunada por parte de STM, ya que genera una dependencia mutua entre el código del proyecto y el código de la biblioteca.

El enfoque de STM para la pseudo EEPROM es sólido: reduce el desgaste de la memoria flash y puede recuperarse incluso si falla la energía durante la escritura. Sin embargo, la API es más compleja de lo necesario y la documentación, aunque cubre la implementación en detalle, no describe suficientemente el uso.

Gracias por toda tu información útil.