找到RAM变量的ROM地址

时间:2018-07-12 14:06:27

标签: c linker arm embedded

我想知道是否有一种方法可以获取用于种子RAM变量初始值的ROM地址?给定一条语句static uint32_t foo = 0x12345678;,初始值0x12345678作为ROM存在于某个地方,用作&foo的初始值。在某个时间点,我希望能够将foo的值重置为其初始状态。

我可以创建第二个变量const static uint32_t initial_foo = 0x12345678;来使用,但这将使存储此用例的变量所需的ROM数据空间增加一倍。

与RAM开头的偏移量&foo(或更具体地说,&_srelocate,请参见下面的链接描述文件)可以可靠地与ROM空间中的符号之一相关联吗?

以下是ARM / GNU C链接器v 6.3.1脚本的选定部分。

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

/* Memory Spaces Definitions */
MEMORY
{
  rom (rx)  : ORIGIN = 0x00400000, LENGTH = 0x00100000
  ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
}

/* The stack size used by the application. NOTE: you need to adjust according to your application. */
__stack_size__ = DEFINED(__stack_size__) ? __stack_size__ : 0x3000;
__ram_end__ = ORIGIN(ram) + LENGTH(ram) - 4;

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(0x4);
        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 */
    } > rom

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

    . = ALIGN(4);
    _etext = .;

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

    /* .bss and stack sections removed */

    . = ALIGN(4);
    _end = . ;
}

1 个答案:

答案 0 :(得分:5)

只需拥有一个变量type foo = value;并确保将其分配到ROM中即可,而不是拥有一个RAM变量const type foo = value;(如果变量具有静态存储持续时间,则可能是这种情况)。然后根据需要手动将其复制到RAM。这样,该值仅在ROM中存储一次。 ROM变量的初始化程序未单独存储。

那么您将不会浪费任何内存,也不必担心以某种方式在.rodata中搜索初始值,这是相当可疑的做法。