GNU LD链接器-无法在地址的Flash中获取变量

时间:2018-08-07 05:01:22

标签: c++ c linker ld stm32

我正在使用STM32F072,需要将结构添加到Flash中的特定位置。但是当地址为0x0801F800时,该结构不会被编程为闪烁。

我在命名空间范围内声明一个实例:

const Memory ConfigData __attribute__ ((section (".ConfigData"))) __attribute__ ((__used__)){ 2u, 1.0f, 0.1f, 1.0f, 12.0f, 2.5f };

要将以上内容插入特定的存储位置,我正在使用:

_ConfigStart = 0x0801F800;
.ConfigData _ConfigStart :
{
    KEEP(*(.ConfigData));
} > FLASH

上面的代码不起作用,当_ConfigStart地址为0x0800F800时,它将起作用。但是我需要将其放在Flash(0x0801F800)的最后一页中,这样才不是可行的选择。

我可以使用STLINK-V2手动编程所需的页面,也可以使用自己的Flash库来执行此操作,但我需要链接程序将其包含在内。

目前没有链接器错误。

链接器文件: mem.ld:

MEMORY
{
  RAM (xrw)     : ORIGIN = 0x20000000, LENGTH = 16K
  CCMRAM (xrw)  : ORIGIN = 0x00000000, LENGTH = 0
  FLASH (rx)    : ORIGIN = 0x08000000, LENGTH = 128K
  FLASHB1 (rx)  : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  MEMORY_ARRAY (xrw)  : ORIGIN = 0x00000000, LENGTH = 0
}

sections.ld (为简洁起见,删除了某些内容):

__stack = ORIGIN(RAM) + LENGTH(RAM);
_estack = __stack;  /* STM specific definition */

/*
 * Default stack sizes.
 * These are used by the startup in order to allocate stacks 
 * for the different modes.
 */
__Main_Stack_Size = 1024 ;

PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;
__Main_Stack_Limit = __stack  - __Main_Stack_Size ;

PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;
_Minimum_Stack_Size = 256 ;


PROVIDE ( _Heap_Begin = _end_noinit ) ;
PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ;
ENTRY(_start)


