2025-09-02 4:32 AM - edited 2025-09-02 4:42 AM
Heyho,
how can I put a constant at the end of the STM32's used flash? (using: STM32CubeIDE)
Not at a specific address (that's not a problem), but I'd like to have a constant always at the end of the used internal flash, independent of any other source code changes.
I just find that there's some ASCII characters = "ASCII" (twice) and lots of 0x00 at the end of my H7 and F7 bin files - that from my sources or placed by CubeIDE?
Thanks!
Solved! Go to Solution.
2025-09-02 6:19 AM
An alignment of 4 would be sufficient :)
2025-09-02 6:24 AM
*.map file will show you what was places after your section.
I'm wondering why you do this?
2025-09-02 6:58 AM
> I'm wondering why you do this?
Part of file check for bootloader / application update
2025-09-02 7:05 AM
That i'm gessing, but still, not exacly understand why this method,
I'm juster after creating my bootleader for many decives (end of flash was that last thing to bothering),
2025-09-02 8:23 AM
Paranoia! :D
2025-09-02 9:26 AM - edited 2025-09-02 9:32 AM
Shoot, now the STM32CubeProg complains about the *.elf file :
Warning: File corrupted. Two or more segments defines the same memory zone
And it doesn't load the complete flash content into the programmer.
:(
And this is very bad for first time flashing in production.
2025-09-02 10:31 AM
Showing your ld file could help helping ...
I tried a small project with this change in the ld file:
...
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM
ENDOFFLASH :
{
. = ALIGN(8);
} >FLASH
/* Remove information from the compiler libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
.ARM.attributes 0 : { *(.ARM.attributes) }
}
In the c file I added a variable like this:
const int __attribute__((section("ENDOFFLASH"))) lastVariable = 123;
2025-09-02 10:39 AM - edited 2025-09-02 10:44 AM
ENDOFFLASH :
{
. = ALIGN(8);
*(ENDOFFLASH)
} >FLASH
Input section and output, don't mix this. Also used attribute for variable or keep for section should me used
2025-09-03 1:45 AM
Now I moved the EOF section within the linker file right after the data init section where ">FLASH" is last used.
Then STM32CubeProg does not complain about the *.elf file, but the data window only shows the first flash section...
No problems with the bin file.
Here's part of my linker file - lots of sections... but it works! Except for the new EOF part with elf.
...
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* Specify the memory areas */
MEMORY
{
ITCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 64K /* instruction RAM */
FLBTVEC (rx) : ORIGIN = 0x08000000, LENGTH = 1K /* bootloader vector table */
FLBTFWINFO (rx) : ORIGIN = 0x08000400, LENGTH = 1K /* bootloader firmware info */
FLBOOT (rx) : ORIGIN = 0x08000800, LENGTH = 250K /* bootloader */
FLUSER (rx) : ORIGIN = 0x0803F000, LENGTH = 4K /* TBD / shared One-Time-Programmable ROM */
FLASHVEC (rx) : ORIGIN = 0x08040000, LENGTH = 1K /* application vector table */
FLFWINFO (rx) : ORIGIN = 0x08040400, LENGTH = 1K /* application firmware info */
FLASH (rx) : ORIGIN = 0x08040800, LENGTH = 766K /* application */
/* DTCM: 128 kB
* 0x2000 0000 - 0x2001FFFF
* used as "general" RAM
* no DMA1/2 access, only MDMA memory to memory
*/
/* DTCM_HPST(xrw) : ORIGIN = 0x20000000, LENGTH = 15K */ /* DTCM heap & stack */
/* DTCM_NOINIT(xrw) : ORIGIN = 0x20003C00, LENGTH = 1K */ /* DTCM no init */
/* DTCM_RAM(xrw) : ORIGIN = 0x20004000, LENGTH = 112K */ /* DTCM */
DTCM_RAM(xrw) : ORIGIN = 0x20000000, LENGTH = 112K /* DTCM */
DTCM_NOINIT(xrw) : ORIGIN = 0x2001C000, LENGTH = 1K /* DTCM no init */
DTCM_HPST(xrw) : ORIGIN = 0x2001C400, LENGTH = 15K /* DTCM heap & stack */
/*
without OCTOSPI / HyperRAM, all A2IP buffers in internal SRAM - NUCLEO debug only:
SRAXI_D1(xrw) : ORIGIN = 0x24000000, LENGTH = 96K
SRAXI_D1_LWIP(xrw) : ORIGIN = 0x24018000, LENGTH = 128K
SRAXI_D1_A2IP(xrw) : ORIGIN = 0x24038000, LENGTH = 96K
*/
/*
with OCTOSPI / HyperRAM, all A2IP buffers in external HyperRAM:
*/
/* internal */
SRAXI_D1(xrw) : ORIGIN = 0x24000000, LENGTH = 320K
SRAM1_D2(xrw) : ORIGIN = 0x30000000, LENGTH = 16K
SRAM2_D2(xrw) : ORIGIN = 0x30004000, LENGTH = 16K
SRAM4_D3(xrw) : ORIGIN = 0x38000000, LENGTH = 16K /* only D3 access */
/* external via OCTOSPI / HyperRAM */
OSPI_A2IP_D1(xrw) : ORIGIN = 0x90000000, LENGTH = 0x0E00000 /* OCTOSPI 1 for A2IP */
OSPI_FILE_D1(xrw) : ORIGIN = 0x90E00000, LENGTH = 0x0200000 /* OCTOSPI 1 for file upload buffer */
/* external quad SPI flash via OCTOSPI */
OSPI_FLASH(xrw) : ORIGIN = 0x70000000, LENGTH = 0x0800000 /* OCTOSPI 2 for QSPI flash */
}
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* Define output sections */
SECTIONS
{
/* The startup code goes first into FLASHVEC */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASHVEC
/* The program code and other data goes into 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 global symbols at end of code */
} >FLASH
/* Constant data goes into FLASH */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM :
{
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* FLASH sections for BOOTLOADER
* firmware version info
*/
.FlashBootFwSection :
{
KEEP(*(.FlashBootFwSection)) ;
} >FLBTFWINFO
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* FLASH sections for APPLICATION
* user eeprom
* firmware version info
*/
.FlashAppUserSection :
{
KEEP(*(.FlashAppUserSection)) ;
} >FLUSER
.FlashAppFwSection :
{
KEEP(*(.FlashAppFwSection)) ;
} >FLFWINFO
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* internal SRAM */
/* used by the startup to initialize data */
_sidata = LOADADDR(.data);
/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
*(.RamFunc) /* .RamFunc sections */
*(.RamFunc*) /* .RamFunc* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >SRAXI_D1 AT >FLASH
/* SRAXI_D1 or DTCM_RAM */
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* EOF string file info */
.FlashAppEOF :
{
. = ALIGN(8);
*(.FlashAppEOF)
*(.FlashAppEOF*)
. = ALIGN(8);
} >FLASH
/* -------------------------------------------------------- */
/* Uninitialized data section */
...
2025-09-03 1:59 AM
Maybe it is removed by linker as not used?
One linker for APP and bootloader? Very bad idea !!!!!!!!!!!!