【KEIL·单片机·扫盲贴】关于ARM单片机程序内存使用情况的细致讨论。
接触了两年多时间的单片机编程本人对关于单片机程序内存如何耗费的问题一直懵懵懂懂,直到在近日看到某篇有关于MDK MAP文件介绍的帖子后才有种醍醐灌顶的感觉,这里我将分享在此之上的观点与见解以供大家讨论学习。
大家都知道ARM单片机的内部存储空间极其匮乏无论是从Flash还是RAM上,每每给单片机机编程都有一种惜字如金的感觉,工程师们一般会在容量有限的情况下规范其编程习惯简化代码避免冗余,那么首先我们如何知道的程序下载到单片机上到底占用了多少Flash程序运行又会使用多少RAM?
首先上一张图:
该图是KEIL编译某个单片机程序后生成的构建信息,这里我们只关注其中的Program Size信息。
Program Size其意义是编译后生成的代码大小单位是字节,Program Size的大小有四大决定因素:Code,RO-data,RW-data,ZI-data 。
Code :意义是代码指令占用的空间;
RO-data :是Read Only Data的缩写,意义是只读常量占用的空间。如const型常量,常量字符串等等;
RW-data :是Read Write Data的缩写,意义是可读可写的已初始化 了的变量占用的空间。如全局变量,静态变量等等;
ZI-data :是Zero Initialize Data的缩写,意义是以0初始化的变量。如未初始化赋值的全局变量,静态变量等等;
综上来说 烧写的时候是FLASH中的被占用的空间大小为:Code + RO Data + RW Data,而程序运行的时候数据使用到的RAM的空间大小为:RW Data + ZI Data。
Why?
FLASH中的被占用的空间很好理解,就是等于代码指令+只读数据的值+已初始化变量的值。那么运行时数据占用RAM空间大小==RW Data + ZI Data又作何理解?
我们都知道,在代码运行机制上单片机不同于PC,单片机的程序通常是在FLASH中直接取指执行,而PC是先把程序拷贝到RAM中再取指执行。
由上说明单片机的RAM中至少不会存在Code拷贝(除非使用了特殊方法强行使程序拷贝到了RAM中执行,本贴不讨论此情况),
其次,单片机RAM中也不会存在RO-data拷贝,因为RO-data是只读数据,为了节省RAM空间,这种数据在执行时直接从FLASH中取出使用,无需再复制到RAM。
那么剩下的 RW Data + ZI Data由于是可读可写的数据,为了能够供程序运行时正常读写,于是就会被放在单片机的RAM中(单片机的FLASH区不能被程序改写)。
有人可能会问RW-data 与ZI-data都是指的全局变量或者静态变量,那么程序中的局部变量去了哪儿?这里就要向大家澄清一个事实,在C或C++中全局变量或 静态变量在RAM中都有一个特定地址(存在于静态区),而局部变量却没有特定的地址
因为局部变量存在于栈中(存在于堆栈区),当函数入栈时系统就会在栈顶之上开辟一段内存供给局部变量使用,当函数出栈时该内存就会被释放掉。
那么单片机在程序运行时RAM的使用量就等于RW Data + ZI Data了吗,还有没有其他因素会导致RAM占用变化?
玩过PC的都知道,一个程序在运行时它在内存中的占用情况是会随时改变的,这其中可能有压栈入栈和堆块的申请与释放等事件发生,那么在单片机里难道就没有这样的过程了吗?答案都是否定的。
单片机的RAM中也有堆栈区,那么程序运行时RAM的使用量就不会再等于RW Data + ZI Data了,因为程序的堆栈区也是一段具体的内存,那么堆栈区的内存占用又有多大?
堆栈区大小的查询方法,这里以STM32F1系列作为介绍,以航迹雲STF1驱动集合库中的startup_stm32f10x_hd.s启动文件为例:
(看不清图片的朋友们,请右键查看图片)
图中有个Stack_Size(栈大小)与Heap_Size(堆大小)定义,这两十六进制的数值之和就是你的单片机运行时RAM中的堆栈字节大小,其他单片机平台的堆栈大小查询方法请自行百度。
以上可以得出,一个arm架构的单片机的程序在运行时将会占用到的RAM空间等于 RW Data + ZI Data + Stack_Size + Heap_Size;
那么在程序运行时还有没有其他因素会导致RAM被使用的空间发生变化?
在回答这个问题之前,我们先来讨论何为 “在编译时编译器会为一个变量分配一段内存” ?玩过汇编的都知道编译器并不会给变量一个内存, 而是编译器在内存中为变量指定了一个地址而已,然后让其他变量不会重复指向该地址,在编译时编译器会把变量名由地址替换掉,这样就达到了貌似"编译器给变量分配了内存" 的效果。
因为编译器为每个变量分配地址且不会让该地址被占用,由此得知RW Data + ZI Data这两块数据在被分配好内存之后会一直处于无法被回收的状态,根据认知科学一一无法回收==占用,所以RAM中的RW Data + ZI Data区就会一直处于占用状态,如果没有新的程序烧录进来RW Data + ZI Data区占用的空间是不会变的。
那么堆栈区就更不用说了,堆栈区的大小是由单片机的启动文件中Stack_Size 与 Heap_Size确定的,函数入栈出栈变的只是堆栈区内的数据而不是变化堆栈区大小( 注:如果函数入栈的数量超出了堆栈区的大小限制则为爆栈),如果没有新的程序烧录进来Stack_Size + Heap_Size区占用的空间也是不会变的。
结论:ARM单片机中的FLASH的占用量取决于Code + RO Data + RW Data,程序运行时RAM的占用量取决于 RW Data + ZI Data + Stack_Size + Heap_Size且在程序运行过程中该占用量几乎不变;
这是我的第一篇博客,以上皆为个人愚解,如有不周欢迎斧正。
2017/9/11 航迹雲
转载于:https://www.cnblogs.com/Contrail/p/7502066.html
【KEIL·单片机·扫盲贴】关于ARM单片机程序内存使用情况的细致讨论。相关推荐
- 分析go程序内存逃逸情况
分析go程序内存逃逸情况 go build -gcflags -m app/admin/service/cmd/server/main.go app/admin/service/cmd/server/ ...
- 嵌入式编程(二):ARM单片机如何将函数 定义到指定程序地址
在单片机编程使用中,会涉及到将某些函数定义到指定的code区.此时需要对工程文件进行配置修改才可完成.本期针对ARM平台单片机做出说明介绍 1.测试目标 将函数Communication_Test定义 ...
- 成功解决keil识别不到单片机芯片,下载不了程序
成功解决keil识别不到单片机芯片,下载不了程序 我的芯片是STM32F429,正点原子的阿波罗. 今天使用开发板做实验,突然找不到芯片了,以前下载的PWM波也运行不了.查找了好久,原来是芯片锁了,终 ...
- zynq7020的ARM单片机编译与运行程序MTCNN
背景:FPGA的运行需要片上ARM的控制,所以需要针对片上ARM编写的源码并且需要片上ARM执行源码. 目的:运用ARM编译MTCNN的代码,然后在ARM上运行. 目录 一.创建虚拟机 二.虚拟机上编 ...
- 【单片机高阶编程】51单片机定义函数到指定的程序地址
51单片机如何将函数 定义到指定程序地址 在单片机编程使用中,会涉及到将某些函数定义到指定的code区.此时需要对工程文件进行配置修改才可完成.本期针对单片机平台做出说明介绍 1.测试目标 将函数te ...
- 51单片机usb烧录电路_51单片机怎么用usb烧写程序 - 全文
单片机怎样用usb烧写程序 首先,需要安装keil软件和STC_ISP程序下载软件. 先对你想要实现对单片机的功能用keil编程,然后用STC_ISP下载软件下载到单片机上,最后打开给单片机提供电源就 ...
- STC单片机不同数据类型串口打印输出示例程序
STC单片机不同数据类型串口打印输出示例程序 串口监视器打印 程序代码 #include "STC15W4K.H" #include <stdio.h> // 为使用K ...
- 单片机入门学习五 STM32单片机学习二 跑马灯程序衍生出的stm32编程基础
上篇文章 单片机入门学习四 STM32单片机学习一 跑马灯程序和创建工程 仅介绍了入门程序及其编译运行过程,下面开始对stm32的一些基础知识做一个记录. 1.stm32f103zet6(上篇问题3 ...
- 项目开发中ARM单片机芯片分类及选型
项目开发中单片机芯片的选型是一件重要而费心的事情 , 如果芯片型号选择得合适 , 单片机应用系统就会得经济 , 工作可靠 ; 如果选择得不合适 , 就会造成经济浪费 , 影响单片机应用系统的正常运行 ...
最新文章
- Android性能优化之图片压缩优化
- 英伟达一大波硬件来袭:今日GTC发布专业GPU与DPU,为收购ARM将在英国建超算
- Sring boot学习笔记(三)-自带注解定时任务使用
- 5G是卡位未来的重要基础设施 物联网已成为新的攻击入口
- 不再为DataGrid生成的表格的单无格中的内容过长、自动折行、表格撑开等问题而烦恼----一个很久以前的做品...
- 【Nutch基础教程之七】Nutch的2种运行模式:local及deploy
- 《四世同堂》金句摘抄(十七)
- 数字图像处理知识总结
- 如何和何时使用 CSS 的权重设置 !important (建议:永不使用!)
- 删除oracle怎么快,如何快速删除Oracle的好方法
- Android 替换字体的方式以及同时替换多种字体
- 20145209 2016-2017-2 《Java程序设计》第5周学习总结
- 老男孩高端linux培训2014业务服务范围
- 「陶哲軒實分析」 習題 3.5.9
- unicode学习笔记
- 关于PHP中echo换行问题
- LaTeX自定义字体安装
- python程序实例视频教程_python从入门到精通视频(全60集)马哥Python未压缩版
- Inav Configurator给F4刷固件进入不了DFU
- 通俗理解核方法(kernel function)