我们在使用Keil MDK编译ARM处理器的应用程序时,程序编译完成后会在下方的Build Output窗口中出现下图的信息提示,其中红色框框的内容对我们尤为重要;Code、RO-data、RW-data、ZI-data的含义理解以及程序最终占用处理器中的Flash空间大小和SRAM空间大小如何?今天就此问题跟大家进行详细的讨论,希望可以对大家有所帮助。 一、含义解释: Code:即代码域,它通常是指编译器生成的机器指令,这些内容会被存储到ROM区。 RO-data:Read Only data,即只读数据域,它指程序中用到的只读数据,这些数据被存储在ROM区,因而程序不能被修改的内容。例如C语言中const关键字定义的变量就是典型的RO-data。 RW-data:Read Write data,即可读写数据域,它指初始化为“非0值”的可读写数据,程序刚运行时,这些数据具有非0的初始值,程序运行的时候它们又会常驻在RAM区,应用程序可以修改其内容。例如C语言中定义的全局变量,且定义时赋予“非0值”给该变量。 ZI-data:Zero Initialie data,即0初始化数据,它指初始化为“0值”的可读写数据域,它与RW-data的区别是程序刚运行时这些数据初始值全都为0,程序运行时和RW-data的性质一样,它们也常驻在RAM区,应用程序可以更改其内容。例如C语言中使用定义的全局变量,且定义时赋予“0值”给该变量(如若定义该变量时没有赋予初始值,编译器会把它当ZI-data来对待,初始化为0); 二、程序存储详解: 关于哪些数据存储在Flash区域,哪些数据存储在SRAM区域,这就涉及到程序的存储状态了,应用程序具有静止和运行两种状态。静止态的程序被存储在非易失存储器中,如内部FLASH区域,因而系统掉电后也能正常保存。但是当程序在运行状态的时候,程序常常需要修改一些暂存数据(例如初始化非0值的数据),这些数据往往存放在Flash中,但是由于需要被修改,所以这些数据在程序运行的时候需要被复制到RAM中。因此,程序在静止与运行的时候它在存储器中的表现是不一样的。 上图中的左侧是应用程序的存储状态,右侧是运行状态,上方棕色区域是RAM存储器区域,下方黄色区域是ROM存储器区域。
程序在存储状态时,RO段(RO section)及RW段都被保存在ROM区(数据不能被修改)。当程序开始运行时,内核直接从ROM中读取代码,并且在执行应用程序代码前,会先执行一段加载代码,它把RW段数据从ROM复制到RAM(因为RW数据在执行过程中可能需要被修改), 并且在RAM中加入ZI段,ZI段的数据都会被初始化为0。加载完后RAM区准备完毕,正式开始执行主体程序。
编译生成的RW-data的数据属于图中的RW端,ZI-data的数据属于图中的ZI段。是否需要掉电保存,这就是把RW-data与ZI-data区别存储的原因,因为在RAM创建数据的时候,默认值为0,但如果有的数据要求初值非0,那就需要使用ROM记录该初始值,运行时再复制到RAM中。
三、程序占用Flash和SRAM的空间计算:
GD32的RO区域不需要加载到SRAM,内核直接从FLASH读取指令运行。当程序存储到芯片的内部FLASH时(即ROM区),它占用的空间是Code、RO-data及RW-data的总和,所以如果这些内容比芯片的FLASH空间大,程序就无法被正常保存在芯片的FLASH了。当程序在执行的时候,需要占用内部SRAM空间(即RAM区),占用的空间包括RW-data和ZI-data空间之和。 总结:程序需要下载到芯片的FLASH空间,FLASH的最小空间应该大于Code + RO Data + RW Data的总和; 程序运行的时候,芯片内部RAM使用的空间应该大于RW Data + ZI Data之和; 另外:程序编译后打开工程的map文件,在map文件的最后一段也有类似的描述,具体见下图所示:(程序编译成功后在①处双击鼠标左键,即可打开工程的map文件,在map文件的末尾即可看到如②所示描述) 本文参考链接:https://stackoverflow.com/questions/5430284/rom-and-ram-in-arm
|