CPU先从系统的RAM中提取指令,随后解码该指令的实际内容,最后再由CPU的相关部分执行该指令。”有小伙伴后台留言提出了疑问:这个取指令过程,应该是从ROM读取指令吧?他说的没错,如果是从单片机程序执行的角度来看,确实是从 ROM 中读取指令。但是,这篇文章应该说的是 X86 或者 ARM-A 芯片的 CPU,先把指令加载到 RAM,CPU 再从 RAM中 取指令。今天来简单聊一聊 MCU 从 Flash 直接运行代码的原理。
聊一聊
关于单片机程序的存储和执行,之前有文章介绍过,可参考 STM32单片机程序的存储和执行。这篇文章侧重点在程序存储和程序加载的基本过程。
对于PC来说,可执行文件存储在磁盘上,当执行的时候,将文件内容(代码和数据)加载到内存中去执行。
而对于单片机来说,程序文件存在ROM中,执行的时候,指令代码不用加载到RAM即可执行。
MCU 内部的 Flash 是可以直接运行代码的,也就是说,可执行文件的 Code 和 RO Data不会被加载到 RAM中。
本文来介绍一下,单片机为什么可以直接运行代码,以及相关的技术原理。
这其中的关键技术为 XIP。那什么是 XIP 呢?
XIP 全称为 eXecute In Place,即芯片内执行,是指 CPU 直接从存储器中读取程序代码执行,而不用再读到内存中。
应用程序可以直接在 flash 闪存内运行,不必再把代码读到系统 RAM 中。flash内执行是指 nor flash 不需要初始化,可以直接在flash内执行代码。
但往往只执行部分代码,好处即是程序代码无需占用内存,减少内存的要求。
所谓片内执行不是说程序在存储器内执行,CPU 的基本功能是取指、译码、运行。
Nor Flash 能在芯片内执行,指的是CPU 能够直接从 Nor flash 中取指令,供后面的译码器和执行器来使用。
为实现就地执行,必须满足几个条件:
存储器必须提供与内存相似的接口给CPU。
该接口必须提供足够快的读取操作,并具有随机访问模式。
如有文件系统,则需要提供合适的映射功能。
程序链接时需要知道存储器的地址或地址与位置无关。
程序不能修改已加载映像中的数据。
NOR Flash 和 EEPROM通常能满足上述要求。
NOR flash 之所以可以片内执行,就是因为他符合 CPU 取指令译码执行的要求。
CPU 送一个地址出来,NOR Flash 就能给一个数据让 CPU 执行,中间不需要额外的处理操作。
对于 Cortex-M3 内核的单片机来说,其内部 Flash 连接到 AHB 总线上。
闪存的指令和数据访问是通过 AHB 总线完成的。单片机的预取模块是用于通过 ICode 总线读取指令的。
通过ICode总线,CPU从片内Flash直接读取指令。为了提高提高程序的执行速度,有的单片机会提供指令预取缓冲区。先将指令读取到预取缓冲区中。
对于STM32单片机来说,预取缓冲区有 2 个,每个缓冲区大小为 64位。在每一次复位以后被自动打开。
由于预取缓冲区的存在, CPU可以工作在更高的主频。CPU每次取指最多为32位的字,取一条指令时,下一条指令已经在缓冲区中等待。这样提高了CPU获取指令的效率和执行指令的速度。
对于51单片机来说,不存在指令预取缓冲区,通过XIP技术,从Flash中读取指令后,接着进行译码、运行。
补充
嵌入式系统中代码的执行方式主要有 3 种:
完全映射:嵌入式系统程序运行时,将所有代码从非易失存储器(Flash、ROM等)复制到RAM中运行。
按需分页:只复制部分代码到RAM中,这种方法对RAM中的页进行导入/导出管理,如果访问位于虚存中但不在物理RAM中会产生页错位,这时才将代码和数据映射到RAM中。
XIP:在系统启动时,不将代码复制到RAM,而是直接在非易失性存储位置执行,RAM中只存放需要不断变化的数据部分。
好了,关于程序的执行,欢迎一起探讨。