哈佛和冯诺依曼,从STM32的const全局变量说起

从在学校到后来的实习工作,讲真,对于处理器的冯诺依曼结构和哈佛结构不大在意,印象中只知道它是数据存储器和程序存储器相关。

昨天在STM32程序中,把全局变量的定义成const属性时,发现它所处的位置是在STM32内置的FLASH而非内置的SRAM中。顿时让我觉得十分奇怪,程序不都必须在RAM中运行?即使在静态常量区不也应该放在SRAM中?

原因?这得从处理器的冯诺依曼和哈佛结构说起了。

1. 哈佛结构和冯诺依曼结构

哈佛结构,指的是数据存储器和程序存储器在物理是是分离的,以51单片机为例,数据存储器是单片机的RAM,程序存储器是单片机的ROM。在数据存储器中上不允许存储指令,同理,在指令存储器上不允许存储数据。

图为网上哈佛结构示意,数据存储器和程序存储器分别使用独立的两条总线,控制单元能够同时与程序存储器、数据存储器通信,实现软件系统功能。ARM采用的就是哈佛结构。(严格来说,很多高级ARM芯片已经采用哈佛结构和冯诺依曼结构的结合了)

冯诺依曼结构,通用计算机采用就是这种结构,数据和程序存储器不分离:

可以看出冯诺依曼把数据存储器和程序存储器都放在memory当中。对冯诺依曼结构而言,在执行程序时必须将指令和数据加载到运行内存中。

两种结构在保护代码区应该有不同的实现,哈佛结构在硬件级别上对代码和数据进行区分,当然软件应该也有,而冯诺依曼结构时应该单纯靠软件级别上进行区分的。

2. STM32的const全局变量地址

程序如下:

const int globalConstDat = 12;
int globalDat = 11;

int main(void)
{
    int localDat = 6;
    const int localConstDat = 7;

    USART_Configuration();

    //ptint to PC from USART1
    printf("&globalConstDat = 0x%p, &globalDat = 0x%p

", &globalConstDat, &globalDat);
    printf("&localDat = 0x%p, &localConstDat = 0x%p
", &localDat, &localConstDat);

    while(1);

    return 0;
}
 
        
 1
         
  2
         
  3
         
  4
         
  5
         
  6
         
  7
         
  8
         
  9
         
  10
         
  11
         
  12
         
  13
         
  14
         
  15
         
  16
         
  17
         
  18

程序运行结果:

根据STM32的存储器映像图(在一文配有此图),可得出,globalConstDat的地址位于flash memory(0x0800 0000~0x0801 ffff),其它变量的地址位于SRAM。为什么会有这种情况?第一取决编译器,第二则是因为ARM是哈佛结构。内置的FLASH和内置的SRAM相当于51单片机的ROM和RAM。SRAM用于存放数据,FLASH用于存放指令。在程序运行的时候,控制单元可以同时和RAM、FLASH通信,也就是说CPU可以直接再FLASH执行程序。注意,有些FLASH是不可以直接在其上去执行程序的,需要加载到RAM来,比如NandFlash,因为读取NandFlah的速度非常慢,但是也有一些FLASH可以,比如NorFlah。STM32内置的FLASH就是类似NorFlash属性的FLASH。全局静态常量是在文本常量区,它是静态且不可修改的,被编译器安排在了程序存储区,也就是说被编译给“指令化”了。

若是在冯诺依曼结构的处理器中,这样的情况,编译器则会有另外一套处理措施了。


经验分享 程序员 微信小程序 职场和发展