我有两个来自Nordic Semiconductor的链接描述文件,用于对其平台进行交叉编译。我正在使用arm-none-eabi-gcc
。在原始设置中,每个示例都是特定的,例如为不同的目标配置RAM和闪存。然后,所有示例都有一个通用的链接器文件。由于我只针对一个平台,因此我将第二个文件的内容复制并粘贴到第一个文件中。
这导致了链接代码的某些问题。在版本1中,我包含了INCLUDE
语句,但是它仅包含一个 empty 文件。在版本2中,我省略了INCLUDE
语句。如果我链接代码,则会得到以下不同的输出。版本1可以正常工作,版本2无法正常工作(它可以启动,但是我无法重置芯片)。
版本1
$ cat output.map | grep bss_
0x0000000020002cc0 __bss_start__ = .
0x0000000020003000 __bss_end__ = .
版本2
$ cat output.map | grep bss_
0x0000000020002cc0 __bss_start__ = .
0x0000000020003000 __bss_end__ = .
0x0000000020003000 __bss_start = .
0x0000000020003000 __bss_start__ = .
0x0000000020003000 _bss_end__ = .
0x0000000020003000 __bss_end__ = .
(我可以看到)与此有关的三个问题。
__bss_
输入两次。 __bss_
除外,
与正确生成的文件相同。我认为INCLUDE
基本上是“复制粘贴”吗?这是怎么回事?
链接器
$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors 6-2017-q2-update)
6.3.1 20170620 (release) [ARM/embedded-6-branch revision 249437]
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
命令
arm-none-eabi-g++ --specs=nano.specs -mcpu=cortex-m4 -Wl,--gc-sections -mthumb -mabi=aapcs -lc -lnosys -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Tscript.ld -Xlinker -Map=app.map -o "app.out" object/files
链接器脚本
底部的修改。
/* Linker script to configure memory regions. */
SEARCH_DIR(.)
GROUP(-lgcc -lc -lnosys)
MEMORY
{
FLASH (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000
RAM (rwx) : ORIGIN = 0x20002c38, LENGTH = 0xd3c8
}
SECTIONS
{
.fs_data :
{
PROVIDE(__start_fs_data = .);
KEEP(*(.fs_data))
PROVIDE(__stop_fs_data = .);
} > RAM
.pwr_mgmt_data :
{
PROVIDE(__start_pwr_mgmt_data = .);
KEEP(*(.pwr_mgmt_data))
PROVIDE(__stop_pwr_mgmt_data = .);
} > RAM
} INSERT AFTER .data;
/* Linker script for Nordic Semiconductor nRF51 devices
*
* Version: Sourcery G++ 4.5-1
* Support: https://support.codesourcery.com/GNUToolchain/
*
* Copyright (c) 2007, 2008, 2009, 2010 CodeSourcery, Inc.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice is included verbatim in any distributions. No written agreement,
* license, or royalty fee is required for any of the authorized uses.
* Modifications to this software may be copyrighted by their authors
* and need not follow the licensing terms described here, provided that
* the new terms are clearly indicated on the first page of each file where
* they apply.
*/
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapBase
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(Reset_Handler)
SECTIONS {
.text :
{
KEEP(*(.isr_vector))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
__etext = .;
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
KEEP(*(.jcr*))
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
} > RAM
.heap (COPY):
{
__HeapBase = .;
__end__ = .;
PROVIDE(end = .);
KEEP(*(.heap*))
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (COPY):
{
KEEP(*(.stack*))
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}
/* Include empty file. */
/* INCLUDE "empty.ld" */