代码之家  ›  专栏  ›  技术社区  ›  Guillaume Petitjean

GNU LD链接器脚本-堆栈放置

  •  0
  • Guillaume Petitjean  · 技术社区  · 6 年前

    这是我的stm32l476链接器脚本:

    /* Generate a link error if heap and stack don't fit into RAM */
    __heap_size = 0x200;;      /* required amount of heap  */
    __stack_size = 0x800;; /* required amount of stack */
    
    /* Specify the memory areas */
    MEMORY
    {
        FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
        RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 96K
    }
    
    /* Define output sections */
    SECTIONS
    {
      /* The startup code goes first into FLASH */
      .default_exceptions :
      {
        . = ALIGN(8);
        KEEP(*(.default_exceptions)) /* Startup code */
        . = ALIGN(8);
      } >FLASH
    
      /* The program code and other data goes into FLASH */
      .text :
      {
        . = ALIGN(8);
        *(.text)           /* .text sections (code) */
        *(.text*)          /* .text* sections (code) */
        *(.glue_7)         /* glue arm to thumb code */
        *(.glue_7t)        /* glue thumb to arm code */
        *(.eh_frame)
    
        KEEP (*(.init))
        KEEP (*(.fini))
    
        . = ALIGN(8);
        _etext = .;        /* define a global symbols at end of code */
      } >FLASH
    
      /* Constant data goes into FLASH */
      .rodata :
      {
        . = ALIGN(8);
        *(.rodata)         /* .rodata sections (constants, strings, etc.) */
        *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
        . = ALIGN(8);
      } >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
    
      /* The startup code goes first into FLASH */
      .exceptions :
      {
        . = ALIGN(8);
        KEEP(*(.exceptions)) /* RAM vector table */
        . = ALIGN(8);
      } >RAM
    
      /* used by the startup to initialize data */
      _sidata = LOADADDR(.data);
    
      /* Initialized data sections goes into RAM, load LMA copy after code */
      .data :
      {
        . = ALIGN(8);
        _sdata = .;        /* create a global symbol at data start */
        *(.data)           /* .data sections */
        *(.data*)          /* .data* sections */
    
        . = ALIGN(8);
        _edata = .;        /* define a global symbol at data end */
      } >RAM AT> FLASH
    
    
      /* Uninitialized data section */
      . = ALIGN(4);
      .bss :
      {
        /* This is used by the startup in order to initialize the .bss secion */
        _sbss = .;         /* define a global symbol at bss start */
        *(.bss)
        *(.bss*)
        *(COMMON)
    
        . = ALIGN(4);
        _ebss = .;         /* define a global symbol at bss end */
      } >RAM
    
      /* User_heap_stack section, used to check that there is enough RAM left */
      .heap :
      {
        . = ALIGN(4);
        PROVIDE ( end = . );
        _sheap = .;
        . = . + __heap_size;
        . = ALIGN(4);
        _eheap = .;
      } >RAM
    
      .stack :
      {
        . = ALIGN(4);
        _estack = .;
        . = . + __stack_size;
        . = ALIGN(4);
        _sstack = .;
      } >RAM
    
      .ARM.attributes 0 : { *(.ARM.attributes) }
    }
    

    对应的映射文件是:

    .stack          0x20002844      0x800 load address 0x0801cc68
                    0x20002844                . = ALIGN (0x4)
                    0x20002844                _estack = .
                    0x20003044                . = (. + __stack_size)
     *fill*         0x20002844      0x800 
                    0x20003044                . = ALIGN (0x4)
                    0x20003044                _sstack = .
    

    我想修改它,以便堆栈位于RAM的末尾。 我尝试了几种方法(包括 here 但没有人在工作。即使放置硬编码地址也会返回一个错误(该芯片上的RAM会高达0x20018000,因此应该适合):

         .stack :
      {
        . = 0x20001000;
        _estack = .;
        . = . + __stack_size;
        . = ALIGN(4);
        _sstack = .;
      } >RAM
    

    错误是:

    20:01:46 **** Build of configuration Debug for project CardioNexion ****
    make app=unit_test board=nucleo-l476rg V=1 all 
    c:/program files (x86)/atollic/truestudio for stm32 9.0.0/armtools/bin/../lib/gcc/arm-atollic-eabi/6.3.1/../../../../arm-atollic-eabi/bin/ld.exe: region `RAM' overflowed by 536789060 bytes
    collect2.exe: error: ld returned 1 exit status
    make: *** [link] Error 1
    
    20:01:50 Build Finished (took 4s.3ms)
    

    你知道是什么引起了这个问题吗?怎么办?(将堆栈放在RAM的末端)。

    2 回复  |  直到 6 年前
        1
  •  3
  •   0___________    6 年前

    这种“传统”的方式不利于裸体的发展。

    最好将堆栈放在RAM的开头。不存在无声变量覆盖的危险,堆栈溢出将生成异常-其例程可以采取适当的操作(例如将设备切换到“安全”模式、重新启动、紧急停止受控机器等)。

        2
  •  4
  •   vlk    6 年前

    如果你想把堆栈放在ram的上面,你可以在链接器脚本中使用简单的算法,如下所示(它被简化了):

    MEMORY {
        FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K
        RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 96K
    }
    
    SECTIONS {
        __stacktop = ORIGIN(RAM) + LENGTH(RAM);
    
        . = ORIGIN(FLASH);
        .text : {
            KEEP(*(.stack))
            KEEP(*(.vectors))
            KEEP(*(.text))
            . = ALIGN(4);
            KEEP(*(.rodata))
            . = ALIGN(4);
        } >FLASH
    
        .data ALIGN(4) : {
            __data_start = .;
            *(.data)
            . = ALIGN(4);
            __data_end = .;
        } >RAM AT >FLASH
    
        .bss ALIGN(4) (NOLOAD) : {
            __bss_start = .;
            *(.bss)
            . = ALIGN(4);
            __bss_end = .;
        } >RAM
    
        . = ALIGN(4);
        __heap_start = .;
    }
    

    重要的是 KEEP(*(.stack)) 在flash开始时,然后在代码中输入 __stacktop 在本节中,如下所示:

    启动文件之一:

    // top of stack
    extern unsigned __stacktop;
    
    // initial stack pointer is first address of program
    __attribute__((section(".stack"), used)) unsigned *__stack_init = &__stacktop;
    

    所有未使用的RAM将从一侧用于堆,从另一侧用于堆栈。

    简单完整的示例如下: https://github.com/cortexm/baremetal