我正在使用STM32F072,需要将结构添加到Flash中的特定位置。但是当地址为0x0801F800时,该结构不会被编程为闪烁。
我在命名空间范围内声明一个实例:
const Memory ConfigData __attribute__ ((section (".ConfigData"))) __attribute__ ((__used__)){ 2u, 1.0f, 0.1f, 1.0f, 12.0f, 2.5f };
要将以上内容插入特定的存储位置,我正在使用:
_ConfigStart = 0x0801F800;
.ConfigData _ConfigStart :
{
KEEP(*(.ConfigData));
} > FLASH
上面的代码不起作用,当_ConfigStart地址为0x0800F800时,它将起作用。但是我需要将其放在Flash(0x0801F800)的最后一页中,这样才不是可行的选择。
我可以使用STLINK-V2手动编程所需的页面,也可以使用自己的Flash库来执行此操作,但我需要链接程序将其包含在内。
目前没有链接器错误。
链接器文件: 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 (为简洁起见,删除了某些内容):
__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 iterrated 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出现在.map文件中,地址为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
当分配给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)
我也尝试过将其放入自己的块中:
.ConfigData :
{
KEEP(*(.ConfigData));
} > CONFIG
使用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
}
没有运气,真的迷失了这个。
编辑
这个问题实际上是对该微处理器和编程器的一个奇怪的怪癖。编程器拒绝编程超出闪存大小寄存器指定的闪存范围,但闪存扩展到128K(而非64K)。我已经写了超出地址范围的各种地址,没有任何问题,我之所以认为可以这样做是因为STLINK Utility允许我查看该内存范围。
此问题专门与STM32F072C8有关,我不是唯一遇到这种混乱的人: