在编译期间将数据写入特定地址

时间:2014-11-18 09:58:28

标签: c gcc linker embedded microcontroller

我希望标题足够描述。所以这就是我想要做的以及我玩过的东西。

等等,首先,这是一个嵌入式应用程序。 Atmel SAM4L微控制器,使用Atmel Studio IDE和GCC编译器/链接器。

是的,我正在编写一个引导加载程序,但是想将引导加载程序版本保存到程序存储器中,直到引导加载程序的已分配空间的末尾(让我们说是0x3FF0)。这样,应用程序还可以通过查看特定地址来检查引导加载程序版本。 此时我正忙着为应用程序更新引导程序本身的实用程序,但我不希望应用程序或引导加载程序使用命令或代码在0x3FF0更新版本,我希望它作为.bin / .hex文件,所以当我启动引导加载程序时,版本会随之闪烁。 所以目前我有一个#define用于bootloader类型,主要版本和次要版本,它们都在项目中的globals.h文件中。基本上我只想在编译时将这3个字节写入0x3FF0。

据我了解,我可以通过链接器获取相当多的技巧,但直到昨天才使用链接器脚本,并且已经能够用它做一些事情,但不是我想要的然而。 该项目还创建了一个非常强大的链接器脚本,所以我也有点警惕在哪里跳转并转储我的三个字节。我知道你不允许移回地址指针。

这是项目生成的链接描述文件

/**
 * \file
 *
 * \brief Flash Linker script for SAM.
 *
 * Copyright (c) 2013 Atmel Corporation. All rights reserved.
 *
 * \asf_license_start
 *
 * \page License
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * 3. The name of Atmel may not be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * 4. This software may only be redistributed and used in connection with an
 *    Atmel microcontroller product.
 *
 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * \asf_license_stop
 *
 */

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

/*
 * NOTE: to keep binary compatibility with SAM4L4 device on SAM4L Xplained Pro,
 * we use SAM4L4 memory space here instead SAM4L8. You may change it if you are
 * using SAM4L8 device.
 */
/* Memory Spaces Definitions */
MEMORY
{
  rom (rx)  : ORIGIN = 0x00000000, LENGTH = 0x00040000 /* flash, 256K */
  ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 /* sram, 32K */
  /* rom (rx)  : ORIGIN = 0x00000000, LENGTH = 0x00080000 */ /* flash, 512K */
  /* ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00010000 */ /* sram, 64K */
}

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

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

据我了解,.ARM.exidx是放在ROM中的最后一个部分,而.relocate将根据区域和MEMORY声明放在RAM中(从0x20000000开始),所以我的三个字节应介于两者之间那两个。

然后,至于如何,我已经尝试了这个例子 http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0803a/BABDJCAA.html 但是我没有看到它反映在我的.bin或.hex文件中。我猜测它只分配内存,并没有实际加载任何东西,因为它只是一个变量。 我也发现过这样的事情 gcc linker description file force symbol to be at specific address ,但我不是因为它不是真正的代码我试图加载到特定的地址,我不知道如何使用这种方法。

我仍在玩操纵链接器脚本并看到我能做到的事情,但是我们将非常感谢任何帮助。

如果需要任何进一步的信息,请询问,我会提供。 (或者,如果我需要更改标题或标签以获得更好的命中率。)

2 个答案:

答案 0 :(得分:1)

事物的地址在链接器阶段确定,对于链接器,一切都只是符号。你的gcc linker description file force symbol to be at specific address  举例说明equaly适用于数据的函数。定义您的版本并将其放在C代码中的单独“版本”部分中。然后链接器可以将该部分放在某处。

现在困难的部分是将它带到rom的 end ,这意味着指定一个足够低的起始地址,该部分将在rom结尾处结束。使其固定大小(3字节)使这更简单。看看如何在链接描述文件中定义 ram_end 。对 rom_version_start 执行相同操作,但使用rom而不是ram并使用它来设置“版本”部分的开头使用'。 = rom_version_start ;'

答案 1 :(得分:1)

所以,对于那些寻找答案的人来说,这是我所做的更详细的例子。

在main.c中我定义了一个原型,首先让这个例子正常工作,之后我尝试了一个数组:

void jver(void) __attribute__((section(".jver")));

static uint8_t jvar[10] __attribute__((section(".jvar"))) = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};

void jver(void)
{
    //static uint8_t sbuf[10] = {0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};
    jamba_TxBuff(jvar, 10);

}

然后,在链接描述文件中,在最后一个部分放在'rom'区域后,我在'rom'区域添加我要添加的东西:

_jverstart = 0x3FF0;
.jver : AT (_jverstart)
{
    *(.jver)
} > rom


_jvarstart = 0x4100;
.jvar : AT (_jvarstart)
{
    *(.jvar)
} > rom

请注意,我必须调整示例,只是使指针等于值不起作用。我必须创建一个变量并使用AT函数。在我的测试过程中,我添加了“rom”区域,如果我将其删除,则没有检查它是否仍然有效。

编译时,我得到以下结果:

:103FF00008B502480A21024B984708BDA02D0000D1
:04400000310D00007E
:0C410000303132333435363738390000A6
:0400000300001A657A
:00000001FF

从最后一个代码到0x3FF0,.bin文件填充0x00,然后是我的jver(void)函数的代码的几个字节(这可能只是对jamba_TxBuff函数的调用),然后填充0x00的所有方式到0x4100,其中“0123456789”。繁荣!!!我现在要添加的是链接器脚本中的'FILL'函数,用0xFF而不是0x00填充。

再次感谢您的参考和建议。