13

STMicroelectronics の STM32F746NG マイクロコントローラを使用しています。このデバイスは、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リンカー スクリプトは、フラッシュ内のプログラム コードが終了するアドレスを表すグローバル シンボルを定義します。

定数データ

読み取り専用データも最終的にフラッシュ メモリに格納されます (揮発性の RAM に配置しても意味がありません)。リンカー スクリプトは、.rodataセクションがフラッシュにある必要があることを定義します。

    /****************************/
    /*      CONSTANT DATA       */
    /****************************/
    .rodata :
    {
        . = ALIGN(4);
        *(.rodata)         /* .rodata sections (constants, strings, etc.) */
        *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
        . = ALIGN(4);
    } >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 アドレスを超えている場合) は、リンカ エラーがスローされます。

リンカースクリプトの終わり

これがリンカースクリプトの終了方法です。そして正直なところ、私はそれが何をするのか分かりません。これが 2 番目の質問です。次の意味は何ですか?

    /* Remove information from the standard libraries */
    /DISCARD/ :
    {
        libc.a ( * )
        libm.a ( * )
        libgcc.a ( * )
    }

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

2 に答える 2

9
  1. .ARM.extab と .ARM.exidx は巻き戻しに関連しています。詳細については、 http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044e/index.htmlを参照してください。巻き戻しを気にしないのであれば、それらは必要ありません (巻き戻しは C++ 例外とデバッグに役立ちます)。

  2. これらのシンボルは、main() の前後に呼び出される C / C++ コンストラクターおよびデストラクタの起動と分解コードに関連しています。.init、.ctors、.preinit_array、および .init_array という名前のセクションは、C/C++ オブジェクトの初期化に関係しており、セクション .fini、.fini_array、および .dtors は分解用です。開始記号と終了記号は、そのような操作に関連するコード セクションの開始と終了を定義し、ランタイム サポート コードの他の部分から参照される場合があります。

.preinit_array および .init_array セクションには、初期化時に呼び出される関数へのポインターの配列が含まれています。.fini_array は、破棄時に呼び出される関数の配列です。おそらく、開始ラベルと終了ラベルは、これらのリストをたどるために使用されます。

  1. ヒープ: そうではありません。その部分は、ヒープ用のスペースとスタック用のスペースを予約することを許可します。予約領域の合計が RAM の境界を超えると、明らかにエラーが発生します。これは例です:

    _Min_Heap_Size = 0; /* 必要なヒープ量 / _Min_Stack_Size = 0x400; /必要スタック量 */

    ._user_heap_stack: { . = アライン (4); 提供 (エンド = .); 提供 ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = アライン (4); >RAM

  2. ライブラリをリンクするには、別の表記法を好みます。これはベアメタルの RTOS を使用しない C++ プロジェクトの単なる例です。 crtbegin.o crtend.o)

于 2016-11-11T00:16:53.723 に答える