0

I am saving settings to the flash memory and reading them back again. 2 of the values always comes back empty. However, the data IS written to flash, since after a reset the values read are the new saved values and not empty.

I started experiencing this problem after I did some code-refactoring after taking the code over from another company.

Saving and reading the settings back works when you actually do the following (old inefficient way): save setting 0 - read setting 0 save setting 1 - read setting 1 ... save setting 13 read setting 13

This is EXTREMELY inefficient and slow since the same page with all the settings are read from flash, the whole block of flash cleared, the new setting put into the read buffer and then the whole block (with only 1 changed setting) are written to flash. And this happens for all 14 settings!! But it works ...

unsigned char Save_One_Setting(unsigned char Setting_Number, unsigned char* value, unsigned char length)
{
  /* Program the user Flash area word by word
    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
  unsigned int a;

  Address = FLASH_USER_START_ADDR;
  a = 0;
  while (Address < FLASH_USER_END_ADDR)
  {
    buf[a++] = *(__IO uint32_t *)Address;
    Address = Address + 4;
  }

  memset(&buf[Setting_Number * 60], 0, 60);         // Clear setting value
  memcpy(&buf[Setting_Number * 60], &value[0], length); // Set setting value

  Erase_User_Flash_Memory();

  HAL_FLASH_Unlock();

  Address = FLASH_USER_START_ADDR;
  a = 0;

  while (Address < FLASH_USER_END_ADDR)
  {
    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, buf[a++]) == HAL_OK)
    {
        Address = Address + 4;
    }
   else
    {
      /* Error occurred while writing data in Flash memory.
         User can add here some code to deal with this error */
      while (1)
      {
        /* Make LED1 blink (100ms on, 2s off) to indicate error in Write operation */
        BSP_LED_On(LED1);
        HAL_Delay(100);
        BSP_LED_Off(LED1);
        HAL_Delay(2000);
      }
    }
  }

  /* Lock the Flash to disable the flash control register access (recommended
     to protect the FLASH memory against possible unwanted operation) *********/
  HAL_FLASH_Lock();
}

I changed this by actually, after reading the settings from the flash into a buffer, update all the changed settings in the buffer, then erase the flash block and write the buffer back to flash. Downside: my first and 4th values always comes back as NULL after saving this buffer to flash.

However, after a system reset the correct values are read from flash.

unsigned char Save_Settings(Save_Settings_struct* newSettings)
{
  /* Program the user Flash area word by word
    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
  unsigned int a;
  unsigned char readBack[60];

  Address = FLASH_USER_START_ADDR;
  a = 0;
  while (Address < FLASH_USER_END_ADDR)
  {
    buf[a++] = *(__IO uint32_t *)Address;
    Address = Address + 4;
  }

  a = 0;

  while (a < S_MAXSETTING)
  {
      if (newSettings[a].settingNumber < S_MAXSETTING)
      {
          memset(&buf[a * 60], 0, 60);          // Clear setting value
          memcpy(&buf[a * 60], newSettings[a].settingValue, newSettings[a].settingLength);  // Set setting value
      }

      ++a;
  }

  Erase_User_Flash_Memory();

  HAL_FLASH_Unlock();

  Address = FLASH_USER_START_ADDR;
  a = 0;

  while (Address < FLASH_USER_END_ADDR)
  {
    if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, buf[a++]) == HAL_OK)
    {
        Address = Address + 4;
    }
   else
    {
      /* Error occurred while writing data in Flash memory.
         User can add here some code to deal with this error */
      while (1)
      {
        /* Make LED1 blink (100ms on, 2s off) to indicate error in Write operation */
        BSP_LED_On(LED1);
        HAL_Delay(100);
        BSP_LED_Off(LED1);
        HAL_Delay(2000);
      }
    }
  }

  /* Lock the Flash to disable the flash control register access (recommended
     to protect the FLASH memory against possible unwanted operation) *********/
  HAL_FLASH_Lock();
}

I started playing around with cleaning and invalidating the data cache. At least the 2 values are not NULL anymore, however, they are still the old values. All other values are the new, saved values. Do a reset, and all values are correct.

Anybody ever had some similar problem? Or maybe an idea of what I can try to get rid of this problem?

VC.One
  • 14,790
  • 4
  • 25
  • 57
user5763204
  • 99
  • 1
  • 11
  • You have 13 settings with fixed length of 60 bytes each making 780 bytes, correct? How does that tally with your block-size - which may be 512 bytes? – Mark Setchell Aug 29 '18 at 19:38
  • Sorry, but I do not think that is the problem. The sectors are handled correctly by the lower layer depending on the address where you want to save. At this (the current) level there should not be any low-level handling involved and handling of the sectors is basically transparent here. – user5763204 Aug 31 '18 at 20:57

0 Answers0