当前位置: 首页 > news >正文

STM32 map 文件浅析

目录

  • 一、概述
  • 二、Section Cross References
  • 三、Removing Unused input sections from the image
  • 四、Memory Map of the image
    • 1、Local Symbols
    • 2、全局符号(Global Symbols)
  • 五、Image Symbol Table
  • 六、Image component sizes


一、概述

.map 文件是编译器链接时生成的一个文件,它主要包含了交叉链接信息。通过 .map 文件,我们可以知道整个工程的函数调用关系、FLASHRAM 占用情况及其详细汇总信息,能具体到单个源文件(.c/.s)的占用情况,根据这些信息,我们可以对代码进行优化。.map 文件可以分为以下 5 个组成部分:

  1. 程序段交叉引用关系(Section Cross References
  2. 删除映像未使用的程序段(Removing Unused input sections from the image
  3. 映像符号表(Image Symbol Table
  4. 映像内存分布图(Memory Map of the image
  5. 映像组件大小(Image component sizes

我们在 Keil 中最常见的就是在编译之后,编译窗口会显示类似如下一段关于程序和数据大小的信息:

这一段提示信息其实是汇总了程序和数据的信息,这些信息其实是单个模块汇总而成,在 .map 文件里有详细列表。

.map 文件输出信息的配置位于:Project -> Options for Target -> Listing,如下图:

主要包含配置:

  • Memory Map:内存映射
  • Callgraph:图像映射
  • Symbols:符号
  • Cross Reference:交叉引用
  • Size Info:大小信息
  • Totals Info:统计信息
  • Unused Section Info:未调用模块信息
  • Veneers Info:装饰信息

我们可根据自己情况,想要输出什么信息,勾选对应信息即可。

接下来将针对 .map 文件的五部分内容进行讲解。

二、Section Cross References

这部分内容描述了各个文件(.c/.s 等)之间函数(程序段)的调用关系,如下图所示:

比如下面这段:

board.o(i.board_lowlevel_init) refers to stm32f4xx_rcc.o(i.RCC_AHB1PeriphClockCmd) for RCC_AHB1PeriphClockCmd

表示的意思是:board.c 文件中的 board_lowlevel_init 函数调用了 stm32f4xx_rcc.c 文件中的 RCC_AHB1PeriphClockCmd 函数。

i.board_lowlevel_init 表示 board_lowlevel_init 函数的入口地址,同理 i.RCC_AHB1PeriphClockCmd 表示 RCC_AHB1PeriphClockCmd 的入口地址

board.oboard.c 源文件生成的目标文件模块

三、Removing Unused input sections from the image

这部分内容描述了工程中由于未被调用而被删除的冗余程序段(函数/数据):

在结尾还列出了一个统计数据,表示共移除l 849 个程序段,共 37144 字节。

四、Memory Map of the image

映像符号表(Image Symbol Table)描述了被引用的各个符号(程序段/数据)在存储器中的存储地址、类型、大小等信息。映像符号表分为两类:本地符号(Local Symbols)和全局符号(Global Symbols)。

1、Local Symbols

本地符号(Local Symbols)记录了用static 声明的全局变量地址和大小,c 文件中函数的地址和用static 声明的函数代码大小,汇编文件中的标号地址(作用域:限本文件),见下:

下面红框处,表示 stm32f4x_dma.c 文件中的 DMA_ClearFlag 函数的入口地址为 0x080001ec,类型为:Section(程序段)
,大小为 0。

因为:i.sys_stm32_clock_init 仅仅表示 sys_stm32_clock_init 函数入口地址,并不是指令,所以没有大小。在全局符号段,会列出sys_stm32_clock_init 函数的大小。

2、全局符号(Global Symbols)

全局符号(Global Symbols)记录了全局变量的地址和大小,C 文件中函数的地址及其代码大小,汇编文件中的标号地址(作用域:全工程),见下:

  1. Symbol Name:符号名称,名称命名及分类请看最后给出的官方参考文档。
  2. Value:存储对应的地址,大家会发现有 0x0800xxxx0x2000xxxx 这样的地址。0x0800xxxx 指存储在 FLASH 里面的代码、变量等。0x2000xxxx 指存储在内存 RAM 中的变量 Data 等。
  3. Ov Type:符号对应的类型。符号类型大概有几种:NumberSectionThumb CodeData等。
  4. Size:存储大小,就是当前行 Symbol 占用大小。
  5. Object(Section):段目标,这里一般指所在模块(源文件)。

图中红框框处部分,表示 stm32f4x_dma.c 文件中的 DMA_ClearFlag 函数的入口地址为:0x080001ed,类型为:Thumb Code(程序段)
,大小为 38 字节。

注意,此处的地址用的 0x08002bc9,和上一节的 0x080001ec 地址不符,这是因为 ARM 规定 Thumb 指令集的所有指令(Thumb 指令集更节省空间),其最低位必须为 1,0x080001ed = 0x080001ec + 1,所以才会有 2 个不同的地址,且总是差 1,实际上就是同一个函数。

五、Image Symbol Table

映像文件分为加载域(Load Region)和运行域(Execution Region),一个加载域必须有至少一个运行域(可以有多个运行域),而一个程序又可以有多个加载域。加载域为映像程序的实际存储区域,而运行域则是 MCU 上电后的运行状态。加载域和运行域的简化关系(这里仅表示一个加载域的情况)图如下图:

有关内存方面的内容可以参考:单片机内存区域划分

由图可知,RW 区也是存放在 ROM(FLASH)里面的,在执行 main 函数之前,RW(有初值且不为 0 的变量)数据会被拷贝到 RAM 区,同时还会在 RAM 里面创建 ZI 区(初始化为 0 的变量)。

Image Entry point : 0x08000189 表示映射入口地址。

Load Region LR_IROM1 (Base: 0x08000000, Size: 0x00001068, Max: 0x00080000, ABSOLUTE) 表示加载区域位于 LR_IROM1 开始地址0x08000000,大小有 0x00001068,这块区域最大为 0x00080000

执行区域有两段:

  1. Execution Region ER_IROM1:在内部 SRAM 运行域,所有 RAM(包括 RW 和 ZI)都是放在这个运行域里面
  2. Execution Region RW_IRAM1:在内部FLASH 运行域,所有需要放内部 FLASH 的代码,都应该放到这个运行域里面

这个区域,其实就是对应我们目标配置中的区域,如下所示:

  • Exec Addr:执行地址
  • Load Addr:加载地址
  • Size:存储大小
  • Type:类型
    1. Data:数据类型
    2. Code:代码类
    3. Zero:未初始化变量类型
    4. PAD:这个类型在 map 文件中放在这个位置,其实它不能算这里的类型。要翻译的话,只能说的“补充类型”。ARM 处理器是 32 位的,如果定义一个 8 位或者 16 位变量就会剩余一部分,这里就是指的“补充”的那部分,会发现后面的其他几个选项都没有对应的值。
  • Attr:属性
    1. RO:存储在 ROM 中的段
    2. RW:存储在 RAM 中的段
  • Section Name:段名。这里也可以说为入口分类名,大概包含:RESETARM.texti.data.bssHEAPSTACK 等。
  • Object:目标

六、Image component sizes

映像组件大小(Image component sizes)给出了整个映像所有代码(.o)占用空间的汇总信息,对我们比较有用,如图所示:

  • Code:指代码的大小;
  • RO-data:指除了内联数据(inline data)之外的常量数据;
  • RW-data:指可读写(RW)、已初始化的变量数据;
  • ZI-data:指未初始化(ZI)的变量数据;
  • Debug:表示调试数据所占的空间大小,如调试输入节及符号和字符串。
  • Object Totals:表示以上部分链接到一起后,所占映像空间的大小。
  • (incl.Generated):表示链接器生产的映像内容大小,它包含在 Object Totals 里面了,这里仅仅是单独列出,我们一般不需要关心。
  • (incl.Padding::表示链接器根据需要插入填充以保证字节对齐的数据所占空间的大小,它也包含在 Object Totals 里面了,这里单独列出,一般无需关心。
  • CodeRo-data:位于 FLASH 中;
  • RW-dataZI-data:位于 RAM 中;
  • RW-data 已初始化的数据会存储在 Flash 中,上电会从 FLASH 搬移至 RAM


    关系如下:
    R O S i z e = C o d e + R O D a t a R W S i z e = R W D a t a + Z I D a t a R O M S i z e = C o d e + R O D a t a + R W D a t a RO Size = Code + RO Data\\ RW Size = RW Data + ZI Data \\ ROM Size = Code + RO Data + RW Data ROSize=Code+RODataRWSize=RWData+ZIDataROMSize=Code+ROData+RWData

这里表示被提取的库成员(.lib 添加到映像中的部分所占空间大小。各项意义同前面提到的说明。我们一般只用看 Library Totals 来分析库所占空间的大小即可。

  • Grand Totals:表示整个映像所占空间大小。
  • ELF Image Totals:表示 ELF 可执行链接格式映像文件的大小,一般和 Grand Totals 一样大小。
  • ROM Totals:表示整个映像所需要的 ROM 空间大小,不含 ZIDebug 数据。
  • Total RO Size:表示 CodeRO 数据所占空间大小,本例程为:4172 字节。
  • Total RW Size:表示 RWZI 数据所占空间大小,即本映像所需 SRAM 空间的大小,本例程为:6816 字节。
  • Total ROM Size:表示 CodeRORW 数据所占空间大小,即本映像所需 FLASH 空间的大小,本例程为:4200 字节。

相关文章:

  • 互联网前后端分离的开发场景,一般会员和数据权限的判断是放在前端还是后端?
  • 二叉树进阶oj题【二叉树相关10道oj题的解析和c++代码实现】
  • 2024.09.19 校招 实习 内推 面经
  • 简单vue指令实现 el-table 可拖拽表格功能
  • Java 图片合成
  • Unity3D 客户端多开
  • 5个python多线程简单示例
  • 一次实践:给自己的手机摄像头进行相机标定
  • 用于视觉的MetaFormer基线模型
  • 数据结构-4.1.特殊矩阵的压缩存储
  • C++11 多线程编程-小白零基础到手撕线程池
  • 秋招内推--招联金融2025
  • 论文阅读:多模态医学图像融合方法的研究进展
  • 负载均衡架构解说
  • C++ Linux多进程同步-命名信号量
  • CentOS6 编译安装 redis-3.2.3
  • codis proxy处理流程
  • jquery cookie
  • leetcode讲解--894. All Possible Full Binary Trees
  • Mithril.js 入门介绍
  • Node项目之评分系统(二)- 数据库设计
  • overflow: hidden IE7无效
  • v-if和v-for连用出现的问题
  • VuePress 静态网站生成
  • 从零开始在ubuntu上搭建node开发环境
  • 基于 Babel 的 npm 包最小化设置
  • 检测对象或数组
  • 面试总结JavaScript篇
  • 前端技术周刊 2018-12-10:前端自动化测试
  • 容器服务kubernetes弹性伸缩高级用法
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 事件委托的小应用
  • 通过npm或yarn自动生成vue组件
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 小试R空间处理新库sf
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​linux启动进程的方式
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (day18) leetcode 204.计数质数
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (十)Flink Table API 和 SQL 基本概念
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (转) Face-Resources
  • (转)es进行聚合操作时提示Fielddata is disabled on text fields by default
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • (转)人的集合论——移山之道
  • (转载)OpenStack Hacker养成指南
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .NET 常见的偏门问题
  • .net 发送邮件
  • .Net 访问电子邮箱-LumiSoft.Net,好用
  • .NET命名规范和开发约定
  • .sdf和.msp文件读取