STM32F0 EEPROM-Leseproblem bei mehreren Variablen

Ich verwende die steeprom-Bibliothek, um meine Variablen zu speichern. Wenn ich eine einzelne Variable speichere, habe ich kein Problem. Ich kann es speichern, aktualisieren und nach dem Trennen der Stromversorgung kann ich diese Variable lesen. Jetzt möchte ich drei verschiedene Variablen auf drei verschiedenen Seiten speichern. Wenn ich sie lesen möchte, sehe ich in allen den neuesten Wert. Mit diesem Code speichere ich die Variablen:

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

Nachdem ich diesen Code programmiert habe, programmiere ich diesen:

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

Und ich sehe "30" im gesamten Speicher statt 10,20,30. Was ist mein Problem?

Seitenadressen:

#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

Und ich habe zwei IROM IROM1 Startadresse ist 0x8000000 und seine Größe ist 0x400 IROM2 Startadresse ist 0x8000800 und seine Größe ist 0xF800

Ich definiere diese am Anfang des Programms:

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

Ich habe es nicht initialisiert. Meinst du, ich setze zum Beispiel 0 an den Anfang und danach benutze ich sie?

Können Sie die Rückgabewerte der Funktionen überprüfen? Es könnte darauf hindeuten, wo etwas schief geht. Haben Sie EEPROM_START_ADDRESS so modifiziert, dass es zu Ihrer speziellen MCU passt? Wie initialisiert man VirtAddVarTab?
Ich habe diese definiert: uint16_t VirtAddVarTab[20]; uint16_t VarDataTab[20]; Und dies ist die erste Seite: #define ADDR_FLASH_PAGE_0 ((uint32_t)0x08000800) /* Base @ of Page 0, 1 Kbytes *///0x08000000 Und ich habe zwei Iroms (IROM1 - IROM2), ihre Adressen sind (0x8000000 (Startadresse) - 0x400(Größe)) (0x8000800(Startadresse) - 0xF800(Größe))
Können Sie diese Informationen bitte zu Ihrer Frage hinzufügen (anstatt sie in einen Kommentar zu schreiben). Initialisieren Sie VirtAddVarTab zusätzlich zur Deklaration? Wenn nicht, ist das die wahrscheinliche Ursache.
Ich habe sie in der Hauptfrage hinzugefügt
Was ist der Zweck des VirtAddVarTabArrays?
Ich nehme an, Sie haben einen Debugger. Wenn nicht, hol dir einen. Gehen Sie einmal durch Ihren Code und das Problem sollte klar werden. Es ist ein gewisser Vorteil, den gesamten Code schrittweise durchzugehen, um den korrekten Betrieb zu überprüfen.
Da ist also Ihr Problem: Die EEPROM-Bibliothek hat im Grunde das Konzept, Schlüssel/Wert-Paare zu lesen und zu schreiben. VirtAddVarTabsoll die Schlüssel enthalten. Da Sie es nicht initialisieren, sind alle Schlüssel 0. Was auch immer Sie lesen und schreiben, es wird immer zu und von Schlüssel 0 sein. Deshalb erhalten Sie 30 als Ergebnis.
@brhans: Die STM-Bibliothek muss VirtAddVarTaballe Schlüssel enthalten. Es ist erforderlich, die aktiven Einträge auf eine neue Flash-Seite zu übertragen, wenn die Seite voll ist.
@Codo ja, so etwas habe ich vermutet.
@Codo: Vielen Dank. Ich initialisiere VirtAddVarTab und es hat mein Problem gelöst
@Kartman: Ich benutze Debugger und es löst mein Problem. Ich kann nicht an Codierung ohne Debugger denken :) Es ist wirklich nützlich
@brhans: VirtAddVarTab ist ein Array zum Speichern von Adressen

Antworten (1)

Die Pseudo-EEPROM-Bibliothek von STM bietet eine Schnittstelle zum Lesen und Schreiben von Schlüssel/Wert-Paaren. Schlüssel sind uint16_tWerte. Das Array VirtAddVarTabsoll alle möglichen Schlüssel enthalten.

Ihr Code initialisiert nicht explizit VirtAddVarTab. Alle Schlüssel sind also 0. Daher schreibt und liest der Code immer auf Schlüssel 0.

Um es zu beheben, initialisieren Sie VirtAddVarTab, zB:

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

Während erforderlich ist, müssen Sie es nicht für und VirtAddVarTabverwenden . (Ich nehme an, Sie haben es aus dem seltsamen Beispielcode von STM kopiert.)EE_WriteVariable()EE_ReadVariable()

Ein verbesserter Ansatz wäre:

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

VirtAddVarTabwird benötigt, wenn eine Flash-Seite voll ist und die aktiven Schlüssel/Wert-Paare auf eine andere Flash-Seite übertragen werden müssen. Dies ist eine unglückliche Designentscheidung von STM, da sie zu einer gegenseitigen Abhängigkeit zwischen dem Projektcode und dem Bibliothekscode führt.

Der Ansatz von STM für das Pseudo-EEPROM ist robust: Es reduziert den Flash-Verschleiß und kann sich selbst dann erholen, wenn die Stromversorgung während des Schreibens ausgefallen ist. Allerdings ist die API komplexer als nötig, und die Dokumentation – obwohl sie die Implementierung im Detail abdeckt – beschreibt die Verwendung unzureichend.

Vielen Dank für all Ihre nützlichen Informationen