C++ 特定地址的链接变量
我正在使用Atmel Studio提供的GCC工具,使用Atmel ARM核心处理器为嵌入式系统编写应用程序。我将使用的生产编程设备可以在编程期间将序列号写入指定的ROM位置,这很好,因为这是一个自动化的过程,避免了潜在的人为错误 我想在二进制文件中留出一些空间,以确保给定的地址在这方面始终是免费的,并且我的应用程序可以从闪存中读取其序列号 我已经看了一些其他的问题,比如看起来和我的问题非常相似的问题,但似乎忽略了答案中的关键细节,因为我无法重现结果 为我的处理器提供的链接器脚本如下所示:C++ 特定地址的链接变量,c++,c,gcc,linker,embedded,C++,C,Gcc,Linker,Embedded,我正在使用Atmel Studio提供的GCC工具,使用Atmel ARM核心处理器为嵌入式系统编写应用程序。我将使用的生产编程设备可以在编程期间将序列号写入指定的ROM位置,这很好,因为这是一个自动化的过程,避免了潜在的人为错误 我想在二进制文件中留出一些空间,以确保给定的地址在这方面始终是免费的,并且我的应用程序可以从闪存中读取其序列号 我已经看了一些其他的问题,比如看起来和我的问题非常相似的问题,但似乎忽略了答案中的关键细节,因为我无法重现结果 为我的处理器提供的链接器脚本如下所示: OU
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00800000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
}
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x3000;
__ram_end__ = ORIGIN(ram) + LENGTH(ram) - 4;
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
_sstack = .;
. = . + __stack_size__;
. = ALIGN(8);
_estack = .;
} > ram
. = ALIGN(4);
_end = . ;
}
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
/**** START ADDED CODE ****/
_metastart = 0x47FF00;
.metadata :
{
. = _metastart;
*(.metadata)
} > rom
/**** END ADDED CODE ****/
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
这个脚本可以正常工作。我曾尝试添加一小段内存来存储闪存中的序列号,但最终链接器总是很高兴地将数据存储在指定的rom区域之外
我已尝试向链接器脚本添加代码,如下所示:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00800000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
}
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x3000;
__ram_end__ = ORIGIN(ram) + LENGTH(ram) - 4;
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
_sstack = .;
. = . + __stack_size__;
. = ALIGN(8);
_estack = .;
} > ram
. = ALIGN(4);
_end = . ;
}
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
/**** START ADDED CODE ****/
_metastart = 0x47FF00;
.metadata :
{
. = _metastart;
*(.metadata)
} > rom
/**** END ADDED CODE ****/
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
对于我的main.cpp,如下所示:
static uint8_t nvSerial[4] __attribute__((used,section(".metadata"))) = { 0xDE, 0xAD, 0xBE, 0xEF };
但最终会得到一个巨大的二进制文件,其数据远远高于0x00480000
,低于0x200000000
。我还尝试编写链接器脚本添加,如下所示(在与上面相同的位置):
但是,我的序列号似乎被完全忽略了(即,0x47FF00
中没有任何内容)。类似地,如果我像这样设置链接器文件,则找不到任何数据:
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x0007FF00
meta (rx) : ORIGIN = 0x0047FF00, LENGTH = 0x00000100 /** ADDED **/
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
}
/** snip **/
.metadata :
{
*(.metadata)
} > meta
有人能就我做错了什么提出建议吗
编辑
因此,问题的“解决方案”是在更新\u etext
的值后,更改我的链接器,以使用KEEP命令来描述元数据
部分。如果我在分配\u etext
之前描述元数据
,那么链接器出于某种原因在元数据
之后存储一组常量数据,并将其存储到未定义的内存区域中。新链接器文件的相关部分如下:
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x0007FF00
meta (rx) : ORIGIN = 0x0047FF00, LENGTH = 0x00000100
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
}
/** snip **/
. = ALIGN(4);
_etext = .;
.metadata :
{
KEEP(*(.metadata))
} > meta
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
这是可行的,但我现在的问题是,为什么这样做?如果使用
.metadata\u metastart:{…}
语法会发生什么?如果使用.metadata\u metastart:{…}
语法会发生什么?