4

我正在研究 Uboot 引导加载程序。我对 Bootloader 的功能和它要处理的应用程序有一些基本的问题:

Q1:据我所知,引导加载程序用于将应用程序下载到内存中。在互联网上,我还发现引导加载程序将应用程序复制到 RAM,然后应用程序从 RAM 运行。我对引导加载程序的工作感到困惑......当通过串行或 TFTP 向引导加载程序提供应用程序时,接下来会发生什么,引导加载程序是先将其复制到 RAM 还是直接写入闪存。

Q2: 为什么需要 Bootloader 将应用程序复制到 RAM 中,然后从 RAM 中运行应用程序?如果我们的应用程序从 FLASH 运行,我们会遇到什么困难?

Q3:“My application is running from RAM/FLASH”是什么意思?这是否意味着我们应用程序的 .text 段或 .code 段在 RAM/FLASH 中?我们并不关心 .bss 部分,因为它被设计为在 RAM 中。

谢谢 Phogat

4

4 回答 4

4

在设计任何硬件系统时,设计人员必须考虑可执行代码的位置。答案取决于微控制器、包含的存储器类型和系统要求。所以答案因系统而异。一些系统执行位于 RAM 中的代码。其他系统执行位于闪存中的代码。您没有告诉我们足够多的有关您的系统的信息,以至于无法了解它的设计目的。

系统可能被设计为从 RAM 执行代码,因为 RAM 访问时间比闪存快,因此代码可以更快地执行。系统可能被设计为从闪存执行代码,因为闪存很丰富,而 RAM 可能没有。系统可能被设计为从闪存执行代码,以便更快地启动。这些只是一些示例,还有其他考虑因素。

RAM 是易失性的,因此它不会通过电源循环保留代码。如果系统执行位于 RAM 中的代码,则需要引导加载程序在上电时获取代码并将其写入 RAM。闪存是非易失性的,因此可以在上电时立即开始执行,并且不需要引导加载程序(但可能仍然有用)。

关于Q3,答案是肯定的。如果系统从 RAM 运行,则 .text 将位于 RAM 中(但直到引导加载程序将其复制到那里之后)。如果系统从闪存运行,那么 .text 部分将位于闪存中。.bss 部分是变量,无论 .text 部分在哪里,都将在 RAM 中。

于 2013-03-15T16:08:25.880 回答
3

是的,一般来说,引导加载程序会引导系统,但它也可能提供一种中断默认引导路径的机制,并允许下载和运行备用固件,以及其他功能(如刷写)。

传统的 rom 有一个传统的 ram,如接口、地址、数据、芯片选择、读/写等。你仍然可以通过这种方式购买 rom,但从引脚空间的角度来看,使用基于 spi 或 i2c 的东西更便宜,这速度较慢。不希望从 ram 运行,但可以容忍一次读取然后从 ram 运行。较新的闪存技术可能/已经存在读取干扰问题,如果您的代码处于读取相同指令的紧密循环中或由于任何其他原因闪存读取速度过快,则电荷可能会下降,从而导致读取返回错误数据,可能导致程序改变路线或崩溃。此外,您的 PC 和其他 linux 平台用于将内核从 NV 存储(硬盘)复制到 ram,然后从那里运行,因此从闪存复制到 ram 并从 ram 运行具有舒适度,并且通常比闪存快。所以有很多不使用闪存的潜在原因,但根据系统的不同,它可能可以从闪存运行就好(某些系统有问题的闪存无法直接访问且不可执行,当然该系统中的某些 rom 需要可执行/可引导)。

如果您使用 ram 中的东西对闪存进行编程,它会简化编码挑战。您可以一次创建和调试从 ram 读取并写入闪存以及从闪存读取并写入 ram 的代码。完毕。现在您可以处理从串行到内存或从内存到串行接收数据的单独代码。完毕。然后处理通过以太网或 USB 或任何 DONE 执行相同操作的代码。您不必处理发明协议或解决时间问题。闪存写入非常慢,即使 xmodem 速度适中也可能太快,因此无论如何您都必须在 ram 中缓冲该数据,还不如让任务完全分开,而不是 xmodem 或任何其他基于串行的闪存加载程序使用基于大内存的先进先出,只需将数据移动到内存,然后分别从内存到闪存。其他接口也一样。技术上可以缓冲数据并产生从下载界面直接进入闪存的错觉,并且根据协议,技术上可以推迟发送方,以便在编程之前在 ram 中只需要一个闪存页面闪光。使用较旧的并行闪光灯,您可以做一些很酷的事情,我认为大多数人都无法理解。当您在某个已知时间段内停止写入闪存页面时,闪存将自动开始对该页面进行编程,您必须等待 10 毫秒或类似的时间才能完成。人们假设您必须对顺序地址进行编程,并且必须在那段时间内为下一个地址获取新数据,并且需要高串行端口速度等,现实情况是,您可以用相同的数据一遍又一遍地敲击相同的地址,并且闪存不会开始对页面进行编程,并且下载界面可能会无限慢。串行闪光灯的工作方式不同,要么不需要技巧,要么有不同的技巧。

