【问题标题】:use specific memory section memory to link a variable使用特定的内存段内存来链接变量
【发布时间】:2014-07-30 14:07:08
【问题描述】:

我在设置 gcc 的 section 属性以定义变量应驻留在特定内存段而不是默认值时遇到问题。

我正在使用 arm cortex m3 LPC1759。我从 LPCXpresso IDE 获得了链接文件,但我不使用它,我有自己的 makefile。链接文件是:

通用链接文件

INCLUDE "./link/LPCmem.ld" /* see below */

ENTRY(ResetISR)

SECTIONS
{
    /* MAIN TEXT SECTION */    
    .text : ALIGN(4)
    {
        FILL(0xff)
        __vectors_start__ = ABSOLUTE(.) ;
        KEEP(*(.isr_vector))
        
        /* Global Section Table */
        . = ALIGN(4) ;
        __section_table_start = .;
        __data_section_table = .;
        LONG(LOADADDR(.data));
        LONG(    ADDR(.data));
        LONG(  SIZEOF(.data));
        LONG(LOADADDR(.data_RAM2));
        LONG(    ADDR(.data_RAM2));
        LONG(  SIZEOF(.data_RAM2));
        __data_section_table_end = .;
        __bss_section_table = .;
        LONG(    ADDR(.bss));
        LONG(  SIZEOF(.bss));
        LONG(    ADDR(.bss_RAM2));
        LONG(  SIZEOF(.bss_RAM2));
        __bss_section_table_end = .;
        __section_table_end = . ;
        /* End of Global Section Table */
        

        *(.after_vectors*)
    } >FLASH
    
    .text : ALIGN(4)    
    {
         *(.text*)
        *(.rodata .rodata.* .constdata .constdata.*)
        . = ALIGN(4);
        
    } > FLASH

    /*
     * for exception handling/unwind - some Newlib functions (in common
     * with C++ and STDC++) use this. 
     */
    .ARM.extab : ALIGN(4)
    {
        *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > FLASH
    __exidx_start = .;
    
    .ARM.exidx : ALIGN(4)
    {
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > FLASH
    __exidx_end = .;
    
    _etext = .;
    
    /* DATA section for SRAM0 */
    .data_RAM2 : ALIGN(4)
    {
       FILL(0xff)
       *(.ramfunc.$RAM2)
       *(.ramfunc.$SRAM0)
        *(.data.$RAM2*)
        *(.data.$SRAM0*)
       . = ALIGN(4) ;
    } > SRAM0 AT>FLASH
    
    /* MAIN DATA SECTION */
    .uninit_RESERVED : ALIGN(4)
    {
        KEEP(*(.bss.$RESERVED*))
        . = ALIGN(4) ;
        _end_uninit_RESERVED = .;
    } > SRAM
    
    /* Main DATA section (SRAM) */
    .data : ALIGN(4)
    {
       FILL(0xff)
       _data = . ;
       *(vtable)
       *(.ramfunc*)
       *(.data*)
       . = ALIGN(4) ;
       _edata = . ;
    } > SRAM AT>FLASH

    /* BSS section for SRAM0 */
    .bss_RAM2 : ALIGN(4)
    {
        *(.bss.$RAM2*)
        *(.bss.$SRAM0*)
       . = ALIGN(4) ;
    } > SRAM0

    /* MAIN BSS SECTION */
    .bss : ALIGN(4)
    {
        _bss = .;
        *(.bss*)
        *(COMMON)
        . = ALIGN(4) ;
        _ebss = .;
        PROVIDE(end = .);
    } > SRAM
        
    /* NOINIT section for SRAM0 */
    .noinit_RAM2 (NOLOAD) : ALIGN(4)
    {
        *(.noinit.$RAM2*)
        *(.noinit.$SRAM0*)
       . = ALIGN(4) ;
    } > SRAM0 
    
    /* DEFAULT NOINIT SECTION */
    .noinit (NOLOAD): ALIGN(4)
    {
        _noinit = .;
        *(.noinit*) 
         . = ALIGN(4) ;
        _end_noinit = .;
    } > SRAM
        
    PROVIDE(_pvHeapStart = .);
    PROVIDE(_vStackTop = __top_SRAM - 0);
}

内存定义文件

/* Define each memory region */
MEMORY
{
  FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x80000           /* 512K bytes */
  SRAM (rwx) : ORIGIN = 0x10000000, LENGTH = 0x8000     /* 32K bytes */
  SRAM0 (rwx) : ORIGIN = 0x2007c000, LENGTH = 0x8000    /* 32K bytes */
}

/* Define a symbol for the top of each memory region */
__top_FLASH = 0x0 + 0x80000;
__top_SRAM = 0x10000000 + 0x8000;
__top_SRAM0 = 0x2007c000 + 0x8000;

上面是上一个文件包含的LPCmem.ld文件。

我强制将 freertos 堆变量放在自定义部分中,如下所示:

static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ]
        __attribute__((section(".data_RAM2")));

对象文件的链接没有错误,但是变量没有放在正确的内存位置,我如何用 nm 命令检查:

...
10000028 d ucHeap
10002028 d uxCriticalNesting
...

我尝试将部分更改为其他不存在的部分,只是为了检查链接器是否验证了名称,显然它没有。

【问题讨论】:

    标签: gcc linker arm


    【解决方案1】:

    TL;DR - 您只是缺少美元符号

    您将部分命名错误。链接器文件的相关部分是,

    /* DATA section for SRAM0 */
    .data_RAM2 : ALIGN(4)
    {
       FILL(0xff)
       *(.ramfunc.$RAM2)
       *(.ramfunc.$SRAM0)
        *(.data.$RAM2*)
        *(.data.$SRAM0*)
        /* *(.data_RAM2);   You need this, without a code change, */
        /*                  but it will still match data. */
       . = ALIGN(4) ;
    } > SRAM0 AT>FLASH
    
    /* Main DATA section (SRAM) */
    .data : ALIGN(4)
    {
       FILL(0xff)
       _data = . ;
       *(vtable)
       *(.ramfunc*)
       *(.data*)     /* Otherwise, this matches your section. */
       . = ALIGN(4) ;
       _edata = . ;
    } > SRAM AT>FLASH
    

    目前,您在.data_RAM2 中有ucHeap。链接器文件使用了.data.$RAM2*,但这不匹配。 * 是一个通配符。因此,*(.data*) 将与您当前拥有的代码匹配。不知道你有没有问题,

     static unsigned char ucHeap[ configTOTAL_HEAP_SIZE ] 
        __attribute__((section(".data_$RAM2")));
    

    这似乎适用于我的 gcc 版本。您只是缺少美元符号。 请参阅gnu ld documentation,特别是input sections。形式是, 存档:目标文件(输入部分 ...);如果您愿意,您可以在其中使用通配符并且可以省略 archive:。通配符是一种有限的 reg-ex 形式。如果您愿意,您可以提供许多输入部分;例如*(.text* .rodata*) 会将来自同一对象的.text.rodata 放在一起。其中,*(.text*); *(.rodata*); 会将所有目标文件中的所有 .text 放在一起,然后放置 .rodata

    【讨论】:

    • 谢谢,使用__attribute__((section(".data.$RAM2"))) 可以正常工作。现在,可以在不更改代码的情况下使用 RAM2:我的意思是,不使用 attribute 部分,链接器能够自动解决这个问题?
    • 您可以使用链接描述文件将所有.data 放在一个特定的目标文件中。如果您只想将源/对象/编译单元中的特定变量放入一个部分,那么attribute 是正确的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-26
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多