STM32 R0 RW ZI Data

CODE、 RO、 RW、 ZI Data 域及堆栈空间

在工程的编译提示输出信息中有一个语句“ Program Size: Code=xx RO-data=xx RWdata=xx ZI-data=xx”,它说明了程序各个域的大小,编译后,应用程序中所有具有同一性质的数据(包括代码)被归到一个域,程序在存储或运行的时候,不同的域会呈现不同的状
态,这些域的意义如下:

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);

ZI-data 的栈空间(Stack)及堆空间(Heap):在 C 语言中,函数内部定义的局部变量属
于栈空间,进入函数的时候从向栈空间申请内存给局部变量,退出时释放局部变量,
归还内存空间。而使用 malloc 动态分配的变量属于堆空间。在程序中的栈空间和堆
空间都是属于 ZI-data 区域的,这些空间都会被初始值化为 0 值。编译器给出的 ZIdata 占用的空间值中包含了堆栈的大小(经实际测试,若程序中完全没有使用 malloc
动态申请堆空间,编译器会优化,不把堆空间计算在内)

综上所述,以程序的组成构件为例,它们所属的区域类别见表

程序组件所属类别
机器代码指令Code
常量RO-data
初值非 0 的全局变量RW-data
初值为 0 的全局变量ZI-data
局部变量ZI-data 栈空间
使用 malloc 动态分配的空间ZI-data 堆空间

程序的存储与运行

RW-data 和 ZI-data 它们仅仅是初始值不一样而已,为什么编译器非要把它们区分开?
这就涉及到程序的存储状态了,应用程序具有静止状态和运行状态。静止态的程序被存储
在非易失存储器中,如 STM32 的内部 FLASH,因而系统掉电后也能正常保存。但是当程
序在运行状态的时候,程序常常需要修改一些暂存数据,由于运行速度的要求,这些数据
往往存放在内存中(RAM),掉电后这些数据会丢失。因此,程序在静止与运行的时候它在
存储器中的表现是不一样的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vfTFCX2W-1690338599455)(C:\Users\ruichi\AppData\Roaming\Typora\typora-user-images\image-20230726102504047.png)]

图中的左侧是应用程序的存储状态,右侧是运行状态,而上方是 RAM 存储器区域,下方是 ROM 存储器区域。

程序在存储状态时, RO 节(RO section)及 RW 节都被保存在 ROM 区。当程序开始运行时,内核直接从 ROM 中读取代码,并且在执行主体代码前,会先执行一段加载代码,它把 RW 节数据从 ROM 复制到 RAM, 并且在 RAM 加入 ZI 节, ZI 节的数据都被初始化为0。加载完后 RAM 区准备完毕,正式开始执行主体程序。

编译生成的 RW-data 的数据属于图中的 RW 节, ZI-data 的数据属于图中的 ZI 节。是否需要掉电保存,这就是把 RW-data 与 ZI-data 区别开来的原因,因为在 RAM 创建数据的时候,默认值为 0,但如果有的数据要求初值非 0,那就需要使用 ROM 记录该初始值,运
行时再复制到 RAM。

STM32 的 RO 区域不需要加载到 SRAM,内核直接从 FLASH 读取指令运行。计算机系统的应用程序运行过程很类似,不过计算机系统的程序在存储状态时位于硬盘,执行的时候甚至会把上述的 RO 区域(代码、只读数据)加载到内存,加快运行速度,还有虚拟内存
管理单元(MMU)辅助加载数据,使得可以运行比物理内存还大的应用程序。而 STM32 没有 MMU,所以无法支持 Linux 和 Windows 系统。

当程序存储到 STM32 芯片的内部 FLASH 时(即 ROM 区),它占用的空间是 Code、RO-data 及 RW-data 的总和,所以如果这些内容比 STM32 芯片的 FLASH 空间大,程序就无法被正常保存了。当程序在执行的时候,需要占用内部 SRAM 空间(即 RAM 区),占用
的空间包括 RW-data 和 ZI-data。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yXg8g9k6-1690338599457)(C:\Users\ruichi\AppData\Roaming\Typora\typora-user-images\image-20230726102715453.png)]

在 MDK 中,我们建立的工程一般会选择芯片型号,选择后就有确定的 FLASH 及SRAM 大小,若代码超出了芯片的存储器的极限,编译器会提示错误,这时就需要裁剪程序了,裁剪时可针对超出的区域来优化。

SRAM 大小,若代码超出了芯片的存储器的极限,编译器会提示错误,这时就需要裁剪程序了,裁剪时可针对超出的区域来优化。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oHfvFpiq-1690338599458)(C:\Users\ruichi\AppData\Roaming\Typora\typora-user-images\image-20230726102808688.png)]

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值