首次编译微控制器的gcc链接描述文件但未运行

时间:2019-10-16 21:55:47

标签: c++ gcc embedded atmel linker-scripts

我通过atmel studio为SAMD51J19微控制器创建了我的第一个gcc链接描述文件,它编译良好,没有问题,但是当加载到设备中时,会发生奇怪的古怪错误。

有时它会发生硬故障,有时不会,有时不会将中断发送给处理程序,有时会发送给处理程序。有时,函数运行时没有发生应有的事情,有时却没有发生。调试器到处都是,旧的股票链接器代码没有这些问题,我也不知道为什么会发生。

大部分内容都已从原始文件中重新使用。我主要要做的是在区域之间添加一些间距或更好的对齐方式,并在其中强制移动一些部分。例如,只读数据位于rom bank 0的末尾而不是中间。所以我真的不知道为什么会这样

下面是我的链接脚本

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)

/*
 * NVM = 2 Banks (512KB) (352KB usable) (160KB reserved for SEEPROM)
 * 1 Bank = 32 blocks (256K) and 16 Regions
 *    Bank 1 (Main) = 32 blocks (256K) and 16 Regions
 *    Bank 2 (Aux)  = 12 Blocks (96KB) and 6 Regions
 * 1 Region = 2 Blocks (16KB) (Protection Alignment)
 * 1 Block = 16 Pages (8KB) (Division Alignment)
 * 1 Page = 32 QWords (512B) (Section Alignment)
 * 1 QWord = 16 Bytes (Sub-Section Alignment)
 * 1 DWord = 8 Bytes
 * 1 Word  = 4 Bytes (Default Alignment)
 *
 * Alignments:
 * 4      Bytes: New piece
 * 16     Bytes: New Subsection
 * 512    Bytes: New Section
 * 8,192  Bytes: New division
 * 16,384 Bytes: New protection region
*/

