前言

前几个月针对公司自己的芯片写了个程序,这个程序有个硬性要求,就是能用的FLASH空间只有4KB,之前已经写得差不多了,最终占用空间3.6KB。

这不,最近又得加需求,还剩一点点FLASH空间可以使用,这该如何是好。需求已经加过来了,不行也得行啊。所以就得去优化之前的代码了,这就得研究比较底层的东西了。

我们的芯片与其它的MCU芯片用起来都差不多一样。我们在用ST的时候,编译完成,会生成很多文件,其中有一个.map文件,里面包含的信息就是工程 ROM/FLASH 和 RAM 的占用情况 。

之前只是关心.map文件的最后几行的 ROM/FLASH占用信息,如:

这次就得认真的学习一下这个文件了,只有清楚的知道这些信息才可以很好的进行代码优化 。下面我们来一起学习一下STM32的.map文件。(以下内容来自野火及安富莱教程文档)

map文件

要生成 map 文件,MDK 中如下选项要选上:

将工程全编译,且没有错误后,双击这里就可以看到生成的 map 文件了:

map文件的内容可分为如下几部分:

1、节区的跨文件引用(Section Cross References)
2、删除无用节区(Removing Unused input ps from the image)
3、符号映像表(Image Symbol Table (Local Symbols Global Symbols)
4、存储器映像索引(Memory Map of the image)
5、映像组件大小(Image component sizes)

1、节区的跨文件引用

这部分主要是不同文件中函数的调用关系。  在这部分中,详细列出了各个.o 文件之间的符号引用。

由于.o 文件是由 asm 或 c/c++源文件编译后生成的,各个文件及文件内的节区间互相独立,链接器根据它们之间的互相引用链接起来,链接的详细信息在这个Section Cross References一一列出。

例如,开头部分说明的是 startup_stm32f429_439xx.o 文件中的“RESET”节区分为它使用的__initial_sp符号引用了同文件“STACK”节区。

也许我们对启动文件不熟悉,不清楚这究竟是什么,那我们继续浏览,可看到 main.o文件的引用说明,如说明 main.o 文件的 i.main 节区为它使用的 LED_GPIO_Config 符号引用了 bsp_led.o 文件的 i.LED_GPIO_Config 节区。

有时在构建工程的时候,编译器会输出 “Undefined symbol xxx (referred from xxx.o)” 这样的提示,该提示的原因就是在链接过程中,某个文件无法在外部找到它引用的标号,因而产生链接错误。

2、删除无用节区

map 文件的第二部分是删除无用节区的说明,见代码清单:

这部分列出了在链接过程它发现工程中未被引用的节区,这些未被引用的节区将会被删除(指不加入到*.axf 文件,不是指在*.o 文件删除),这样可以防止这些无用数据占用程序空间。

例如,上面的信息中说明 startup_stm32f429_439xx.o 中的 HEAP(在启动文件中定义的用于动态分配的“堆”区)以及 stm32f4xx_adc.o 的各个节区都被删除了,因为在我们这个工程中没有使用动态内存分配,也没有引用任何 stm32f4xx_adc.c 中的内容。

由此也可以知道,虽然我们把 STM32 标准库的各个外设对应的 c 库文件都添加到了工程,但不必担心这会使工程变得臃肿,因为未被引用的节区内容不会被加入到最终的机器码文件中

对于这个部分功能,用户最好将 MDK 中这个选项勾上,然后全编译工程,效果会比较好:

3、符号映像表

map 文件的第三部分是符号映像表(Image Symbol Table), 见代码清单 51-12。

这个表列出了被引用的各个符号在存储器中的具体地址、占据的空间大小等信息。

如我们可以查到LED_GPIO_Config 符号存储在 0x080002a5 地址,它属于 Thumb Code 类型,大小为 106 字节,它所在的节区为 bsp_led.o 文件的 i.LED_GPIO_Config 节区。

4、存储器映像索引

map 文件的第四部分是存储器映像索引(Memory Map of the image), 见代码清单:

映像文件可以分为加载域(Load Region)和运行域(Execution Region) 。

简单的说,加载域就是程序在 Flash 中的实际存储,而运行域是芯片上电后的运行状态,通过下面的框图可以有一个感性的认识:

通过上面的框图可以看出,RW 区也是要存储到 ROM/Flash 里面的,在执行映像之前,必须将已初始化的 RW 数据从 ROM 中复制到 RAM 中的执行地址并创建 ZI Section(初始化为 0 的变量区)。

本工程的存储器映像索引分为 ER_IROM1 及 RW_IRAM1 部分,它们分别对应 STM32内部 FLASH 及 SRAM 的空间。

相对于符号映像表,这个索引表描述的单位是节区,而且它描述的主要信息中包含了节区的类型及属性,由此可以区分 Code、 RO-data、 RW-data及 ZI-data。

例如,从上面的表中我们可以看到 i.LED_GPIO_Config 节区存储在内部 FLASH 的0x080002a4 地址,大小为 0x00000074,类型为 Code,属性为 RO。而程序的 STACK 节区(栈空间)存储在 SRAM 的 0x20000000 地址,大小为 0x00000400,类型为 Zero,属性为RW(即 RW-data) 。

5、映像组件大小

map 文件的最后一部分是包含映像组件大小的信息(Image component sizes),这也是最常查询的内容,见代码清单  :

这部分包含了各个使用到的*.o 文件的空间汇总信息、整个工程的空间汇总信息以及占用不同类型存储器的空间汇总信息,它们分类描述了具体占据的 Code、 RO-data、 RW-data及 ZI-data 的大小,并根据这些大小统计出占据的 ROM 总空间。

综合整个 map 文件的信息,可以分析出,当程序下载到 STM32 的内部 FLASH 时,需要使用的内部 FLASH 是从 0x0800 0000 地址开始的大小为 1456 字节的空间;当程序运行时,需要使用的内部 SRAM 是从 0x20000000 地址开始的大小为 1024 字节的空间。

总结

对照着这个map文件再看看我的程序,就可以知道哪里占的flash空间多了。硬件相关的部分已经用寄存器来操作,协议处理部分占用的flash空间最多。

最后,对于.map文件,我们一般只需要了解最后几行即可。如果想要深入学习,可以参照野火及安富莱的教程文档进行学习。


扫码或长按关注

回复「 篮球的大肚子」进入技术群聊

STM32的map文件学习笔记相关推荐

  1. STM32 LCD中英文字符显示学习笔记

    本实验基于STM32 LCD英文字符显示学习笔记. 开发板:野火指南者(STM32F103VE) STM32库版本:STM32F10x_StdPeriph_Lib_V3.5.0 IDE:KEIL5(代 ...

  2. React学习:事件绑定、组件定义、for、map循环-学习笔记

    文章目录 React学习:事件绑定.组件定义.for.map循环-学习笔记 事件绑定 组件定义 (参数传递) for.map循环 React学习:事件绑定.组件定义.for.map循环-学习笔记 事件 ...

  3. STM32 CAN总线通信学习笔记(一)

    STM32 CAN总线通信学习笔记(一) 一.CAN总线简介 CAN 是控制器局域网络(Controller Area Network, CAN)的简称.CAN采用数据块编码的方式,数据块根据帧的类型 ...

  4. 【STM32】OV2640摄像头学习笔记 转

    [STM32]OV2640摄像头学习笔记 2019年03月03日 13:01:35 淹死的大白鲨 阅读数 4736更多 分类专栏: [STM32] 版权声明:本文为博主原创文章,遵循 CC 4.0 B ...

  5. oracle修改asm参数文件,学习笔记:Oracle RAC参数文件管理 修改创建asm中的spfile文件...

    天萃荷净 Oracle rac创建修改asm中的spfile文件内容 create spfile to asm --查看sid SQL> show parameter instance_name ...

  6. JavaSE中Map框架学习笔记

    前言:最近几天都在生病,退烧之后身体虚弱.头疼.在床上躺了几天,什么事情都干不了.接下来这段时间,要好好加快进度才好. 前面用了三篇文章的篇幅学习了Collection框架的相关内容,而Map框架相对 ...

  7. python map zip_Python学习笔记(九) map、zip和filter函数

    这篇文章主要介绍 Python 中几个常用的内置函数,用好这几个函数可以让自己的代码更加 Pythonnic 哦 1.map map() 将函数 func 作用于序列 seq 的每一个元素,并返回处理 ...

  8. oracle12c口令文件,学习笔记:Oracle 12C ASM 新特性 共享密码文件

    天萃荷净 测试试验ORACLE 12C ASM 新特性 共享密码文件的详细过程 在ORACLE 12C之前大家都知道密码文件是存放在?/dbs或者?/database中,如果要修改修改sysdba权限 ...

  9. STM32 HAL库开发学习笔记: USART1串口通讯(中断方式) IDE-STM32CubeIDE

    STM32串口通讯有三种方式,分别为阻塞(轮询).中断.DMA.这里将用中断的方式开发. 笔者也是刚入门STM32 HAL库开发,该笔记致希望于能帮到初学者,文中配置步骤.代码.实验现象均是笔者实践可 ...

最新文章

  1. 建立数组并写入数据_redis高并发利器:神奇的位操作,底层原理、数据结构剖析...
  2. Win32 API 打开另一个进程
  3. scum开服务器延迟高怎么办,人渣SCUM卡顿优化方法 人渣SCUM卡顿怎么办
  4. html中链接不自动变色,HTML 点击 标签 链接 点击之后变色-转发【已解决】
  5. unity三维向量变化为角度_三维旋转
  6. 设计模式17_命令模式
  7. 【腾讯云的1001种玩法】 Laravel 整合微视频上传管理能力,轻松打造视频App后台...
  8. 最新出炉程序猿使用说明书
  9. Silverlight像素着色器编写简明指南 附送文字描边效果
  10. 275页PDF:《编写高质量代码:改善Python程序的91个建议》
  11. nlp基础—12.LSTM-CRF模型介绍
  12. 致加西亚的信 名言佳句
  13. VMware 搭建私有云
  14. React Native入门——布局实践:开发京东客户端首页(一
  15. 全国职称计算机应用能力考试6,全国职称计算机应用能力考试.doc
  16. 《R语言数据挖掘》读书笔记:五、聚类分析
  17. STM32初识及运用—GPIO
  18. GLUT之鼠标事件两点画线 4
  19. Web前端开发的思考与经验----五年工作经验
  20. 华夫饼为什么不松软_只需半个小时,教你轻松制作松软“华夫饼”,健康美味无添加...

热门文章

  1. GIS基础软件及操作(二)
  2. postgresql9.5 run 文件linux安装后配置成开机服务
  3. php 逗号 分割字符串
  4. Backtrader多周期回测
  5. JAVA中的内部类与C++内部类的区别
  6. ubuntu18.04安装mysql数据库
  7. 增加表单的文字段的html的代码是,表单及表单新增元素(示例代码)
  8. linux 双mipi摄像头,VS-RK3399 在linux系统下面调试Mipi camera接口介绍
  9. 猫和老鼠java下载安装_tomcat(Java服务器)
  10. java breakpoint_java断点