2021-12-08 02:44 AM
Hello there,
For my project based on a STM32F401RB, I need to save in memory an array of data. I'm currently using the EEPROM emulation for STM32F4xx microcontrollers as described in AN3969.
It's working fine most of the time. I can read the EEPROM at each start of the program and write to it whenever I need.
But a problem occurs from time to time, without knowing exactly what is the cause : a new writing in the EEPROM is not saved. I noticed this during a new reading of the EEPROM which does not give me the last ones that I thought I had saved but oldest ones which are no longer relevant.
From this point on, the situation never changes. I am unable to save my latest data and can only read the latest data that has actually been saved to the EEPROM.
I have found that the write (EE_WriteVariable) and read (EE_ReadVariable) functions to the EEPROM always return "FLASH_COMPLETE" status when the problem appears, which is supposed to be the state of normal operation, at least it seems to me.
The only major difference from normal operation that I see in this problematic state is in the EE_Init () function which is executed each time the program is started. Below is what I do before calling EE_Init () at the start of my program.
FLASH_Status FlashStatus;
FLASH_Unlock(); /* Unlock the Flash Program Erase controller */
FlashStatus = EE_Init();
Inside EE_Init(), when the operation of the EEPROM is normal, I see that the condition "Page0 valid, Page1 erased" is the one that happens to be true. When I have the problem, the program is in the condition "Page0 valid, Page 1 valid", which is obviously an error state. Normally, the EE_Format () function should erase both Page0 and Page1 and set Page0 as valid page, but I guess it's not working because the situation is not evolving and each time the program restarts I see the same thing.
uint16_t EE_Init(void)
{
uint16_t PageStatus0 = 6, PageStatus1 = 6;
uint16_t VarIdx = 0;
uint16_t EepromStatus = 0, ReadStatus = 0;
int16_t x = -1;
uint16_t FlashStatus;
/* Get Page0 status */
PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
/* Get Page1 status */
PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
/* Check for invalid header states and repair if necessary */
switch (PageStatus0)
{
.....
.....
case VALID_PAGE:
if (PageStatus1 == VALID_PAGE) /* Invalid state -> format eeprom */
{
/* Erase both Page0 and Page1 and set Page0 as valid page */
FlashStatus = EE_Format();
/* If erase/program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */
{
/* Erase Page1 */
FlashStatus = FLASH_EraseSector(PAGE1_ID, VOLTAGE_RANGE);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
.....
}
The only thing that seems to work to reset the EEPROM is a general Erase Chip that I do with the little SEGGER J-Flash-Lite application. By reprogramming the STM32, the EEPROM will work normally again.
I don't know very well how this emulation of EEPROM for STM32F4 works, I just shared the observations that I made.
My question is about why the EE_Format () does not seem to work properly in my application. Any help will be greatly appreciated on a way out of this problematic state of the EEPROM.
Thank you.
2021-12-08 02:57 AM
To be more complete, these are my reading and writing functions of the EEPROM.
The variable table is an uint32_t array containing the data I want to save in EEPROM. I split each uint32_t into two uint16_t to write it in the EEPROM, and I reconstuit them during the reading process.
FLASH_Status WriteTable_EEprom(void){
int j = 0x5000;
uint16_t lowbytes;
uint16_t highbytes;
FLASH_Status FlashStatus;
for(int i=1; i<100; i++){
lowbytes = table[i];
highbytes = table[i] >> 16;
FlashStatus = EE_WriteVariable(j, lowbytes); // Saving table
j++;
FlashStatus = EE_WriteVariable(j, highbytes); // Saving table
j++;
}
return FlashStatus;
}
FLASH_Status ReadTable_EEprom(void){
FLASH_Status FlashStatus;
int j = 0x5000;
uint16_t bytes[2];
uint32_t var;
for(int i=1; i<100; i++){
FlashStatus = EE_ReadVariable(j, &bytes[0]); // Reading table
j++;
FlashStatus = EE_ReadVariable(j, &bytes[1]); // Reading table
j++;
uint32_t tmp = bytes[1];
var = (tmp << 16) & 0xFFFF0000;
}
return FlashStatus;
}
2021-12-08 05:45 AM
Most would be better managing a configuration structure/array directly via the FLASH API, perhaps journalling, and skipping the EEPROM Emulation non-sense.