Electronic – Which flash sector to write into

embeddedflashstm32

I need to save working configuration of my embedded application to the flash memory.

I am using STM32f746 uController. According to the datasheet. There is 8 sectors on the main block of the flash memory.

This will be my first time trying to write/read data from internal flash memory.

My question is the following:

  • How can I be sure what sectors/addresses are safe to use?

some sectors and addresses may be used by the HAL or any other internal mechanism in architecture or the firmware. How can I be sure that a given address is not used and will never be used by another parts?

Best Answer

To use a region of the internal flash for your own purposes, reserve it in the linker definition. But first, decide which area you'd like to use. Looking at the flash layout,

enter image description here

the sectors at the end are quite large, so you can use those only when you are content with losing a fourth of the available flash (half if you'd like to have a backup sector). In this case, just decrease the amount of flash in the linker config file. If you are using the GNU toolchain, change it from

FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1024K

to

FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 768K /* last 256k reserved */

or

FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K /* last 512 reserved */

update in this case, the last sectors will be left alone by ST-Link, i.e. neither erased (unless you explicitly let it erase all flash) nor programmed.


To use one (or two) of the 32k sectors, we can't just move the beginning up, because the vector table must reside in sector 0, as the reset address is taken from there. we can put some custom structures after the vector table.

.isr_vector :
{
  . = ALIGN(4);
  KEEP(*(.isr_vector)) /* Startup code */
  . = ALIGN(32768);
  KEEP(*(.userconfig1))
  . = ALIGN(32768);
  KEEP(*(.userconfig2))
  . = ALIGN(32768);
} >FLASH

and then in the code

__attribute__ ((section(".userconfig1"),used))
volatile const struct cfg userconfig1[32768/sizeof(struct cfg)];
__attribute__ ((section(".userconfig2"),used))
volatile const struct cfg userconfig2[32768/sizeof(struct cfg)];

to be able to get at the values directly from the program.

update in this case, these sectors will be erased and programmed every time you reflash your code. They will be filled with zeroes, or you can put some default values in the arrays in your code.


UPDATE

Unlike most STM32 MCUs, it's possible to move the beginning of the flash on the F7, freeing up the 32k sectors. Adjust both the begin and the length of the flash sector in the linker script, e.g.

FLASH (rx)      : ORIGIN = 0x08020000, LENGTH = 896K

to free up the first four 32k blocks, and adjust the Boot address option bytes accordingly, in this case to 0x2008