【问题标题】:Big empty space in memory?内存中的大空间?
【发布时间】:2014-05-04 21:45:18
【问题描述】:

实际上我是昨天才开始接触嵌入式编程的,我注意到一些我认为很奇怪的东西。我有一个非常简单的程序,只返回 0。

int main() {

    return 0;
}

当我在 IAR Embedded Workbench 中运行它时,我有一个内存视图显示程序内存。我注意到内存中有一些内存,但它是一大块空白空间,然后又有内存(我很讨厌解释:P所以这是内存的图像)

请帮助我比现在更了解这一点。我真的不知道要搜索什么,因为我对此很陌生。

【问题讨论】:

  • 什么处理器架构?这只发生在低内存的固定位置吗?它可能是几件事中的任何一个,例如调试器配置了硬件内存映射的详细信息,以认为在这些位置实际上没有任何响应,调试器最近没有尝试从芯片读取的区域,具有重复的内容,或者可能还没有立即想到的其他内容。
  • 我正在使用 ARM,并在我正在使用的程序中的模拟器中运行它。
  • 第一位可能是中断向量,那么代码段位于0x80。没有分配休息。有一个向量 '80 00 00 00' 看起来很像重新启动,还有几个向量指向 '70 01 00 00' 处的一小段代码,我怀疑这是一个禁用中断的“严重错误”无限循环。检查您的 makefile 和/或部分位置。

标签: c memory embedded arm


【解决方案1】:

前两行是 8 个中断向量,表示为 32 位指令,最高字节在后。即以4个字节为一组读取,最高字节在后,然后通过通常的方法转换为指令。前几个向量,包括内存位置 0 的复位,结果是 LDR 指令,它将立即地址加载到 PC 寄存器中。这会导致处理器跳转到该地址。 (复位向量也是设备开机时运行的第一条指令。)

您可以查看 LDR 指令 here 的结构,或通过 Internet 搜索在许多其他地方查看。如果我们将复位向量18 f0 95 e5写成e5 95 f0 18,那么我们看到PC寄存器加载了位于偏移0x20处的地址。

所以接下来的两行是前两行中的指令引用的内存位置。复位向量将 PC 发送到 0x00000080,这是程序的 C 运行时开始的地方。 (其他向量将 PC 发送到程序末尾附近的 0x00000170。这条指令的内容留给读者。)

通常,C 运行时是添加到程序前面的代码,用于将全局变量从闪存加载到 RAM 中,并将未初始化的 RAM 设置为 0。然后您的程序将启动。

您最初的问题是:为什么会有这么大的未使用闪存缺口?答案是闪存并不是非常珍贵,所以我们可以浪费一点,并且在那里有额外的空间可以实现向前兼容。如果我们需要增加向量表的大小,那么我们不需要移动代码。事实上,这种中断模型在新的 ARM Cortex 处理器中已经改变了。

【讨论】:

  • 它在哪里设置堆栈指针?还是只保留默认值?
  • 对不起,我很笨,但在这种情况下什么是向量?
  • 您可以查找“中断向量”以找到详尽的解释。 tl;dr 是当某些硬件事件发生时,设备会自动跳转到某些位置以获取指令。一般来说,程序员不能改变这种行为(除了可能为表格选择不同的位置。)通常,这些指令的空间有限,所以你的代码会在那里放置一个跳转指令来跳转到你的其他地方自己的代码。 “向量”是闪存中设备在中断时跳转到的位置。
  • @Lundin 堆栈指针通常由程序前面的 crt 代码设置。我不知道这个设备的约定。
  • 对不起,我说错了。 “向量”是表中指向代码中要跳转到的位置的东西。通常,is 是跳转指令,或者在这种情况下是 LDR 指令。
【解决方案2】:

UncleO 是对的,但这里有一些额外的信息。

项目的链接器命令文件(用于 IAR EW 的 *.icf)确定节在内存中的位置。 (查看 Project->Options->Linker->Config 以识别您的链接器配置文件。)如果您使用文本编辑器查看链接器命令文件,您可能能够确定它在哪里找到名为 .intvec (或类似)的部分在地址 0x00000000。然后它可能会在地址 0x00000080 处找到另一个部分(可能是 .text)。

您还可以查看 .map 文件中标识的这些内存部分及其位置。 (确保在 Project->Options->Linker->List 下选中“Generate linker map file”。)但是,映射文件是构建的输出,它是确定位置的链接器命令文件。

所以内存中的空间是存在的,因为链接器命令文件指示它是那样的。我不确定那个空间是否必要,但这肯定不是问题。您也许可以尝试使用链接器命令文件并移动第二部分。但是异常表(又名中断向量表)必须位于 0x00000000。如果您移动它,您需要确保重置向量指向启动代码的新位置。

【讨论】:

  • 我怀疑这个想法是为 FIQ 处理程序留出一点空间。
【解决方案3】:

物理(非虚拟)内存地址映射到物理电路。最低地址通常映射到寄存器,而不是 RAM 阵列。为了保持一致性,一个给定的地址通常会映射到同一家族的不同处理器上的相同功能,而缺少的功能会在地址映射中显示为一个小洞。

此外,在所有 I/O 寄存器和内务处理功能之后,RAM 被分配到一个连续的地址范围。这会在所有寄存器和 RAM 之间产生一个大洞。

或者,正如@Martin 建议的那样,它可能将未初始化和只读闪存表示为-- 字节。与真正未分配的地址不同,访问此地址不太可能产生异常,您甚至可以使用适当的 Flash 控制器命令使它们“重新出现”。

在现代桌面级机器上,虚拟内存对您隐藏了所有这些,甚至物理地址映射的部分内容也可能是可配置的。许多嵌入式处理器允许配置到指定中断向量表的位置。

【讨论】:

  • +1 这是一个符合 8051 等芯片工作原理的有效答案。发布者最终回应了指定架构的请求,结果我们现在知道它不是以这种方式工作的芯片。但这对最初提供的信息的有效答案 - 其最终不适用是提问者的错,而不是答案发布者的错
猜你喜欢
  • 1970-01-01
  • 2021-03-18
  • 2022-08-22
  • 1970-01-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-24
相关资源
最近更新 更多