STM32F0 límite interno de lectura y escritura de EEPROM para una variable

Uso la biblioteca de emulación st eeprom para guardar mis variables. Quiero aumentar la variable cuando presiono el botón y guardarlo en eeprom. Funciona bien hasta 256 pero después de 256, el microcontrolador deja de funcionar. Parece que funciona 256 veces y puedo escribir 256 veces en una página, pero quiero leer y escribir más que eso. ¿Dónde está el problema? Esta es la biblioteca .h

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __EEPROM_H
#define __EEPROM_H

/* Includes ----------------------------------------------------------------- 
-*/ #include "stm32f0xx.h"

  /* Exported constants ----------------------------------------------------- 
 ---*/

 /* Base address of the Flash sectors */
 #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
 #define ADDR_FLASH_PAGE_11    ((uint32_t)0x08006000) /* Base @ of Page 11, 1 
 Kbytes *///0x08002C00
 #define ADDR_FLASH_PAGE_12    ((uint32_t)0x08006800) /* Base @ of Page 12, 1 
 Kbytes *///0x08003000
 #define ADDR_FLASH_PAGE_13    ((uint32_t)0x08007000) /* Base @ of Page 13, 1 
 Kbytes *///0x08003400
 #define ADDR_FLASH_PAGE_14    ((uint32_t)0x08007800) /* Base @ of Page 14, 1 
 Kbytes *///0x08003800
 #define ADDR_FLASH_PAGE_15    ((uint32_t)0x08008000) /* Base @ of Page 15, 1 
 Kbytes *///0x08003C00
 #define ADDR_FLASH_PAGE_16    ((uint32_t)0x08008800) /* Base @ of Page 16, 1 
 Kbytes *///0x08004000
 #define ADDR_FLASH_PAGE_17    ((uint32_t)0x08009000) /* Base @ of Page 17, 1 
 Kbytes *///0x08004400
 #define ADDR_FLASH_PAGE_18    ((uint32_t)0x08009800) /* Base @ of Page 18, 1 
 Kbytes *///0x08004800
 #define ADDR_FLASH_PAGE_19    ((uint32_t)0x0800A000) /* Base @ of Page 19, 1 
 Kbytes *///0x08004C00
 #define ADDR_FLASH_PAGE_20    ((uint32_t)0x0800A800) /* Base @ of Page 20, 1 
 Kbytes *///0x08005000
 #define ADDR_FLASH_PAGE_21    ((uint32_t)0x0800B000) /* Base @ of Page 21, 1 
 Kbytes *///0x08005400
 #define ADDR_FLASH_PAGE_22    ((uint32_t)0x0800B800) /* Base @ of Page 22, 1 

 /* Define the size of the sectors to be used */
 //#define PAGE_SIZE               (uint32_t)FLASH_PAGE_SIZE  /* Page size */
 #define PAGE_SIZE             ((uint32_t)0x0800)
 /* EEPROM start address in Flash */
 /* Change this if you need more EEPROM space and require less programming 
 space */
 #define EEPROM_START_ADDRESS  ((uint32_t)ADDR_FLASH_PAGE_30) /* EEPROM 
 emulation start address */

 /* Pages 0 and 1 base and end addresses */
  #define PAGE0_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
  #define PAGE0_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE 
  - 1)))

  #define PAGE1_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x400))
  #define PAGE1_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + PAGE_SIZE 
  - 1))

   /* Used Flash pages for EEPROM emulation */
   #define PAGE1                 ((uint16_t)1) /* Page nb between 
   PAGE0_BASE_ADDRESS & PAGE1_BASE_ADDRESS*/

     /* No valid page define */
   #define NO_VALID_PAGE         ((uint16_t)0x00AB)

    /* Page status definitions */
    #define ERASED                ((uint16_t)0xFFFF)     /* Page is empty */
    #define RECEIVE_DATA          ((uint16_t)0xEEEE)     /* Page is marked to 
    receive data */
    #define VALID_PAGE            ((uint16_t)0x0000)     /* Page containing 
    valid data */

    /* Valid pages in read and write defines */
    #define READ_FROM_VALID_PAGE  ((uint8_t)0x00)
    #define WRITE_IN_VALID_PAGE   ((uint8_t)0x01)

     /* Page full define */
     #define PAGE_FULL             ((uint8_t)0x80)

    /* Variables' number */
     #define NB_OF_VAR             ((uint8_t)0x04)

     /* Exported types ------------------------------------------------------------*/
     /* Exported macro ------------------------------------------------------------*/
     /* Exported functions ------------------------------------------------------- */
      uint16_t EE_Init(void);
      uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data);
      uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data);


      #endif /* __EEPROM_H */

