gpt4 book ai didi

c++ - 将数组写入 .hex 文件中的特定闪存位置

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:44:58 24 4
gpt4 key购买 nike

对于我在 Atmel SAM4E16C 上的嵌入式应用程序,我需要在 .hex 文件的末尾放置一个包含固件信息的数组。我正在使用带有 GCC 的 Atmel Studio 7。

我已经为 Atmega168PB 完成了此操作,但不知何故它不适用于该项目。

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

/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00420000, LENGTH = 0x000E0000 /* changed to leave space for 128KB Bootloader -> was 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;
/* Firmware Info - 8 Bytes long at the end of ROM */
__FWInfo_start__ = ORIGIN(rom) + LENGTH(rom) - 8;
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 = . ;


/* 8 Byte Firmware Info Section */

.FWInfo : AT (__FWInfo_start__)
{
*(.FWInfo)
} > rom
}

这是我正在使用的链接描述文件。我添加了 __FWInfo_start__ 和 .FWInfo 部分。

在我的应用程序中,我尝试使用属性部分 .FWInfo 定义固件信息 block ,但我无法在我的 .hex 文件中找到数据。

#define SIZE_OF_FWINFO  8
const uint8_t nFirmwareInfoBlock[SIZE_OF_FWINFO] __attribute__((section(".FWInfo"))) = {
0xff, // reserved for future
0xff, // reserved for future
DEVICE_TYPE, // DeviceType
BUILD_NR, // BuildNr of Firmware
VERSION_MINOR, // VersionMinor of Firmware
VERSION_MAJOR, // VersionMajor of Firmware
0xFF, // Checksum
0xFF // Checksum
};

我希望有人能帮助我解决为什么这行不通的问题。提前致谢。

编辑:这是 .map 文件中的条目:

.data          0x00000000        0x0 src/main.o
.FWInfo 0x00000000 0x8 src/main.o
.debug_macro 0x00000000 0x8b0 src/main.o

和..

 *fill*         0x200133b0     0x3000 
0x200163b0 . = ALIGN (0x8)
0x200163b0 _estack = .
0x200163b0 . = ALIGN (0x4)
0x200163b0 _end = .

.FWInfo
*(.FWInfo)
OUTPUT(Dali4Net.elf elf32-littlearm)

据我从第二个 block 的上下文中读取,应该在 .FWInfo 或之后写入一个地址?

最佳答案

来自 GCC variable attribute documentation :

used

This attribute, attached to a variable with static storage, means that the variable must be emitted even if it appears that the variable is not referenced.

因此,为了防止链接器删除未使用的数据,请使用:

const uint8_t nFirmwareInfoBlock[SIZE_OF_FWINFO]
__attribute__((used,section(".FWInfo"))) =
{ ... } ;

另一种但可能不太吸引人的解决方案是声明数组 volatile 然后执行虚拟读取即:

const uint8_t nFirmwareInfoBlock[SIZE_OF_FWINFO]
__attribute__((section(".FWInfo"))) =
{ ... } ;

int main()
{
uint8_t dummy = nFirmwareInfoBlock[0] ;
...
}

第三种方法是完全避免工具链依赖并使用优秀但有些神秘的 SRecord作为 构建后 操作将数据直接修补到 hex 文件的实用程序。这具有独立于工具链的优势,但您可能需要一个步骤来生成要修补的数据,但为此编写一个生成器可能很简单。

关于c++ - 将数组写入 .hex 文件中的特定闪存位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40768934/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com