1
\$\begingroup\$

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?

\$\endgroup\$
  • \$\begingroup\$ Isn't the usage by the "HAL or any other internal mechanism" documented somewhere? \$\endgroup\$ – anrieff Jul 5 at 7:29
  • \$\begingroup\$ It should, I tried to find such documentation but did not succeed. \$\endgroup\$ – ihsanogluu Jul 5 at 7:41
  • \$\begingroup\$ Related (but not exact duplicate): Storing values in the internal flash memory \$\endgroup\$ – berendi - protesting Jul 5 at 8:47
  • \$\begingroup\$ @berendi this is a completly differen question. I am not asking HOW to read and write. I am asking for a way to be sure I got safe addresses to use. \$\endgroup\$ – ihsanogluu Jul 5 at 8:59
  • \$\begingroup\$ The answer for your question is the same as the first part of the linked answer: it depends on the linker used. \$\endgroup\$ – berendi - protesting Jul 5 at 9:02
1
\$\begingroup\$

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


\$\endgroup\$
  • \$\begingroup\$ thank you for your useful answer. I am using keil and can't apply these linker scripts. Keil uses different syntax with scatter files. However your answer was helpful for me I changed the size of Flash in the scatter file. Now the last sector won't be included in the program flash. I know it is a huge sector but its ok. This does the job. thank you. \$\endgroup\$ – ihsanogluu Jul 5 at 12:01
1
\$\begingroup\$

You can use any flash sector (or smallest erasable unit).
The first one is required to boot when BOOT_ADD isn't changed for a different entry point.

You will have to specify in your linker that you are using a region of memory for other purposes, or link the configuration to this region already.

See Table 3. STM32F756xx and STM32F74xxx Flash memory organization in the reference manual.

Please also note Table 48. Flash memory programming in the Datasheet. There are significant sector erase times.

You may also want to investigate eeprom emulation to support more write cycles, or faster writing. But the low sector count might make this wasteful to implement. In that case you might want to get external FRAM/EEPROM.

\$\endgroup\$
  • 1
    \$\begingroup\$ It's indeed possible to use the first sector on the STM32F7. \$\endgroup\$ – berendi - protesting Jul 5 at 11:50
  • \$\begingroup\$ @berendi Noted. \$\endgroup\$ – Jeroen3 Jul 5 at 12:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.