I'm working with a STM32F072 and need to add a structure to a specific location in Flash. But the structure doesn't get programmed to flash when the address is 0x0801F800.
I declare an instance at namespace scope:
const Memory ConfigData __attribute__ ((section (".ConfigData"))) __attribute__ ((__used__)){ 2u, 1.0f, 0.1f, 1.0f, 12.0f, 2.5f };
To insert the above at a specific memory location i'm using:
_ConfigStart = 0x0801F800;
.ConfigData _ConfigStart :
{
KEEP(*(.ConfigData));
} > FLASH
The above code does not work however, when the _ConfigStart address is 0x0800F800 it does work. But I need it to be in the last page of flash (0x0801F800) so that isn't a workable option.
I am able to use the STLINK-V2 to manually program the page I want and I can also use my own flash library to do it but I need it to be included by the linker.
There are no linker errors at this point.
Linker files: mem.ld:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
CCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 0
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
MEMORY_ARRAY (xrw) : ORIGIN = 0x00000000, LENGTH = 0
}
sections.ld(some things cut out for brevity):
__stack = ORIGIN(RAM) + LENGTH(RAM);
_estack = __stack; /* STM specific definition */
/*
* Default stack sizes.
* These are used by the startup in order to allocate stacks
* for the different modes.
*/
__Main_Stack_Size = 1024 ;
PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;
__Main_Stack_Limit = __stack - __Main_Stack_Size ;
PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;
_Minimum_Stack_Size = 256 ;
PROVIDE ( _Heap_Begin = _end_noinit ) ;
PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ;
ENTRY(_start)
SECTIONS
{
.isr_vector : ALIGN(4)
{
FILL(0xFF)
__vectors_start = ABSOLUTE(.) ;
__vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */
KEEP(*(.isr_vector)) /* Interrupt vectors */
KEEP(*(.cfmconfig)) /* Freescale configuration words */
*(.after_vectors .after_vectors.*) /* Startup code and ISR */
} >FLASH
.inits : ALIGN(4)
{
/*
* Memory regions initialisation arrays.
*
* Thee are two kinds of arrays for each RAM region, one for
* data and one for bss. Each is iterated at startup and the
* region initialisation is performed.
*
* The data array includes:
* - from (LOADADDR())
* - region_begin (ADDR())
* - region_end (ADDR()+SIZEOF())
*
* The bss array includes:
* - region_begin (ADDR())
* - region_end (ADDR()+SIZEOF())
*
* WARNING: It is mandatory that the regions are word aligned,
* since the initialisation code works only on words.
*/
__data_regions_array_start = .;
LONG(LOADADDR(.data));
LONG(ADDR(.data));
LONG(ADDR(.data)+SIZEOF(.data));
LONG(LOADADDR(.data_CCMRAM));
LONG(ADDR(.data_CCMRAM));
LONG(ADDR(.data_CCMRAM)+SIZEOF(.data_CCMRAM));
__data_regions_array_end = .;
__bss_regions_array_start = .;
LONG(ADDR(.bss));
LONG(ADDR(.bss)+SIZEOF(.bss));
LONG(ADDR(.bss_CCMRAM));
LONG(ADDR(.bss_CCMRAM)+SIZEOF(.bss_CCMRAM));
__bss_regions_array_end = .;
/* End of memory regions initialisation arrays. */
/*
* These are the old initialisation sections, intended to contain
* naked code, with the prologue/epilogue added by crti.o/crtn.o
* when linking with startup files. The standalone startup code
* currently does not run these, better use the init arrays below.
*/
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
/*
* The preinit code, i.e. an array of pointers to initialisation
* functions to be performed before constructors.
*/
PROVIDE_HIDDEN (__preinit_array_start = .);
/*
* Used to run the SystemInit() before anything else.
*/
KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))
/*
* Used for other platform inits.
*/
KEEP(*(.preinit_array_platform .preinit_array_platform.*))
/*
* The application inits. If you need to enforce some order in
* execution, create new sections, as before.
*/
KEEP(*(.preinit_array .preinit_array.*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/*
* The init code, i.e. an array of pointers to static constructors.
*/
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/*
* The fini code, i.e. an array of pointers to static destructors.
*/
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH
.flashtext : ALIGN(4)
{
*(.flashtext .flashtext.*) /* Startup code */
} >FLASH
.text : ALIGN(4)
{
*(.text .text.*) /* all remaining code */
/* read-only data (constants) */
*(.rodata .rodata.* .constdata .constdata.*)
*(vtable) /* C++ virtual tables */
KEEP(*(.eh_frame*))
*(.glue_7)
*(.glue_7t)
} >FLASH
/* ARM magic sections */
.ARM.extab : ALIGN(4)
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
. = ALIGN(4);
__exidx_start = .;
.ARM.exidx : ALIGN(4)
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
. = ALIGN(4);
_etext = .;
__etext = .;
.data_CCMRAM : ALIGN(4)
{
FILL(0xFF)
*(.data.CCMRAM .data.CCMRAM.*)
. = ALIGN(4) ;
} > CCMRAM AT>FLASH
_sidata = LOADADDR(.data);
.data : ALIGN(4)
{
FILL(0xFF)
/* This is used by the startup code to initialise the .data section */
_sdata = . ; /* STM specific definition */
__data_start__ = . ;
*(.data_begin .data_begin.*)
*(.data .data.*)
*(.data_end .data_end.*)
. = ALIGN(4);
/* This is used by the startup code to initialise the .data section */
_edata = . ; /* STM specific definition */
__data_end__ = . ;
} >RAM AT>FLASH
_ConfigStart = 0x0801F800;
.ConfigData _ConfigStart :
{
KEEP(*(.ConfigData));
} > FLASH
.bss (NOLOAD) : ALIGN(4)
{
__bss_start__ = .; /* standard newlib definition */
_sbss = .; /* STM specific definition */
*(.bss_begin .bss_begin.*)
*(.bss .bss.*)
*(COMMON)
*(.bss_end .bss_end.*)
. = ALIGN(4);
__bss_end__ = .; /* standard newlib definition */
_ebss = . ; /* STM specific definition */
} >RAM
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/*
* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0.
*/
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}
ConfigData appears in the .map file here with address 0x0800f800:
.igot.plt 0x20000078 0x0 c:/program files (x86)/gnu tools arm embedded/7 2017-q4-major/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libstdc++_nano.a(new_op.o)
.ConfigData 0x0800f800 0x18
*(.ConfigData)
.ConfigData 0x0800f800 0x18 C:\Users\David\AppData\Local\Temp\cc10vcUe.ltrans0.ltrans.o
.rel.dyn 0x0800f818 0x0
And appears to get a size when allocated to 0x0801f800:
.igot.plt 0x20000078 0x0 load address 0x080090c8
.igot.plt 0x20000078 0x0 c:/program files (x86)/gnu tools arm embedded/7 2017-q4-major/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libstdc++_nano.a(new_op.o)
.ConfigData 0x0801f800 0x18
*(.ConfigData)
.ConfigData 0x0801f800 0x18 C:\Users\David\AppData\Local\Temp\ccIUhOBG.ltrans0.ltrans.o
.rel.dyn 0x0801f818 0x0
.rel.iplt 0x0801f818 0x0 c:/program files (x86)/gnu tools arm embedded/7 2017-q4-major/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libstdc++_nano.a(new_op.o)
I have also tried putting it into its own block:
.ConfigData :
{
KEEP(*(.ConfigData));
} > CONFIG
With the mem.ld:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K - 0x800
CONFIG(R) : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 0x800
}
No luck, really lost on this one.
EDIT
The issue was infact a strange quirk with this micro controller and the programmer. The programmer refuses to program beyond the flash range specified by the flash size register but the flash extends to 128K (not 64K). I have written to various addresses beyond the address range without issue and the reason I thought it was alright to do that was because the STLINK Utility allowed me to view that memory range.
This issue is specifically to-do with the STM32F072C8, and I'm not the only one with this confusion:
User contributions licensed under CC BY-SA 3.0