Escribo dos funciones para leer y escribir memoria.

FLASH_Unlock();

EE_Init();

EE_ReadVariable( ++i , &alarm_counter );

FLASH_Lock();   

y

FLASH_Unlock(); 

EE_Init();


EE_WriteVariable( ++i , alarm_counter ); 

FLASH_Lock();   

Cambié mi código así:

uint16_t VirtAddVarTab[10] = {0,1,2,3,4,5,6,7,8,9};

 uint16_t VirtdataTab[10] = {0,0,0,0,0,0,0,0,0,0};

 uint16_t alarm_counter = 0; 
 
 ......

 FLASH_Unlock();

 EE_Init();

 EE_ReadVariable(VirtAddVarTab[0], &VirtdataTab[0]);

 alarm_counter = VirtdataTab[0] + 1;

 EE_WriteVariable( VirtAddVarTab[0] , alarm_counter ); 

 FLASH_Lock();  

¿Tengo que usar una dirección como 0x0100 o es correcto usarla así en mi código?

¿0x0100 es esta dirección en el archivo .h? #define ADDR_FLASH_PAGE_0 ((uint32_t)0x08000800)

Nunca he usado esa biblioteca, pero he leído sus documentos. Normalmente, debería cambiar a otra página y borrar la anterior. Puede haber breves retrasos debido al proceso de migración de la página, pero debería permitir escrituras continuas después de la migración. Quizás tengas errores en tu configuración. Por favor comparte tu código.
@Tagli: actualicé la publicación e inserté el código
En su nuevo código, no entiendo el propósito de VirtdataTab. ¿Para qué sirve? ¿Por qué una matriz?

Respuestas (3)

Parece que no entendiste la API de EEPROM (probablemente debido a su documentación deficiente). Su código modifica la clave en lugar del valor y una vez que la página está llena, no migrará los valores correctos a la nueva página, ya que solo funciona para un conjunto fijo de claves.

Suponiendo que alarm_counter son de hecho los valores que desea aumentar cuando se presiona el botón, su código debería verse así:

#define NB_OF_VAR 1

...

#define EE_KEY_ALARM_COUNTER 0x0100

uint16_t VirtAddVarTab[NB_OF_VAR] = { EE_KEY_ALARM_COUNTER };

uint16_t alarm_counter;

...

FLASH_Unlock();
EE_Init();
EE_ReadVariable(EE_KEY_ALARM_COUNTER, &alarm_counter);

alarm_counter++;

EE_WriteVariable(EE_KEY_ALARM_COUNTER, alarm_counter); 
FLASH_Lock();
Agrego mi código modificado a continuación. Pero puedo escribir 256 veces
En su nuevo código, no entiendo el propósito de VirtdataTab. ¿Para qué sirve? ¿Por qué una matriz? Tenga en cuenta que NB_OF_VAR y VirtAddVarTabno son solo nombres aleatorios. Deben declararse así para que funcione la biblioteca de emulación de EEPROM.

Quiero aumentar la variable cuando presiono el botón y guardarlo en eeprom.

Lo que está haciendo es incrementar la dirección (i), por lo que está escribiendo el valor de alarm_counter en toda una página de Flash.

¿Cómo puedo arreglarlo? ¿Cuántas variables puedo guardar en una página?
¿Dejar de incrementar i e incrementar alarm_counter en su lugar, tal vez?
EE_WriteVariable( i , alarm_counter++ ); ¿como esto?

Encontré el problema. Hay una definición en el archivo eeprom.h para el tamaño de página. Fue:

#define PAGE_SIZE ((uint32_t)0x0800)

Lo cambié a:

#define PAGE_SIZE             0x400U

Y todo funciona sin problema