2024-08-19 02:20 PM
Hi,
I would like to change at runtime some user-defined variables stored in Flash (so they remain on the system after power off). I have defined them as const and some are just 16 bits vars and others are more complex large structures. What is the best way to do that?
I came across the Flash Sector erase function but don't want to risk using a whole block erase (i.e. reading block, changing specific byte, word or struct then write back the entire sector with new values). Are there other options?
Also which include files do I need? Still getting familiar with the documentation, I came across three possible header files to include but not sure which to include in my code of these:
#include <stm32l4xx_hal_flash.h>
#include <stm32l4xx_hal_flash_ex.h>
#include <stm32l4xx_hal_flash_ramfunc.h>
could someone please clarify that too.
Thank you :smiling_face_with_smiling_eyes:
2024-08-19 02:28 PM
There's no way to modify a flash sector without erasing it first. It is a hardware limitation. The most common solution is to use a sector of flash which is reserved for user settings variables and can be erased as needed.
The top level HAL include should be "stm32l4xx_hal.h". That's it. Other files are included from within there as needed. Modify your stm32l4xx_hal_conf.h file to include other modules if needed.
2024-08-19 02:32 PM
You cannot change anything random in a flash memory.
After erase (block of memory typically) you can write it once - that's it. To write new data, you have to erase the area and then you can write it again.
So to store some values, you can use the battery backed up ram ( if you have a battery on your system) in RTC module, attach an eeprom or use a part of the CPU flash as a eeprom ( there are some examples for this in GitHub or STM examples ).
2024-08-19 03:08 PM
Journal the structure content over the available erased flash space.
By "journal" I mean write multiple instances of the structure, with say a sequence count and checksum or CRC, so you can walk it later and pull out the most recent valid instance.
Use two pages/sectors, so you always have a valid copy, erase the first page at the point you're ready to write the second instance into the second page.
2024-08-20 05:57 AM
Note: depending on STM32L4 exact model you are using, the Flash page sizes can be 2 or 4 KBytes. Check the actual value in the reference manuals or stm32l4xx_hal_flash.h.
For example, if you are using STM32L4R5 (STM32L4R5xx defined in your C project):
#if defined (STM32L4P5xx) || defined (STM32L4Q5xx) || defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#define FLASH_PAGE_SIZE ((uint32_t)0x1000)
#define FLASH_PAGE_SIZE_128_BITS ((uint32_t)0x2000)
#else
#define FLASH_PAGE_SIZE ((uint32_t)0x800)
#endif
Other STM32 families also have different Flash page sizes.
2024-08-22 03:38 PM
Thank you all,
I think I will also implement the journal that @Tesla DeLorean suggested. Is there any code example I can use as reference?
To make sure it remains consistent, I think I should specify the page address to be used. Would you recommend any preferred flash memory areas, like perhaps at the very top? Or would that be an issue if changing to a larger memory size micro in the future?
How do you ensure that page is never overwritten by other code (to avoid having such code modified when updating the variables)?
Thank you
2024-08-22 03:48 PM
@Ricko wrote:Is there any code example I can use as reference?
you could look at how X-CUBE-EEPROM does it, or the earlier app notes:
Or other manufacturers solutions; eg,