首页 > 解决方案 > 这两个链接描述文件部分有什么区别?

问题描述

我有一个涉及 .firmware_header 部分的 STM32 项目,该部分限制了我的应用程序映像的末尾。我正在尝试重新定位 .data 部分,以便它出现在 .firmware_header 部分之前,但由于某种原因,我在这样做时遇到了很多困难。

以下工作,但破坏了我用来签署图像的脚本,因为它不知道它需要在校验和计算中包含 .data 部分(LMA 在 RAM 中)。

  _sidata = .;
  .data_x : AT(_sidata) /* LMA address is _sidata (in FLASH) */
  {
    . = ALIGN(4);
    _sdata = .; /* data section VMA address */
    *(.data*)
    . = ALIGN(4);
    _edata = .;
  } > SRAM

  .firmware_header (_sidata + SIZEOF(.data_x)):
  {
    . = ALIGN(4);
    KEEP(*(.firmware_header))
    . = ALIGN(4);
  } > FLASH

这不起作用。即使所有地址(sidata、sdata、edata)都正确并且映像启动,但初始化数据存在问题,并且映像通常在开始运行后由于明显的原因硬失败。为什么会启动失败?要加载到内存中的数据的位置与前面的链接描述文件片段中的相同,存储数据在闪存中的位置也相同。

    .data_flash :
  {
    . = ALIGN(4);
    _sidata = .;
    *(.data*)
    . = ALIGN(4);
  } > FLASH

  .firmware_header :
  {
    . = ALIGN(4);
    KEEP(*(.firmware_header))
    . = ALIGN(4);
  } > FLASH

  .data_ram (NOLOAD) :
  {
    . = ALIGN(4);
    _sdata = .;
    . = . + SIZEOF(.data_flash);
    _edata = .;
    . = ALIGN(4);
  } > SRAM

这就是我在 reset_handler() 中将数据从闪存加载到内存中的方式:

void **pSource, **pDest;
for (pSource = &_sidata, pDest = &_sdata; pDest != &_edata; pSource++, pDest++)
    *pDest = *pSource;

我在这里想念什么?这些在功能上不应该完全相同吗?

标签: gcclinkerembeddedstm32

解决方案


一个脚本将所有.data段的字节放入闪存中的相应部分,但将它们的所有地址解析为 RAM 中的运行时位置;这就是您的程序所需要的。要初始化变量,您需要将内容从闪存复制到 RAM,您所做的。

第二个脚本在闪存中解析.data加载时位置(如果我可以这么说的话)的所有段地址;这是行不通的,因为您的程序在运行时无法写入这些位置。该NOLOAD部分只是增加 RAM 中的位置指针,而不解析初始化变量的地址。

请查看交叉引用中的一些初始化变量(到一个不等于零的值)。使用您的第一个脚本,它将正确位于 RAM 中的某个地址,使用您的第二个脚本,它将错误地位于闪存中的某个地址。


推荐阅读