STM32 MDK编译后生成的 .map文件深入分析

.map文件是STM32开发中非常重要的一个文件,在该文件中可以详细的查看单个文件、函数及用户定义的全局变量等的占用RAM和ROM(一般为片内FLASH)的空间大小,通过了解这些信息可以很方便的进行代码的优化。

在MDK5中,生成的.map文件包含的内容可以在Options for Target--->Listing中如下界面中进行配置,默认是全选的,用户也可以根据自己的需求进行选择,如只生成Total info信息。在配置好map生成选项后编译整个工程,双击Project框中的项目名称即可打开.map文件。若使用的是STM32CubeMX生成的工程,则可能双击无法打开.map文件,具体解决方法参考这篇文章:

在STM32CubeMX生成的MDK5工程上添加RT-Thread Nano后双击工程名无法打开.map文件的解决方法

默认生成的.map文件由以下几部分构成:

1)Section Cross References

该部分描述了不同函数之间(可能在同或不同文件中)的调用关系。

在.map中生成该部分信息需要勾选下图中的标签4:

.map文件中生成的信息如下所示(部分截图):

第一行startup_stm32f103xb.o(RESET) refers to startup_stm32f103xb.o(STACK) for __initial_sp说明:startup_stm32f103xb.o文件中的“RESET”段为它使用的__initial_sp引用了startup_stm32f103xb.o文件中的“STACK”段。

有时候在编译工程时会报错,提示"Undefined symbol xxx(referred from yyy.o)",这表明在链接的过程中,yyy.o文件中引用的xxx符号并没有被定义,此时我们需要打开yyy.c或yyy.s文件查看xxx是否被定义,没定义需加上定义。

.o文件是.c文件或.s文件编译后生成的目标文件,各个文件及文件内的段是相互独立的,链接器根据它们之间的相互引用将各文件链接起来。

2)Removing Unused input sections from the image.

该部分描述了被MDK编译器优化掉的在链接过程中链接器发现的并未在工程中被引用的段或函数。这里需要注意的是,这部分并非在.o文件中被删除的,而是在链接器将这些.o文件链接生成.axf文件的过程中忽略掉这些无用部分,只将有用到的部分添加进.axf文件,如此可以有效的减少代码占用空间大小。

在.map中生成该部分信息需要勾选下图中的标签7:

.map文件中生成的信息如下所示(部分截图):

在MDK中可以通过勾选Options for Target--->C/C++--->One ELF Section per Function选项进行多余函数优化,若不勾选该选项也会进行部分函数优化,但不够彻底

下面通过实例说明勾选和不勾选One ELF Section per Function对生成的工程的影响:

  • 当勾选Options for Target--->C/C++中的One ELF Section per Function后在.map文件中生成的Removing Unused input sections from the image部分总结果如下:

共优化了529个函数,减少占用空间30270Bytes

  • 当取消勾选Options for Target--->C/C++中的One ELF Section per Function后在.map文件中生成的Removing Unused input sections from the image部分总结果如下:

共优化了121个函数,减少占用空间3806Bytes

通过以上对比可发现,勾选Options for Target--->C/C++--->One ELF Section per Function相比于不勾选要减少代码空间为26464Byte(30270 - 3806 )。这部分优化的空间最终会体现在Program Size中的Code大小上(60560 - 35716 = 24844Bytes),因此该选项对工程代码的优化有很大的作用,建议要勾选上这个选项。

3)Image Symbol Table

该部分描述了Local Symbols和Global Symbols,即局部标号和全局标号。

在.map中生成该部分信息需要勾选下图中的标签3:

.map文件中生成的信息如下所示(部分截图):

Local Symbols主要指的是通过static声明的全局变量地址和大小,.c文件中函数的地址和用static声明的函数代码的大小,汇编文件中的作用域限定在本文件中的标号地址。如被限定在某个.c文件中使用的函数一般用static进行修饰防止和其它文件中的同名函数冲突,如在某个函数内部通过static声明的变量虽然具有全局的生命周期但其只能在该函数中被访问。

Global Symbols主要是指不是用static声明的全局变量的地址和大小,.c文件中和函数的地址及其代码大小,汇编文件中作用域为全工程的标号地址。

4)Memory Map of the image

该部分描述了映像文件的内存映射。

在.map中生成该部分信息需要勾选下图中的标签1:

.map文件中生成的信息如下所示(部分截图):

映像文件分为加载域(Load Region)和执行域(Execution Region):

加载域反映了程序中各个段存放在ROM(FLASH)存储器中时的位置关系,Load Region LR_IROM1 (Base: 0x08000000, Size: 0x0000ffb4, Max: 0x00010000, ABSOLUTE, COMPRESSED[0x0000f744])中的Base表示程序从0x08000000处开始保存,Size表示程序实际占用ROM(一般为内部FLASH)空间为0x0000ffb4 Bytes,Max表示芯片最大的ROM空间为0x00010000。

执行域是芯片上电后开始执行代码的时候的运行状态,Execution Region ER_IROM1 (Exec base: 0x08000000, Load base: 0x08000000, Size: 0x0000ef94, Max: 0x00010000, ABSOLUTE)中的Base表示执行域从0x08000000处开始,Size表示执行域空间大小为0x0000ef94 Bytes,Max表示芯片最大的ROM空间为0x00010000。

映像中的入口点Image Entry point是程序开始执行的地方,为_main函数起始的地方,而不是Reset_Handler。

RAM上的普通变量只需4字节对齐,但是栈空间的边界需要8字节对齐。

 

5)Image component sizes

该部分描述了映像文件的组件大小,组件指的是单个的源文件,因为一个项目工程是由很多个.c文件组成的。这里会列举单个.c文件所占用的空间大小(RAM和ROM),具体为Code、inc.data(内联函数)、RO-Data、RW-Data、ZI-Data,并根据这些信息统计出程序占据的总RAM和ROM空间的大小。

在.map中生成该部分信息需要勾选下图中的标签5:

  1. Code:代码段,存放程序的代码部分
  2. RO-Data:只读数据段,存放程序中定义的常量
  3. RW-Data:读写数据段,存放初始化为非0值得全局变量
  4. ZI-Data:0数据段,存放初始化为0的全局变量或未初始化的全局变量(程序运行时会对未初始化的全局变量自动清0)

.map文件中生成的信息如下所示(部分截图):

从如上汇总信息可以看出,整个程序下载到STM32的ROM(FLASH)中时占用的空间大小为从0x08000000开始的38440字节 (Code + RO Data + RW Data) 。当程序运行时,占用的RAM空间大小为从0x20000000开始的11152字节(RW Data + ZI Data)。

 

.map文件中名词的解释:

  • section:映像文件的代码和数据块
  • RO:Read-Only,包括RO-Data(只读数据)和RO-Code(代码)
  • RW:Read-Write,指的是RW-Data,即读写数据段,存放初始化为非0值的全局变量
  • ZI:Zero-Initialized,指的是ZI-Data,0数据段,存放初始化为0的全局变量或未初始化的全局变量(程序运行时会对未初始化的全局变量自动清0)
  • .text:与RO-Code意义相同
  • .constdata:与RO-Data意义相同
  • .bss:与ZI-Data意义相同
  • .data:与RW-Data意义相同

htm文件:

基本统计了所有被调用函数的栈stack的使用情况(不考虑中断嵌套,因为中断嵌套是不可预测的),会给出函数调用时最大的栈深度,如此可以方便评估究竟需要开辟多大的栈空间。

 

参考资料:

安富莱:MDK生成的map和htm文件分析

《ARM Cortex-M3与ARM Cortex-M4权威指南》(第3版)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/429551.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#程序的组织结构

C#程序的组织结构: namespace(命名空间): C#程序中的一种代码组织形式,主要用来标识类的可见范围。一个namespace中包含了一系列的类,一般一个文件中会使用多个using语句引入多个命名空间。 语法&#xff…

hihocoder1477 闰秒

地址:http://hihocoder.com/problemset/problem/1477 题目: 闰秒 时间限制:10000ms单点时限:1000ms内存限制:256MB描述 计算机系统中使用的UTC时间基于原子钟,这种计时方式同“地球自转一周是24小时”的计时方式有微小的偏差。为了弥补这种偏…

C#命名空间namespace中不能直接包含字段(变量)或方法(函数)之类的成员

C#命名空间即namespace中不能直接包含字段(变量)或方法(函数)之类的成员,须将字段或方法放到类class中,否则编译器会报错。 C#命名空间中不能直接定义字段(变量): 将val…

Lucene实战之初体验

前言 最早做非结构化数据搜索时用的还是lucene.net,一直说在学习java的同时把lucene这块搞一搞,这拖了2年多了,终于开始搞这块了。 开发环境 idea2016、lucene6.0、jdk1.8 使用lucene准备条件 1、pom.xml 2、测试数据。 我从博客园首页拿了几…

C#中变量(成员变量、局部变量、全局变量)的作用域

不管在任何编程语言中都有变量的定义,变量就像是一个容器,不同的变量会在内存中占据不同大小的内存空间。定义变量后会将分配的地址绑定在这个变量名上,以后对该变量名的操作就是对该内存地上存储内容的操作。 namespace test {class myTest…

Servelt中的ServletContext对象

转载于:https://www.cnblogs.com/yxh-only/p/6548046.html

export function函数传参_从底层看前端(七)—— JavaScript到底有多少种函数?

在上篇文章中我们了解到了执行上下文是什么,也知道了任何语句的执行都会依赖特定的上下文。一旦上下文被切换,整个语句的效果可能都会发生变化。那么,切换上下文的时机就显得非常重要。在JavaScript中,切换上下文最主要的场景就是…

liunx常用命令0

1 开启Linux操作系统,要求以root用户登录GNOME图形界面,语言支持选择为汉语 点击“未列出?”-->输入root和密码 2 使用快捷键切换到虚拟终端2,使用普通用户身份登录,查看系统提示符 ctrlaltf2 3 使用命令退出虚拟终…

2个td合成一个td_18个月16个爆款,合成类玩法的下一个机会在哪?

18个月16个爆款!近日,编者体验了近18个月爆款小程序榜单之中的游戏,体验之后编者发现,在这200多款游戏中,有16款都应用了合成类玩法,而且部分游戏是数次登榜,比如枪火工厂、全民养鲲、世界争霸等…

在线代码图片生成工具carbon

在日常工作中时常需要和同事间进行代码的沟通和交流,有时只是需要讨论某一段代码的内容,因此不必将整个文件发给同事。通常可以将部分代码进行截图,或者直接将部分代码复制粘贴发送给同事。但以上方法或因为代码太长需要多次截图,…

antd 日期时间选择_Excel最全时间类函数总结,有必要收藏一下哦

Excel数据格式中,一共分十一类,其中两类分别是日期与时间。Excel中存在大量公式用于处理这两个类型的数据,下面一一介绍与之相关的函数。年月日函数Excel函数中分别用year()、month()、day()函数返回一日期的年、月、日,这三个函数…

C#中的变量类型(值类型、引用类型)

C#中的变量类型: 值类型:值类型直接存储的是变量的值,变量空间在栈上分配,分配速度比较快。给变量赋值时需注意变量类型的取值范围,给变量赋不合理的值会导致编译器报错。布尔类型的变量只有两种可选择的值true/false&…

Java:IDEA下使用JUNIT

单元测试的基本使用 一、环境配置 使用idea IDE 进行单元测试,首先需要安装JUnit 插件。 1.安装JUnit插件步骤 File-->settings-->Plguins-->Browse repositories-->输入JUnit-->选择JUnit Generator V2.0安装。 2.使用JUnit插件 在需要进行单元测试…

arcore之路-unity开发从入门到实践_Unity游戏开发——单例模式的最佳实践

0.前言StarryFun:Unity游戏开发——关于单例模式的理解​zhuanlan.zhihu.com之前一篇文章讲了单例模式的简单理解,自知其中有很多不严谨的地方,由于本萌新也是在学习阶段,所以去翻看了开源的项目都是怎么实现的,发现了…

光耦的简介

光耦,光电耦合器的简称,它是以光信号作为介质传输电信号的元器件。光耦的输入端和输出端信号可以非常好的进行隔离,因此在隔离电路中经常会见到光耦。光耦合器一般由三部分组成:光的发射、光的接收及信号放大。输入的电信号驱动发…

接待员如何向客人upsell_客房留言卡也能收获好评,看看高情商酒店如何做的?...

客人对酒店最客观的评价从点评中就能看到,那酒店服务如何才能被客人看到呢?可不可以通过一张留言卡,被客人感知到呢?本文整理了多个客房服务实际场景案例,帮助酒店了解如何写好这张留言卡。一、什么场景下放置留言卡&a…

“2020 RT-Thread开发者大会” 思考感悟

从2019年开始参加RT-Thread的一次线下培训活动后,就深深的喜欢上这个国产的RTOS,之后RT-Thread举办的活动基本都有参加(但每次活动抽奖都抽不到!)。当然,最为盛大的还属一年一度的RT-Thread开发者大会&…

小红书笔记_小红书的沙雕笔记,害人不浅啊

话说,当代人的十大必备软件是什么?要猫姐来说的话。除了微信微博抖音,小红书也肯定少不了!它简直就是大部分PLMM的“种草神器”。就连明星都纷纷入驻小红书变身为“美妆博主”。前一阵上了热搜榜和李晨分手的范冰冰也是小红书的一…

2020 RT-Thread开发者大会 ART-Badge电子胸牌(可二次开发)

2020 RT-Thread开发者大会 ART-Badge电子胸牌(可二次开发),动手实验IOT会场有介绍使用PersimmonUI设计器进行柿饼UI的开发,使用拖拽控件、注册事件的方式进行GUI的开发。开发语言使用JS,界面实现非常方便,后…