RAM/FLASH 不是一些行业术语。这可能意味着 .text 位于 rom(闪存)中,而 .data 和 .bss 位于 ram 中。.data 的初始状态的副本也可能在闪存上,并在调用 main() 之前复制到 ram,同样,在调用 main() 之前,.bss 将归零。查看 gnu 源代码(glibc,还是 gcc,我不知道)中大多数平台的 crt0.S,以了解引导程序如何以通用方式工作的要点。

运行 linux 或其他操作系统不需要引导加载程序,您不需要 uboot,但它非常有用。Linux 非常简单,你复制内核和根文件系统,或者在内存中设置一些寄存器或一些标签,或者两者都分支到内核中的入口点,linux 从那里接管。因为 linux 非常复杂,所以希望有一个复杂的引导加载程序,它可以利用像以太网这样的高速接口(而不是仅限于串行或更慢的接口)。

于 2013-03-15T15:17:56.850 回答
2

关于第二季度,您从 Flash 执行时可能面临的一个困难是另一个代码更新。如果您从尝试更新的同一块 Flash 执行,系统将崩溃。这取决于您的系统架构(您的应用程序和引导加载程序在 Flash 中的组织方式),但如果您尝试更新引导加载程序本身,则可能特别难以避免。

于 2013-03-15T16:24:13.113 回答
2

关于您的问题 Q2,我将添加一些内容。

Q2: 为什么需要 Bootloader 将应用程序复制到 RAM 中,然后从 RAM 中运行应用程序?如果我们的应用程序从 FLASH 运行,我们会遇到什么困难?

这不仅仅是关于拥有 SPI 或类似的串行外部代码存储器(无论如何这并不常见)。

即使是连接到通常高速并行总线的外部 ROM/FLASH/EPROM/ 也会阻止系统在最大时钟(零等待状态)上运行,即使在相对较慢的 MCU 上,由于外部存储器访问时间的原因。对于 100 MHz 时钟,您需要 10 ns 的 FLASH 访问时间,这并不容易获得(如果经济上可行的话)。你会同意 100 MHz 不再是大脑旋转的速度了:-)

这就是为什么许多 MCU/CPU 架构正在通过一次读取乘法指令,或拥有内部现金,或做任何需要补偿缓慢的外部代码存储器的技巧。只有大多数较旧的 8 位架构可以直接从闪存(“就地”)执行代码。

即使您唯一的代码存储器是内部闪存,也需要做一些事情来加速它。看看这篇文章的例子:

http://www.iqmagazineonline.com/magazine/pdf/v_3_2_pdf/pg14-15-18-19-9Q6Phillips-Z.pdf

它描述了 ARM7 如何整合他们称为 MAM(内存加速器模块)的东西。这是一本很好的读物,您会在那里找到一些措施来加快特定 ARM7 架构的代码内存访问(适用于大多数其他架构):

  1. 限制最大时钟频率(文章中的示例从 80 MHz 到大约 20 MHz)
  2. 在闪存访问期间插入等待周期
  3. 使用指令缓存
  4. 将程序代码从闪存复制到 RAM

显然,如果指令缓存不是一个选项(太小或时钟太高),那么在启动时将代码重新定位到那里之后,您实际上只能从 RAM 执行。

还可以选择仅运行 RAM 中的特定代码部分,这可以指定给链接器。对于 DSP(数字系统处理)系统,即使在过去只有几十兆赫兹的时钟,也确实没有从 EPROM/FLASH 运行的选项,更不用说现在了。

另一个问题是调试,用于调试放在 ROM 甚至 Flash 中的代码的选项非常有限(您必须将部分代码移动到 RAM 才能在大多数系统上设置断点)。

于 2013-03-15T16:23:11.130 回答