SECTIONS
{
    .isr_vector : ALIGN(4)
    {
        FILL(0xFF)

        __vectors_start = ABSOLUTE(.) ;
        __vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */
        KEEP(*(.isr_vector))        /* Interrupt vectors */

        KEEP(*(.cfmconfig))         /* Freescale configuration words */   

        *(.after_vectors .after_vectors.*)  /* Startup code and ISR */

    } >FLASH

    .inits : ALIGN(4)
    {
        /* 
         * Memory regions initialisation arrays.
         *
         * Thee are two kinds of arrays for each RAM region, one for 
         * data and one for bss. Each is iterrated at startup and the   
         * region initialisation is performed.
         * 
         * The data array includes:
         * - from (LOADADDR())
         * - region_begin (ADDR())
         * - region_end (ADDR()+SIZEOF())
         *
         * The bss array includes:
         * - region_begin (ADDR())
         * - region_end (ADDR()+SIZEOF())
         *
         * WARNING: It is mandatory that the regions are word aligned, 
         * since the initialisation code works only on words.
         */

        __data_regions_array_start = .;

        LONG(LOADADDR(.data));
        LONG(ADDR(.data));
        LONG(ADDR(.data)+SIZEOF(.data));

        LONG(LOADADDR(.data_CCMRAM));
        LONG(ADDR(.data_CCMRAM));
        LONG(ADDR(.data_CCMRAM)+SIZEOF(.data_CCMRAM));

        __data_regions_array_end = .;

        __bss_regions_array_start = .;

        LONG(ADDR(.bss));
        LONG(ADDR(.bss)+SIZEOF(.bss));

        LONG(ADDR(.bss_CCMRAM));
        LONG(ADDR(.bss_CCMRAM)+SIZEOF(.bss_CCMRAM));

        __bss_regions_array_end = .;

        /* End of memory regions initialisation arrays. */

        /*
         * These are the old initialisation sections, intended to contain
         * naked code, with the prologue/epilogue added by crti.o/crtn.o
         * when linking with startup files. The standalone startup code
         * currently does not run these, better use the init arrays below.
         */
        KEEP(*(.init))
        KEEP(*(.fini))

        . = ALIGN(4);

        /*
         * The preinit code, i.e. an array of pointers to initialisation 
         * functions to be performed before constructors.
         */
        PROVIDE_HIDDEN (__preinit_array_start = .);

        /*
         * Used to run the SystemInit() before anything else.
         */
        KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))

        /* 
         * Used for other platform inits.
         */
        KEEP(*(.preinit_array_platform .preinit_array_platform.*))

        /*
         * The application inits. If you need to enforce some order in 
         * execution, create new sections, as before.
         */
        KEEP(*(.preinit_array .preinit_array.*))

        PROVIDE_HIDDEN (__preinit_array_end = .);

        . = ALIGN(4);

        /*
         * The init code, i.e. an array of pointers to static constructors.
         */
        PROVIDE_HIDDEN (__init_array_start = .);
        KEEP(*(SORT(.init_array.*)))
        KEEP(*(.init_array))
        PROVIDE_HIDDEN (__init_array_end = .);

        . = ALIGN(4);

        /*
         * The fini code, i.e. an array of pointers to static destructors.
         */
        PROVIDE_HIDDEN (__fini_array_start = .);
        KEEP(*(SORT(.fini_array.*)))
        KEEP(*(.fini_array))
        PROVIDE_HIDDEN (__fini_array_end = .);

    } >FLASH

    .flashtext : ALIGN(4)
    {
        *(.flashtext .flashtext.*)  /* Startup code */
    } >FLASH

    .text : ALIGN(4)
    {
        *(.text .text.*)            /* all remaining code */

        /* read-only data (constants) */
        *(.rodata .rodata.* .constdata .constdata.*)        

        *(vtable)                   /* C++ virtual tables */

        KEEP(*(.eh_frame*))

        *(.glue_7)
        *(.glue_7t)

    } >FLASH


    /* ARM magic sections */
    .ARM.extab : ALIGN(4)
    {
       *(.ARM.extab* .gnu.linkonce.armextab.*)
    } > FLASH


    . = ALIGN(4);
    __exidx_start = .;      
    .ARM.exidx : ALIGN(4)
    {
       *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } > FLASH

    __exidx_end = .;

    . = ALIGN(4);
    _etext = .;
    __etext = .;

    .data_CCMRAM : ALIGN(4)
    {
       FILL(0xFF)
       *(.data.CCMRAM .data.CCMRAM.*)
       . = ALIGN(4) ;
    } > CCMRAM AT>FLASH

    _sidata = LOADADDR(.data);

    .data : ALIGN(4)
    {
        FILL(0xFF)
        /* This is used by the startup code to initialise the .data section */
        _sdata = . ;            /* STM specific definition */
        __data_start__ = . ;
        *(.data_begin .data_begin.*)

        *(.data .data.*)

        *(.data_end .data_end.*)
        . = ALIGN(4);

        /* This is used by the startup code to initialise the .data section */
        _edata = . ;            /* STM specific definition */
        __data_end__ = . ;

    } >RAM AT>FLASH

    _ConfigStart = 0x0801F800;
    .ConfigData _ConfigStart :
    {
        KEEP(*(.ConfigData));
    } > FLASH

    .bss (NOLOAD) : ALIGN(4)
    {
        __bss_start__ = .;      /* standard newlib definition */
        _sbss = .;              /* STM specific definition */
        *(.bss_begin .bss_begin.*)

        *(.bss .bss.*)
        *(COMMON)

        *(.bss_end .bss_end.*)
        . = ALIGN(4);
        __bss_end__ = .;        /* standard newlib definition */
        _ebss = . ;             /* STM specific definition */
    } >RAM

    /* Stabs debugging sections.  */
    .stab          0 : { *(.stab) }
    .stabstr       0 : { *(.stabstr) }
    .stab.excl     0 : { *(.stab.excl) }
    .stab.exclstr  0 : { *(.stab.exclstr) }
    .stab.index    0 : { *(.stab.index) }
    .stab.indexstr 0 : { *(.stab.indexstr) }
    .comment       0 : { *(.comment) }
    /*
     * DWARF debug sections.
     * Symbols in the DWARF debugging sections are relative to the beginning
     * of the section so we begin them at 0.  
     */
    /* DWARF 1 */
    .debug          0 : { *(.debug) }
    .line           0 : { *(.line) }
    /* GNU DWARF 1 extensions */
    .debug_srcinfo  0 : { *(.debug_srcinfo) }
    .debug_sfnames  0 : { *(.debug_sfnames) }
    /* DWARF 1.1 and DWARF 2 */
    .debug_aranges  0 : { *(.debug_aranges) }
    .debug_pubnames 0 : { *(.debug_pubnames) }
    /* DWARF 2 */
    .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
    .debug_abbrev   0 : { *(.debug_abbrev) }
    .debug_line     0 : { *(.debug_line) }
    .debug_frame    0 : { *(.debug_frame) }
    .debug_str      0 : { *(.debug_str) }
    .debug_loc      0 : { *(.debug_loc) }
    .debug_macinfo  0 : { *(.debug_macinfo) }
    /* SGI/MIPS DWARF 2 extensions */
    .debug_weaknames 0 : { *(.debug_weaknames) }
    .debug_funcnames 0 : { *(.debug_funcnames) }
    .debug_typenames 0 : { *(.debug_typenames) }
    .debug_varnames  0 : { *(.debug_varnames) }    
}

