gpt4 book ai didi

linker - 了解 ARM Cortex-M 微 Controller 的链接描述文件

转载 作者:行者123 更新时间:2023-12-04 02:16:49 25 4
gpt4 key购买 nike

我正在使用 STMicroelectronics 的 STM32F746NG 微 Controller 。该设备基于 ARM Cortex-M7 架构。我花了相当多的时间来理解示例项目中的链接描述文件。我弄清楚了基础知识,但我仍然无法掌握其中的大部分内容。请帮助我理解这些部分。

链接描述文件的开始

链接描述文件开始如下:

/* Entry Point */
ENTRY(Reset_Handler) /* The function named 'Reset_Handler' is defined */
/* in the 'startup.s' assembly file. */

/* Highest address of the user mode stack */
/* Remember: the stack points downwards */
_estack = 0x20050000; /* End of RAM */

/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200; /* Required amount of heap */
_Min_Stack_Size = 0x400; /* Required amount of stack */

/* --------------------------------------------------------------------*/
/* MEMORY AREAS */
/* --------------------------------------------------------------------*/
MEMORY
{
/* FLASH MEMORY */
/* ------------ */
/* Remember: the flash memory on this device can */
/* get accessed through either the AXIM bus or the */
/* ITCM bus. Accesses on the ITCM bus start at */
/* address 0x0020 0000. Accesses on the AXIM bus */
/* at address 0x0800 0000. */
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
/* FLASH (rx) : ORIGIN = 0x00200000, LENGTH = 1024K */

/* RAM MEMORY */
/* ---------- */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 320K
}

向量表和程序代码

定义存储区后,链接描述文件继续定义段。链接描述文件中定义的第一部分是向量表。它必须以闪存的第一个字节结束。
/* --------------------------------------------------------------------*/
/* OUTPUT SECTIONS */
/* --------------------------------------------------------------------*/
SECTIONS
{
/****************************/
/* VECTOR TABLE */
/****************************/
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Vector Table */
. = ALIGN(4);
} >FLASH

插入向量表后,是时候上程序代码了:
    /****************************/
/* PROGRAM CODE */
/****************************/
.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)


/* Note: The function ‘.text.Reset_Handler’ is one of the *(.text*) sections, */
/* such that it gets linked into the output .text section somewhere here. */
/* We can verify the exact spot where the Reset_Handler section is positioned, by */
/* examining the second entry of the vector table. */
/* A test has given the following results:
/* FLASH (rx) : ORIGIN = 0x0800 0000 ==> Reset_Handler = 0x0800 1C91 */
/* FLASH (rx) : ORIGIN = 0x0020 0000 ==> Reset_Handler = 0x0020 1CB9 */
/*
/* In both cases, the Reset_Handler section ends up a few hundred bytes after the */
/* vector table in Flash. But in the first case, the “Reset_Handler” symbol points */
/* to the Reset-code through AXIM-interface, whereas in the latter case it points */
/* to the Reset-code through the ITCM-interface. */


KEEP (*(.init))
KEEP (*(.fini))

. = ALIGN(4);
_etext = .; /* Define a global symbol at end of code */

} >FLASH

链接描述文件定义了 e_text表示 flash 中程序代码结束地址的全局符号。

恒定数据

只读数据也最终存在于闪存中(将其放入 volatile RAM 中毫无意义)。链接描述文件定义了 .rodata部分应在闪存中:
    /****************************/
/* CONSTANT DATA */
/****************************/
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >FLASH

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

我不知道这些部分是什么。所以让这成为第一个问题。这些部分是什么,它们显示在哪些目标文件中?如您所知,链接描述文件需要将一些目标文件链接在一起。我不知道这些神秘部分存在于哪些目标文件中:
  • .ARM.extab
  • .ARM
  • .preinit_array
  • .init_array
  • .fini_array

  • 这是对闪存的分配的结束。链接描述文件继续定义在 RAM 中结束的部分。

    RAM 中的部分
    .data.bss部分对我来说很清楚。没有关于这个的问题。
        /****************************/
    /* INITIALIZED DATA */
    /****************************/
    _sidata = LOADADDR(.data);
    .data :
    {
    . = ALIGN(4);
    _sdata = .; /* create a global symbol at data start */
    *(.data) /* .data sections */
    *(.data*) /* .data* sections */

    . = ALIGN(4);
    _edata = .; /* define a global symbol at data end */

    } >RAM AT> FLASH


    /****************************/
    /* UNINITIALIZED DATA */
    /****************************/
    . = ALIGN(4);
    .bss :
    {
    _sbss = .; /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .; /* define a global symbol at bss end */
    __bss_end__ = _ebss;

    } >RAM

    链接描述文件还定义了一个 ._user_heap_stack部分:
        /****************************/
    /* USER_HEAP_STACK SECTION */
    /****************************/
    /* User_heap_stack section, used to check that there is enough RAM left */
    ._user_heap_stack :
    {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
    } >RAM

    显然这部分没有立即使用。它仅被定义为检查 RAM 是否仍有足够的空间用于堆栈和堆。如果不是这种情况( . 超过顶部 RAM 地址),则会引发链接器错误。

    链接脚本的结尾

    这就是链接描述文件的结束方式。老实说,我不知道它有什么作用。所以这是第二个问题:以下是什么意思?
        /* Remove information from the standard libraries */
    /DISCARD/ :
    {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
    }

    .ARM.attributes 0 : { *(.ARM.attributes) }
    }
    /* END OF LINKERSCRIPT */

    最佳答案

  • .ARM.extab 和 .ARM.exidx 与展开有关。您可以在这里找到更多信息 http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/index.html .如果您不关心展开(展开对于 C++ 异常和调试很有用),则不需要它们。
  • 这些符号与在 main() 之前/之后调用的 C/C++ 构造函数和析构函数启动和拆除代码有关。名为 .init、.ctors、.preinit_array 和 .init_array 的部分与 C/C++ 对象的初始化有关,而名为 .fini、.fini_array 和 .dtors 的部分则用于拆卸。开始和结束符号定义了与此类操作相关的代码部分的开始和结束,并且可能会从运行时支持代码的其他部分引用。

  • .preinit_array 和 .init_array 部分包含指向将在初始化时调用的函数的指针数组。 .fini_array 是一个将在销毁时调用的函数数组。大概开始和结束标签用于遍历这些列表。
  • 堆:不是真的,那部分允许为堆保留一些空间,为堆栈保留一些空间。显然,如果保留区域的总和超出 RAM 边界,则会引发错误。这是一个例子:

    _Min_Heap_Size = 0;/* 所需的堆数量/
    _Min_Stack_Size = 0x400;/所需的堆栈数量 */

    ._user_heap_stack :
    {
    . =对齐(4);
    提供(结束 = .);
    提供 ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . =对齐(4);
    } >内存
  • 链接库我更喜欢不同的表示法,这只是裸机无 RTOS C++ 项目的一个示例:
    组(libgcc.a libc_nano.a libstdc++_nano.a libm.a libcr_newlib_nohost.a crti.o crtn.o crtbegin.o crtend.o)
  • 关于linker - 了解 ARM Cortex-M 微 Controller 的链接描述文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40532180/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com