关于您的问题 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 架构的代码内存访问(适用于大多数其他架构):
- 限制最大时钟频率(文章中的示例从 80 MHz 到大约 20 MHz)
- 在闪存访问期间插入等待周期
- 使用指令缓存
- 将程序代码从闪存复制到 RAM
显然,如果指令缓存不是一个选项(太小或时钟太高),那么在启动时将代码重新定位到那里之后,您实际上只能从 RAM 执行。
还可以选择仅运行 RAM 中的特定代码部分,这可以指定给链接器。对于 DSP(数字系统处理)系统,即使在过去只有几十兆赫兹的时钟,也确实没有从 EPROM/FLASH 运行的选项,更不用说现在了。
另一个问题是调试,用于调试放在 ROM 甚至 Flash 中的代码的选项非常有限(您必须将部分代码移动到 RAM 才能在大多数系统上设置断点)。