/* Memory Spaces Definitions */
MEMORY
{
  rom0     (rx)  : ORIGIN = 0x00000000, LENGTH = 0x0003F800 /*Rom Bank 0: Main Bank (For Code)*/
    lnl      (rx)  : ORIGIN = 0x0003F800, LENGTH = 0x00000800 /*Load-N-Lock 0-Wait State Speed: 2KB*/

  rom1     (rx)  : ORIGIN = 0x00040000, LENGTH = 0x00018000 /*Rom Bank 1: Aux Bank (For Data)*/
  qspi     (rx)  : ORIGIN = 0x04000000, LENGTH = 0x01000000 /*External NVM: (Additional Aux Data on seperate chip)*/
  ram      (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000 /*Ram (Default RAM)*/
  seeprom  (rx)  : ORIGIN = 0x44000000, LENGTH = 0x00010000 /*SEEPROM: Runtime Permanent Data*/
  bkupram  (rwx) : ORIGIN = 0x47000000, LENGTH = 0x00002000 /*Backup Ram: Program Data*/
}

/* The stack size used by the application*/
STACK_SIZE = 0xC000;

/* Section Definitions */
SECTIONS
{
  /*
    Program Code

    Gameplan for .text output section

    No support for exceptions or unwinding tables

    Vectors go at start
    Program Code is placed on the next QWord
    Thumb/Arm Glue code is placed on the next QWord
    Read-Only Data is placed in it's own page
    Relocate Data is placed in it's own page
  */
  .text :
  {
    /*Start at top*/
    . = 0x00000000;
    _stext = .;
    _sfixed = .;

    /*Vector Table*/
    /*Place Vectors at start of rom0 as required*/
    KEEP(*(.vectors .vectors.*))

    /*Program Code*/
    . = ALIGN(16); /*New Subsection*/
    *(.text .text.* .gnu.linkonce.t.*)

    /*C & C++ Special Generated Code, part of main program code*/

    /*C++ Setup Code*/
    . = ALIGN(4); /*New piece*/
    KEEP(*(.init))

    . = ALIGN(4); /*New piece*/
    __preinit_array_start = .;
    KEEP (*(.preinit_array))
    __preinit_array_end = .;

    . = ALIGN(4); /*New piece*/
    __init_array_start = .;
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array))
    __init_array_end = .;

    /*C++ Constructor Code*/
    . = ALIGN(4); /*New piece*/
    KEEP (*crtbegin.o(.ctors))
    KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*crtend.o(.ctors))

    /*C++ Teardown Code*/
    . = ALIGN(4); /*New piece*/
    KEEP(*(.fini))

    . = ALIGN(4); /*New piece*/
    __fini_array_start = .;
    KEEP (*(.fini_array))
    KEEP (*(SORT(.fini_array.*)))
    __fini_array_end = .;

    /*C++ Deconstructor Code*/
    . = ALIGN(4); /*New piece*/
    KEEP (*crtbegin.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*crtend.o(.dtors))

    /*Thumb <==> ARM Code Translation Glue*/
    . = ALIGN(16); /*New Subsection*/
    *(.glue_7t) *(.glue_7)

    /*Read-Only/Constant Data, placing in a new page*/
    . = ALIGN(512); /*New Page*/
    *(.rodata .rodata* .gnu.linkonce.r.*)

    /*This is for relocating data, place it in it's own page*/
    . = ALIGN(512); /*New Page*/
    _placeRelocate = .;

    _efixed = .;
    _etext = .;
  } > rom0 /*These of course go in the main rom bank*/

  /*
    Rom 0 Custom Code

    Gameplan for .rom0 output section

    This is sort of a workarea for program-specific usage unrelated to generated
    code. It needs to go into it's own block.
  */
  .rom0 (NOLOAD):
  {
    . = ALIGN(8192); /*New block*/
    _srom0 = .;
    *(.rom0*)
    _erom0 = .;
  } > rom0

  /*
    Load-N-Lock 0-Wait State Speed

    Gameplan for .lnl output section

    LNL is placed in it's own reserved memory area of a specific size in rom0. Space is
    immensely cramped and every byte counts. No alignment will be done.
  */
  .lnl (NOLOAD):
  {
    _slnl = .;
    *(.lnl*)
    _elnl = .;
  } > lnl /*Goes into it's own specific area*/

  /*
    Rom 1 Custom Code

    Gameplan for .rom1 output section

    Rom Bank 1 is more relaxed given the entire bank is for program usage.
    This needs to be placed after the first page. The first page is reserved
    for program-specific header data and work area.
  */
  .rom1 (NOLOAD):
  {
    . = 512; /*2nd page from start*/
    _srom1 = .;
    *(.rom1*)
    _erom1 = .;
  } > rom1 /*Goes into rom bank 1*/

  /*
    QSPI Custom Code

    Gameplan for .qspi output section

    QSPI is similar to ROM1 in that it's just an area that can be used
    for custom usage or work area.
  */
  .qspi (NOLOAD):
  {
    . = ALIGN(4); /*New piece*/
    _sqspi = .;
    *(.qspi*)
    _eqspi = .;
  } > qspi /*Goes into QSPI*/

  /*
    Uninitialized Data

    Gameplan for .bss output section

    Uninitialized data goes into main RAM at the start
  */
  .bss (NOLOAD) :
  {
    . = ALIGN(4); /*New piece*/
    _sbss = . ;
    _szero = .;
    *(.bss .bss.*) /*Place BSS Data at start of RAM*/

    . = ALIGN(4); /*New piece*/
    *(COMMON) /*Place common data after*/
    _ebss = . ;
    _ezero = .;

    /*Relocate data comes after bss*/
    . = ALIGN(4); /*New piece*/
    _relocateStart = .;
  } > ram

  /*
    Relocate data

    Gameplan for .relocate output section

    This needs to be placed at rom0 in it's own defined section. It will
    be copied to the end of bss.
  */
  .relocate : AT (_placeRelocate)
  {
    . = ALIGN(4); /*New piece*/
    _srelocate = .;
    *(.data .data.*);

    . = ALIGN(4); /*New Piece*/
    *(.ramfunc .ramfunc.*);
    _erelocate = .;
  } > ram /*Place in RAM*/

  /*
    Stack data

    Gameplan for .stack output section

    Placed at end of RAM an empty area large enough for the stack
  */
  .stack (NOLOAD):
  {
    . = ALIGN(8); /*New larger piece*/
    _sstack = .; /*Begin Stack*/

    . = . + STACK_SIZE; /*Insert large blank area for stack*/

    . = ALIGN(8); /*New larger piece*/
    _estack = .; /*End stack placement*/
  } > ram

  /*
    SEEPROM Data

    Gameplan for .seeprom output section

    The SEEPROM section is like rom1 just byte-writable rather than
    block/page eraseable/writable. Unlike ROM1 however SEEPROM can start
    at the beginning.
  */
  .seeprom (NOLOAD):
  {
    . = ALIGN(4); /*New piece*/
    _seeprom = .;
    *(.seeprom*)
    _eseeprom = .;
  } > seeprom /*Goes into seeprom area*/

  /*
    Custom Backup RAM

    Gameplan for .bkupram output section

    Like ROM1 and SEEPROM, this is another potential usage area.
  */
  .bkupram (NOLOAD):
  {
    . = ALIGN(4); /*New piece*/
    _sbkupram = .;
    *(.bkupram*)
    _ebkupram = .;
  } > bkupram /*Goes into bkupram area*/

  . = ALIGN(4); /*New piece*/
  _end = . ; /*End of everything*/
}

