cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F746 writing data into internal flash without erasing whole sector

q123w123e123qweqwe
Associate III

Hi,

I'm working on a project using stm32f746 and touchGFX. I need to store some data into flash and change it when I desire for that, I guess I have to erase the whole sector, which I don't want because I have some data in every sector. I use 85% flash for now. So is there any way to delete specific memory before writing?

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

I would create a new memory definition for just the vector table, and move the beginning of FLASH past the reserved flash sectors.

MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 320K
  FLASH_VECTOR    (rx)    : ORIGIN = 0x8000000,   LENGTH = 32K 
  FLASH    (rx)    : ORIGIN = 0x8018000,   LENGTH = 928K /* 1024 - 3*32 */
}
 
/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH_VECTOR
  .after_vector :
  {
    . = ALIGN(4);
    KEEP(*(.after_vector))
    . = ALIGN(4);
  } >FLASH_VECTOR

and keep everything else unchanged.

Now the memory between 0x08008000 and 0x08018000, i.e. flash sectors 1 and 2 are no longer managed by the linker, so you can have your own functions that read and write that area as described in the flash chapter of the reference manual.

There is about 31 kbytes of flash space wasted after the vector table, you can move some read-only data in there if memory is still tight. Look through the .map file, look for read-only data structures, arrays whose size add up to roughly 31 k. CubeIDE has a memory details table in the Build Analyzer view which contains more or less the same information as the .map file, open the .rodata section under flash, order it by size, and pick some objects from there. Put the following line before their definition in the .c source:

__attribute__((section(".after_vector")))

so that this 31 kbyte of flash does not go wasted.

View solution in original post

7 REPLIES 7
berendi
Principal

No, flash does not work that way. You can erase whole sectors at once (set all bits to 1s) or write to bytes which are not written since the last erase. (Actually you can turn any bit from 1 to 0, even one-by-one.) So you have to reserve at least one full sector, or better two of them to have a backup when the power goes away while erasing.

You might want use the 32 kbyte sectors 1 & 2 at the beginning for data storage. Keep the vector table in sector 0 and move up the rest of the code to 0x08018000 (sector 3). How to actually do it depends on the toolchain.

You can use a jouralling technique where you write structures until you consume unwritten space, whilst reading back the last or most recent structure.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Befor I've seen this I change the flash section's value on LinkerScript file from 1024 to 768. And I easly used last part becouse touchGFX didn't store anything in there. But 7. section is huge I cant' use 254kB and need that memory. So I tried your thing and create new stack (.myspace) but I dont know how to fill this or is there any way to do it.

I use STM32F746 and CubeIDE as compiler.

Tanks for reply btw.

/
 
/* Entry Point */
ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);	/* end of "RAM" Ram type memory */
 
_Min_Heap_Size = 0x200 ;	/* required amount of heap  */
_Min_Stack_Size = 0x400 ;	/* required amount of stack */
 
/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 320K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 768K 
}
 
/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH
 
  /* The program code and other data into "FLASH" Rom type memory */
  .myspace :
  {
  	. = ALIGN(4);
  	*(.myspace)
  	*(.myspace*)
  	. = ALIGN(4);
  }>FLASH
  
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
 
    KEEP (*(.init))
    KEEP (*(.fini))
 
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH

berendi
Principal

I would create a new memory definition for just the vector table, and move the beginning of FLASH past the reserved flash sectors.

MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 320K
  FLASH_VECTOR    (rx)    : ORIGIN = 0x8000000,   LENGTH = 32K 
  FLASH    (rx)    : ORIGIN = 0x8018000,   LENGTH = 928K /* 1024 - 3*32 */
}
 
/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH_VECTOR
  .after_vector :
  {
    . = ALIGN(4);
    KEEP(*(.after_vector))
    . = ALIGN(4);
  } >FLASH_VECTOR

and keep everything else unchanged.

Now the memory between 0x08008000 and 0x08018000, i.e. flash sectors 1 and 2 are no longer managed by the linker, so you can have your own functions that read and write that area as described in the flash chapter of the reference manual.

There is about 31 kbytes of flash space wasted after the vector table, you can move some read-only data in there if memory is still tight. Look through the .map file, look for read-only data structures, arrays whose size add up to roughly 31 k. CubeIDE has a memory details table in the Build Analyzer view which contains more or less the same information as the .map file, open the .rodata section under flash, order it by size, and pick some objects from there. Put the following line before their definition in the .c source:

__attribute__((section(".after_vector")))

so that this 31 kbyte of flash does not go wasted.

Carve a hole to allow you to use one of the smaller flash blocks.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

It worked thanks a lot.

 
 
 
 i  am trying to use this concept in my project which is based on stm32f401ccu6,
 Here i want to keep free the sector 2 and 3 so that they can used to store few device specific calibration parameters. the parameters will updated hundreds of time during the life cycle of the device. so sectors(2 and 3) need to be erased many times.
when i added your logic in the linker script, programmed device with this, when i read the device memory using st link it shows that the sectors 2 and 3 is not free but have data and main program is not loaded at sector 4 but it remains at 0x8000000.
Please suggest the correct solution. or if you could share the complete linker script for cross checking.