这两个链接描述文件节之间有什么区别?

时间:2019-07-18 23:00:27

标签: gcc linker embedded stm32

我有一个STM32项目,其中涉及一个.firmware_header部分,该部分为我的应用程序映像的结尾加盖。我试图重新放置.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;

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

1 个答案:

答案 0 :(得分:0)

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

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

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