【问题标题】:'Undefined Reference' to linker variable used in C source code对 C 源代码中使用的链接器变量的“未定义引用”
【发布时间】:2014-12-08 09:04:32
【问题描述】:

我正在 ST ARM 微控制器上进行一些编程,其中一部分我需要将一些数据存储在闪存中,这些数据将在启动时保持不变。

为了在我的项目中保持一致性,我想在我的链接描述文件中定义这些数据的位置,然后在我的代码中使用这个变量。我已经这样做了(针对两个不同的区域)。

我的链接器脚本的相关部分:

MEMORY
{
    flash :             org = 0x08000000, len = 60k     /* Standard boot - No bootloader */
    flash_config_info : org = 0x0801F800, len = 1k      /* Location for config info storage */
    flash_boot_info :   org = 0x0801FC00, len = 1k      /* Location for boot info storage */
    ram :               org = 0x20000000, len = 20k  
}

我的启动信息部分的标题:

#ifndef BOOTLOADER_H_
#define BOOTLOADER_H_

#include <stdint.h>

extern uint32_t flash_boot_info;
#define BOOT_INFO_PAGE_ADDRESS (&flash_boot_info)

//...

#endif

我的配置信息部分的标题:

#ifndef INFO_H_
#define INFO_H_

#include <stdint.h>

extern uint32_t flash_config_info;
#define INFO_CONFIG_PAGE_ADDRESS (&flash_config_info)

//...

#endif

我的问题:我在链接时收到关于 flash_boot_info 变量的“未定义引用”错误。我没有收到关于flash_config_info 的相同错误。需要注意的是,如果我切换变量的名称,错误会跟随引用的位置,而不是变量(当引用 flash_boot_info 时,我会收到关于 flash_config_info 的错误)。

有没有人知道为什么会发生这样的错误?我在引用变量的方式上没有发现任何差异,但我将不胜感激。

谢谢!

【问题讨论】:

  • 检查项目设置中的链接器配置,可能0x0801FC00 地址没有正确定义。您是否尝试过使用该地址“玩耍”?比如你知道0x08000000很可能是合法地址,所以把flash段的长度从60k改为59k,然后在0x0800EC00分配flash_boot_info段。
  • 另外,不要将-Text= 等与自定义链接器文件一起使用。对于这种情况,ld 可能会发出警告,因为如果您使用 memory region 并使用-Text 等指定它们应该在哪里,它会做一些非常奇怪的事情。跨度>

标签: c linker arm linker-errors undefined-reference


【解决方案1】:

同样的事情可以通过在sections 节中进行分区来完成。例如,

MEMORY
{
    flash : org = 0x08000000, len = 64k
    ram :   org = 0x20000000, len = 20k  
}
SECTIONS
{
   .text {
      boot.o(.text);
      *(.text);
      *(.rodata);
   } > flash
   .data {
      *(.data);
   } > ram AT>flash
   . = ADDR(.text) + 0x1F800; /* to config position */
   .config { *(.config); } > flash
   . = ADDR(.text) + 0x1FC00; /* to boot position */
   .boot { *(.boot); } > flash
   .bss { *(.bss); } > ram
}

要解决的主要问题是 ld 希望将所有内容都放在一个内存区域中。这是因为您只需要将映像(二进制)刻录到一台设备上。实际上,我认为您只有一个闪存设备,并且只想划分闪存。为此,最好使用位置计数器 (.)。

您可以预处理链接描述文件和/或使用常量使 1f8001fc00 值更具可读性。使用内存区域看起来更好,但我认为使用 sections 进行这种分区会有更好的体验。

【讨论】:

  • 你也许可以让内存区域工作,但我认为它是错误的工具。如果这不能回答您的问题,请至少给出一个更好的理由来说明您为什么要使用内存区域。
猜你喜欢
  • 1970-01-01
  • 2015-03-21
  • 2011-05-03
  • 2014-12-25
  • 1970-01-01
  • 2013-08-29
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
相关资源
最近更新 更多