ConfigData出现在.map文件中,地址为0x0800f800:

 .igot.plt      0x20000078        0x0 c:/program files (x86)/gnu tools arm embedded/7 2017-q4-major/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libstdc++_nano.a(new_op.o)

.ConfigData     0x0800f800       0x18
 *(.ConfigData)
 .ConfigData    0x0800f800       0x18 C:\Users\David\AppData\Local\Temp\cc10vcUe.ltrans0.ltrans.o

.rel.dyn        0x0800f818        0x0

当分配给0x0801f800时似乎会变大:

.igot.plt       0x20000078        0x0 load address 0x080090c8
 .igot.plt      0x20000078        0x0 c:/program files (x86)/gnu tools arm embedded/7 2017-q4-major/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libstdc++_nano.a(new_op.o)

.ConfigData     0x0801f800       0x18
 *(.ConfigData)
 .ConfigData    0x0801f800       0x18 C:\Users\David\AppData\Local\Temp\ccIUhOBG.ltrans0.ltrans.o

.rel.dyn        0x0801f818        0x0
 .rel.iplt      0x0801f818        0x0 c:/program files (x86)/gnu tools arm embedded/7 2017-q4-major/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v6-m\libstdc++_nano.a(new_op.o)

我也尝试过将其放入自己的块中:

.ConfigData :
    {
        KEEP(*(.ConfigData));
    } > CONFIG

使用mem.ld:

MEMORY
{
  RAM   (xrw)   : ORIGIN = 0x20000000,      LENGTH = 16K
  FLASH (rx)    : ORIGIN = 0x08000000,      LENGTH = 128K - 0x800
  CONFIG(R)     : ORIGIN = ORIGIN(FLASH) +  LENGTH(FLASH),  LENGTH = 0x800
}

没有运气,真的迷失了这个。

编辑

这个问题实际上是对该微处理器和编程器的一个奇怪的怪癖。编程器拒绝编程超出闪存大小寄存器指定的闪存范围,但闪存扩展到128K(而非64K)。我已经写了超出地址范围的各种地址,没有任何问题,我之所以认为可以这样做是因为STLINK Utility允许我查看该内存范围。

此问题专门与STM32F072C8有关,我不是唯一遇到这种混乱的人:

0 个答案:

没有答案