闪存和RAM:代码执行


13

我最近开始学习汇编,并开始了解链接器脚本和其他硬件编程的低级细节。我也在自学计算机体系结构,并且一直担心我的内存模型图可能一直是错误的。

根据我目前的了解,在将二进制文件“烧录”到处理器上之后,所有代码和数据都驻留在非易失性存储器中-易失性RAM复位后不包含任何内容。当程序开始“执行”时,它从地址0x0000开始执行,该地址几乎总是(AFAIK)Flash中的最低地址。因此,指令被锁存到将Flash连接到CPU内核的总线上,这就是实际执行的地方。但是,当我们谈论CPU从内存中检索或存储数据时,我们通常是在谈论RAM-我知道我们也可以从程序存储器中读取/写入数据(我已经在AVR上看到了这一点)但这不常见吗?是因为RAM比ROM快,所以我们更喜欢在那存储数据?

这个问题的公认答案是,大多数代码都是在RAM之外执行的。

这是否意味着启动运行时代码(其本身从Flash执行)必须将所有程序操作码从Flash复制到RAM,并以某种方式将Flash中的地址映射到RAM,以便CPU从那里获取操作码?它与启动时将.data节从ROM移到RAM的过程类似吗?

我可以想象这在程序和数据存储器共享总线的冯·诺依曼体系结构中会更简单,但是在哈佛体系结构中,这是否不意味着所有代码和数据都必须先通过CPU寄存器?

您可能会猜到,我对整个业务感到有些困惑。总是以更高的抽象级别进行编程,我很容易为这些细节所困扰。任何帮助表示赞赏。


2
在简单的微控制器中,无需从程序存储器(如今通常是闪存)复制到RAM即可执行。
大卫

这是因为RAM比Flash快,但是由于掉电后数据丢失,因此出现了非易失性存储器Flash。接通电源后,数据便从闪存加载到RAM,CPU开始工作,所有这些重复执行。
拉扎尔

Answers:


14

这取决于设备。

RAM的构建速度比Flash快;在约100MHz的频率范围内,这一点变得越来越重要。

简单的微控制器

小型慢速微控制器直接从Flash执行。这些系统通常也比SRAM具有更多的闪存。

中端系统

一旦设备变得更快,情况就会有所不同。中型ARM系统也可以做到这一点,或者它们可以具有做些更聪明的mask ROM引导加载程序:也许从USB或外部EEPROM将代码下载到内部SRAM中。

大型系统

更大,速度更快的系统将具有外部DRAM和外部闪存。这是典型的手机架构。此时,有足够的可用RAM,并且它比Flash快,因此引导加载程序将复制并执行它。这可能涉及通过CPU寄存器清除它,或者如果有DMA单元,则可能涉及DMA传输。

哈佛的体系结构通常很小,因此不必担心复制阶段。我见过带有“混合哈佛”的ARM,它是一个包含各种内存但有两个不同提取单元的地址空间。只要不是来自同一内存的代码和数据就可以并行获取。因此,您可以从闪存中获取代码,从SRAM中获取数据,或者从SRAM中获取代码,并从DRAM中获取数据,等等。


1

RAM通常比闪存快,但是直到时钟速度超过80-100MHz才真正无关紧要-只要闪存访问时间快于执行指令所需的时间,它就可以没关系。

RAM的物理结构使我们能够构建非常快的设备;比闪光灯快得多。此时,在执行之前将代码块复制到RAM是有意义的。这也为开发人员带来了其他好处,例如能够在运行时修改代码。

在冯·诺依曼(von Neumann)架构中,程序和数据存储器共享一条总线,但是在哈佛架构中,这不意味着所有代码和数据都必须首先通过CPU寄存器吗?

不必要。这就是虚拟寻址的地方。它实际上不是引用原始硬件RAM地址的程序代码,而是引用虚拟地址空间。虚拟地址空间的块被映射到物理存储设备,这些物理存储设备可以是RAM,ROM,闪存甚至设备缓冲区。

例如,当您在微型计算机上引用地址0x000f0004时,您可能正在从闪存中读取地址0x0004。该虚拟地址是0x000f0004,但物理地址是0x0004只是-整个0x000fxxxx地址空间映射到一个4KB物理存储设备。当然,这只是一个例子,管理和组织虚拟地址空间的方法在不同的体系结构中差别很大。

因此,当您说“程序从几乎始终是闪存中最低的地址的地址0x0000开始执行”时,您将无法保证是正确的。实际上,许多微控制器都是从0x1000开始的。


3
我会说,这种区别在20-40MHz而不是100Mhz时才有意义,因为我看到的大多数闪存设备都在该点附近开始需要等待状态。在许多情况下,代码闪存将包含电路,以便每次提取都将抓取多个指令字,因此对于许多种代码,从闪存运行的“惩罚”将仅为大约5-10%,但对于某些其他类型的代码,代码(例如,有很多跳转),惩罚可能会更加严重。
超级猫

这不是虚拟寻址,而是内存映射的I / O(内存区域使用外围设备映射到I / O,许多MCU上的名称为“静态内存控制器”)。当然,I / O可以到达另一个内存,因此有时我们不将其视为I / O。但这绝对不是虚拟内存映射。
Ben Voigt

1

您所说的并非完全正确或错误。有不同的方案。

这取决于您是在原始硬件上进行编程还是在OS随附的硬件上进行编程。

在通用计算机上运行的操作系统从HDD中获取代码,并将其存储在RAM中,以加快访问速度。如果您的处理器尝试持续不断地直接从HDD中获取数据,则由于两者之间的速度不匹配,操作会慢得多。因此,您的RAM会发挥作用,在其中存储您的重复代码部分,以加快访问速度。而且在处理器高速缓存中还提供了更多功能,以使其更快。

现在,当您使用微控制器时,它完全取决于您在芯片上放置数据的位置。如果数据是静态的,则可能需要将其放在代码存储器中,这样可以节省比代码存储器小得多的RAM。在C语言中,当使用静态初始化数据类型时,或者在某些编译器中,const前缀数据将存储在代码存储器中,否则将存储在RAM中。在程序集中,您可以直接使用DB(在Basic 8051中为Define Byte)来初始化特定位置上的数据。现在,即使在某些控制器(如PIC ARM)中,您也可以在运行时写入ROM,但获取数据将花费大量时间。

另外,在中级和复杂的控制器中还有Boot loader硬件,它告诉控制器或处理器从哪里执行启动代码,或者它本身就是实际上被分割到内存中的启动代码,因此,存在很多可能的改进,我宁愿说该行业的混合动力技术融合了传统RAM ROM和存储器的整个概念。因此,基本上您的困惑是正确的。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.