以及ide附带的原始文件

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)

/* Memory Spaces Definitions */
MEMORY
{
  rom0     (rx)  : ORIGIN = 0x00000000, LENGTH = 0x0003F800
  lnl      (rx)  : ORIGIN = 0x0003F800, LENGTH = 0x00000800 /*Load-N-Lock 0-Wait State Caching: 2KB*/
  rom1     (rx)  : ORIGIN = 0x00040000, LENGTH = 0x00018000
  qspi     (rx)  : ORIGIN = 0x04000000, LENGTH = 0x01000000
  ram      (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
  seeprom  (rx)  : ORIGIN = 0x44000000, LENGTH = 0x00010000
  bkupram  (rwx) : ORIGIN = 0x47000000, LENGTH = 0x00002000
}

/* The stack size used by the application. NOTE: you need to adjust according to your application. */
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0xC000;

/* Section Definitions */
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(4);
        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 */
    } > rom0

    /* .ARM.exidx is sorted, so has to go in its own output section.  */
    PROVIDE_HIDDEN (__exidx_start = .);
    .ARM.exidx :
    {
      *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > rom0
    PROVIDE_HIDDEN (__exidx_end = .);

    . = ALIGN(4);
    _etext = .;

    .lnl :
    {
      /*. = ALIGN(4);*/
        __lnl_start__ = .;
        *(.lnl*)
        __lnl_end__ = .;
    } > lnl

    .rom1 (NOLOAD):
    {
        . = ALIGN(8);
        _rom1 = .;
        *(.rom1 .rom1.*);
        . = ALIGN(8);
        _rom1 = .;
    } > rom1

    .seeprom (NOLOAD):
    {
        . = ALIGN(8);
        _seeprom = .;
        *(.seeprom .seeprom.*);
        . = ALIGN(8);
        _eseeprom = .;
    } > seeprom

    .relocate : AT (_etext)
    {
        . = ALIGN(4);
        _srelocate = .;
        *(.ramfunc .ramfunc.*);
        *(.data .data.*);
        . = ALIGN(4);
        _erelocate = .;
    } > ram

    .bkupram (NOLOAD):
    {
        . = ALIGN(8);
        _sbkupram = .;
        *(.bkupram .bkupram.*);
        . = ALIGN(8);
        _ebkupram = .;
    } > bkupram

    .qspi (NOLOAD):
    {
        . = ALIGN(8);
        _sqspi = .;
        *(.qspi .qspi.*);
        . = ALIGN(8);
        _eqspi = .;
    } > qspi

    /* .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 = . ;
}

1 个答案:

答案 0 :(得分:0)

经过大量的试验,试验和错误后,结果发现ram部分似乎必须按照以下顺序依次“重定位”,“ bss”然后“ stack”。

我试图做的是将“ bss”放在“ relocate”上方,这导致一切无法正常工作。所以这就是答案,但是谁能解释为什么“ bss”必须高于“ relocate”。我这样做是因为我希望将静态成员放在顶部,并且我知道重定位是针对非静态成员的。