cancel
Showing results for 
Search instead for 
Did you mean: 

EEPROM stuck with STM32F4: impossible to save the last data and reading only irrelevant old data

CrimsonKing
Associate

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.

2 REPLIES 2
CrimsonKing
Associate

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;
}

Most would be better managing a configuration structure/array directly via the FLASH API, perhaps journalling, and skipping the EEPROM Emulation non-sense.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..