Sometimes you just need to store information permanently – for example data like calibration values or a user generated configuration. Normally you’d use an external EEPROM that is connected via I2C or similar, but there’s no need to struggle with extra hardware as you can easily store the data within the STM32’s internal flash.
The following steps are required to write information to the flash:
- Erase one or more pages (or sectors)
- Unlock the flash for writing operations
- Write desired data (half-word or word) to the flash
- Lock the flash again
It is necessary to erase to erase the pages or sectors, as you can only write data once after each erase operation.
In this example, we will be using a struct to hold our data. To be able to iterate over the struct’s members, it is important that the members are all the same data type (as in data size). We will use a pointer of the member’s data type to iterate over each member.
__IO is a macro that evaluates to
Note: There is no need to use a data structure like the one above, just use the one that fits your requirements, you can also store single variables or arrays.
Find a page / sector that fits your required data size
Now, we need to determine a page or sector that has enough space from our main application so we won’t override any data in the future. Depending on your STM32 device, you’ll find the information on the page or sector addresses and their sizes in datasheet or Reference manual, but also, maybe more easily, using the ST-Link Utility (Target > Erase Sectors..):
Note: The screenshot above was taken while being connected to a STM32F407.
Source: STM32F303 Reference manual
For this example, we’ll use page 16, which starts at address 0x08008000 and has 2K of memory – so let’s define the address somewhere in our header:
#define FLASH_MEMORYMAP_BASE_ADDR 0x08008000
For the next step, we will write our flash functions. Let’s start with the flash erase function.
Note: You can find information on any of the flash operations in the Reference manual under chapter 4.2.3 Flash program and erase operations.
Now that we’ve erased our desired page or sector, it’s time to write some data into the flash. But before that, we need to unlock the flash first. Again, find the required information in the Reference manual:
After a (hopefully) successful unlocking of the flash, we are actually able to write some data into the flash.
Note: The STM32F303 only supports half-word writes to the flash, but as we are dealing with words, we need to perform a little „trick“. We convert the word into the lower and higher bytes (half-words), write the lower half-word first, add 2 to the address and then write the higher half-byte second.
Locking the flash again is as simple as writing to a register.
While not really necessary, let’s write a quick function to read a word from the flash, for the sake of convenience.
Finally: Writing the data in a batch
This method is a wrapper for all the required steps to write the whole
MemoryMap structure into the flash. As every member of the struct is of the same size, we can use a pointer (in this example:
elemPtr) that points to the first member of the struct and gets incremented for each element in the structure.
To read all data from the flash into the struct again, we use another function.
If you’ve put everything together, you should be able to see the written data in your flash beginning at the selected address.
Putting it all together
Here is a little test script, that shows how to use the library.