【STM32-MAP文件分析】

news2024/11/27 12:39:49

STM32-MAP文件分析

  • ■ MDK编译生成文件简介
    • ■ .o
    • ■ .axf
    • ■ .hex
    • ■ .crf
    • ■ .d
    • ■ .dep
    • ■ .lnp
    • ■ .lst
    • ■ .map
    • ■ .build_log.htm
    • ■ .htm 文件
    • ■ .map 文件
  • ■ map文件分析
    • ■ map 文件的 MDK 设置
      • ■ 1. 要生成 map 文件 在 Listing 选项卡里面
      • ■ 2. Keil5 中打开.map 文件
    • ■ map 文件的基础概念
      • ■ 1. Section:程序段
      • ■ 2. RO: Read Only 的缩写,
      • ■ 3. RW: Read Write 的缩写,
      • ■ 4. ZI: Zero initialized 的缩写,
      • ■ 5. .text:相当于 RO code
      • ■ 6. .constdata:相当于 RO data
      • ■ 7. .bss:相当于 ZI data
      • ■ 8. .data:相当于 RW data
    • ■ map 文件的组成部分说明
      • ■ 1. 程序段交叉引用关系(Section Cross References)
      • ■ 2. 删除映像未使用的程序段(Removing Unused input sectionsfrom the image)
      • ■ 3. 映像符号表(Image Symbol Table)
        • ■ 3.1 本地符号(Local Symbols) 地址和大小
        • ■ 3.2 全局符号( Global Symbols)地址和大小
      • ■ 4. 映像内存分布图( Memory Map of the image)
      • ■ 5. 映像组件大小(Image component sizes)

■ MDK编译生成文件简介

MDK 编译工程,会生成一些中间文件(如 .axf、 .crf、 .d、 .dep、.hex、 .lnp、 .lst、 .o、 .htm、 bulild_log.htm 和.map等),最终生成 hex 文件,编译过程产生的所有文件,都存放在 Output 文件夹下
在这里插入图片描述

■ .o

可重定向 1对象文件,每个源文件(.c/.s 等)编译都会生成一个.o 文件
它是由编译器编译.c/.s 文件时所产生的可重定向对象文件,其文件名同.c/.s 文件一模一样,只是后缀为.o。所以,我们看到.o 就应该想到与之对应的.c 或者.s 文件,我们在分散加载里面经常会用到.o 文件。

■ .axf

由 ARMCC 编译生产的可执行对象文件,不可重定向 2(绝对地址)
多个.o 文件链接生成.axf 文件,我们在仿真的时候,需要用到该文件,
由 armlink 链接器,将整个工程参与编译的.o 文件链接成一个可执行对象文件,它是不可重定向的。有了该文件,我们就可以用仿真器来下载到 MCU 进行仿真调试了。
注意:各类仿真器,在进行下载调试的时候,都是使用的.axf 文件。

■ .hex

Intel Hex 格式文件,可用于下载到 MCU, .hex 文件和.bin 文件由.axf 文件转换而来可执行的对象文件
.hex 文件和.bin 文件的区别是: .bin 文件不含地址信息,全部都是可执行代码;而.hex 文件则是包含地址信息的可自行代码。
我们在使用 ISP 软件进行程序下载的时候,
一般使用的是.hex 文件,由 ISP 软件解析.hex 文件包含的地址信息来实现程序下载。而我们在进行 BootLoader 升级的时候,一般使用.bin 文件,地址由 Bootloader 程序指定。

■ .crf

交叉引用文件,包含浏览信息(定义、标识符、引用)

■ .d

由 ARMCC/GCC 编译生产的依赖文件(.o 文件所对应的依赖文件)
每个.o 文件,都有一个对应的.d 文件

■ .dep

整个工程的依赖文件

■ .lnp

MDK 生成的链接输入文件,用于命令输入

■ .lst

C 语言或汇编编译器生成的列表文件

■ .map

连接器生成的列表文件/MAP 文件, 该文件对我们非常有用!

■ .build_log.htm

最近一次编译工程时的日志记录文件

■ .htm 文件

链接生成的列表文件
它是编译器在编译代码的时候生成的一个列表文件, 包含了整个工程的静态调用图, 最大的用处就是可以查看栈深度(最小深度),方便设置栈大小。
它是编译器在编译代码的时候生成的一个列表文件, 包含了整个工程的静态调用图, 最大的用处就是可以查看栈深度(最小深度),方便设置栈大小。 .htm 文件可以直接由浏览器打开(双击打开)。 .htm 文件包含两部分内容:
1, 整个工程最大栈(Stack) 深度及其调用关系
我们打开:新建工程例程→Output→atk_h750.htm 文件(双击,注意:必须整个工程编译一遍,才会生成 atk_h750.htm 文件,否则是找不到这个文件的!),可以看到如图 1.2 所示:
在这里插入图片描述
可以看到,例程的最大栈深度是 416 字节,最大栈深时的调用关系为: __rt_entry_main⇒ main ⇒ sys_stm32_clock_init ⇒AL_RCC_ClockConfig ⇒ HAL_InitTick ⇒HAL_NVIC_SetPriority ⇒ __NVIC_SetPriority。

不过需要注意的是,这里的最大栈深度仅仅是最低要求(静态栈),因为它并没有统计无栈深的函数(用内存管理)、递归函数、以及无法追踪的函数(函数指针)等所包含的栈(Stack)。
不过它给我们指明了最低需求,我们在分配栈深度的时候,就可以参考这个值来做设置,一般不低于静态栈的2倍。我们例程默认设置的栈深(Stack_Size)为0X800(通过.s文件设置),

2, 各个函数的栈深及其调用关系
.htm 文件还给出了每个函数所使用的栈深度以及其调用关系,如图 1.3 所示:
在这里插入图片描述
上图给出了 sys_stm32_clock_init 函数的最大栈深度及其调用关系,并且列出了其所调用的函数及其所被调用的函数。

■ .map 文件

对我们编程非常有帮助,是本文档重点要给大家介绍的,因此另起一节,进行重点说明。
其他文件类型及说明,请大家参考: MDK→help→uVision Help→B. File Types,如图 1.3所示:
在这里插入图片描述

■ map文件分析

map 文件是编译器链接时生成的一个文件,它主要包含了交叉链接信息。通过.map 文件,我们可以知道整个工程的函数调用关系、 FLASH 和 RAM 占用情况及其详细汇总信息,能具体到单个源文件(.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)

接下来,我们将分三个部分对 map 文件进行详细介绍:
1, map 文件的 MDK 设置
2, map 文件的基础概念
3, map 文件的组成部分说明

■ map 文件的 MDK 设置

■ 1. 要生成 map 文件 在 Listing 选项卡里面

要生成 map 文件,我们需要在 MDK 的魔术棒→Listing 选项卡里面,进行相关设置,如图 2.1.1 所示:
在这里插入图片描述
中红框框出的部分就是我们需要设置的,默认情况下, MDK 这部分设置就是全勾选的,如果我们想取消掉一些信息的输出,则取消相关勾选即可(一般不建议)。

■ 2. Keil5 中打开.map 文件

双击工程目标 LED(不同工程名字可能不一样),打开.map 文件。
在这里插入图片描述

■ map 文件的基础概念

为了更好的分析 map 文件,我们先对需要用到的一些基础概念进行一个简单介绍,相关概念如下:

■ 1. Section:程序段

描述映像文件的代码或数据块,我们简称程序段

■ 2. RO: Read Only 的缩写,

包括只读数据(RO data)和代码(RO code)两部分内容,占用 FLASH 空间

■ 3. RW: Read Write 的缩写,

包含可读写数据(RW data,有初值,且不为 0),占用 FLASH(存储初值)和 RAM(读写操作)

■ 4. ZI: Zero initialized 的缩写,

包含初始化为 0 的数据(ZI data),占用 RAM 空间。

■ 5. .text:相当于 RO code

■ 6. .constdata:相当于 RO data

■ 7. .bss:相当于 ZI data

■ 8. .data:相当于 RW data

■ map 文件的组成部分说明

■ 1. 程序段交叉引用关系(Section Cross References)

这部分内容描述了各个文件(.c/.s 等)之间函数(程序段)的调用关系,在这里插入图片描述
main.o(i.main) refers to sys.o(i.sys_stm32_clock_init) for sys_stm32_clock_init, 表示:
main.c文件中的main函数,调用了sys.c中的sys_stm32_clock_init函数。
其中:
i.main 表示 main 函数的入口地址
i.sys_stm32_clock_init 表示sys_stm32_clock_init 的入口地址。

■ 2. 删除映像未使用的程序段(Removing Unused input sectionsfrom the image)

这部分内容描述了工程中由于未被调用而被删除的冗余程序段(函数/数据),
在这里插入图片描述
例如 main.c 中没有调用到的rev16_text 等文件将被移除。

另外,在最后还有一个统计信息: 361 unused section(s) (total 43234 bytes) removed fromthe image. 表示总共移除了 361 个程序段(函数/数据),大小为 43234 字节。即给我们的MCU 节省了 43234 字节的程序空间。

为了更好的节省空间,我们一般在 MDK→魔术棒→C/C++选项卡里面勾选: One ELFSection per Function,如图 2.1.2.2 所示:
在这里插入图片描述

■ 3. 映像符号表(Image Symbol Table)

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

■ 3.1 本地符号(Local Symbols) 地址和大小

记录了用 static 声明的全局变量地址和大小, c 文件中函数的地址和 用 static 声明的函数代码大小,汇编文件中的标号地址(作用域: 限本文件)
在这里插入图片描述
图中红框框处部分,表示 sys.c 文件中的 sys_stm32_clock_init 函数的入口地址为:0x08002bc8,类型为: Section(程序段),大小为 0。因为: i. sys_stm32_clock_init 仅仅表示 sys_stm32_clock_init 函数入口地址,并不是指令,所以没有大小。
在全局符号段,会列出sys_stm32_clock_init 函数的大小。
在这里插入图片描述

■ 3.2 全局符号( Global Symbols)地址和大小

全局符号(Global Symbols) 记录了全局变量的地址和大小, C 文件中函数的地址及其代码大小,汇编文件中的标号地址(作用域: 全工程), 全局符号如图 2.1.3.2.1 所示:
在这里插入图片描述
图中红框框处部分
表示 sys.c 文件中的 sys_stm32_clock_init 函数的入口地址为:0x08002bc9,类型为: Thumb Code(程序段),大小为 344 字节。
在这里插入图片描述

注意,此处Local Symbols: 的地址用的 0x080003e8,和Global Symbols: 0x080003e9地址不符,这是因为ARM 规定 Thumb 指令集的所有指令,其最低位必须为 1, 0x080003e9= 0x080003e8+ 1,所以才会有 2 个不同的地址,且总是差 1,实际上就是同一个函数。

Local Symbols:
在这里插入图片描述
Global Symbols:
在这里插入图片描述

■ 4. 映像内存分布图( Memory Map of the image)

映像文件分为加载域( Load Region)和运行域( Execution Region)
一个程序可以有多个加载域, 一个加载域必须有至少一个运行域(可以有多个运行域)。
加载域为映像程序的实际存储区域,而运行域则是 MCU 上电后的运行状态。加载域和运行域的简化关系(这里仅表示一个加载域的情况)
在这里插入图片描述
由图可知, RW 区也是存放在 ROM(FLASH)里面的,在执行 main 函数之前, RW(有初值且不为 0 的变量)数据会被拷贝到 RAM 区,同时还会在 RAM 里面创建 ZI 区(初始化为 0 的变量)。
在这里插入图片描述

序号描述
① 处表示映像的入口地址,也就是整个程序运行的起始地址,为: 0X0800 0299。 实际地址为: 0X0800 0298(Thumb 指令最低位是 1)。
② 处表示 LR_m_stmflash 加载域, 其起始地址为: 0X0800 0000;占用大小为: 0X0000 2D8C; 最大地址范围为: 0X0002 0000。
其内部包含两个运行域: ER_m_stmflash和 RW_m_stmsram。
③ 处表示 ER_m_stmflash 运行域,其起始地址为: 0X0800 0000;占用大小为: 0X0000 2D6C;最大地址范围为: 0X0002 0000;即 内部 FLASH 运行域,所有需要放内部 FLASH 的代码,都应该放到这个运行域里面。
对于 STM32F1/F4/F767 等开发板, 我们例程所有的代码,都是放在这个运行域的(名字可能不一样)。
④ 处表示 RW_m_stmsram 运行域,其起始地址为:0X2400 0000;占用大小为: 0X0000 2D6C;最大地址范围为: 0X0008 0000;即内部 SRAM 运行域,所有 RAM(包括 RW 和 ZI)都是放在这个运行域里面。
⑤ 处表示 LR_m_qspiflash 加载域,其起始地址为: 0X9000 0000;占用大小为: 0X0000 0720;最大地址范围为: 0X0080 0000。
其内部包含一个运行域: ER_m_qspiflash。
⑥ 处表示 ER_m_qspiflash 运行域,其起始地址为: 0X9000 0000;占用大小为: 0X0000 0720;最大地址范围为: 0X0080 0000;即外部 QSPI FLASH 运行域,所有需要放 外部 QSPI FLASH 的代码,都应该放到这个运行域里面。

如 sys_stm32_clock_init 函数:该函数在 ER_m_stmflash 运行域;入口地址为: 0X0800 2BC8;大小为: 0X168 字节;是 sys.c里面的函数。了解这些信息,对我们分析及优化程序非常有用。

■ 5. 映像组件大小(Image component sizes)

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

在这里插入图片描述

在这里插入图片描述

① 处,表示.c/.s 文件生成对象所占空间大小(单位:字节,下同),即.c/.s 文件编译后所占代码空间的大小。
每个项所代表的意义如下:

类型作用
Code(inc.data):表示包含内联数据(inc.data)后的代码大小。
如 delay.o(即delay.c)所占的 Code 大小为 142 字节,其中 8 字节是内联数据。
RO Data:表示只读数据所占的空间大小,一般是指 const 修饰的数据大小。
RW Data:表示有初值(且非 0)的可读写数据所占的空间大小,它同时占用 FLASH和 RAM 空间。
ZI Data:表示初始化为 0 的可读写数据所占空间大小,它只占用 RAM 空间。
Debug:表示调试数据所占的空间大小,如调试输入节及符号和字符串。
Object Totals:表示以上部分链接到一起后,所占映像空间的大小。

(incl.Generated):表示链接器生产的映像内容大小,它包含在 Object Totals 里面了,这里仅仅是单独列出,我们一般不需要关心。
(incl.Padding) :表示链接器根据需要插入填充以保证字节对齐的数据所占空间的大小,它也包含在 Object Totals 里面了,这里单独列出,一般无需关心。

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

③ 处,表示本工程全部程序汇总后的占用情况。其中:

类型作用
Grand Totals:表示整个映像所占空间大小。
ELF Image Totals:表示 ELF 可执行链接格式映像文件的大小,一般和 Grand Totals一样大小。
ROM Totals:表示整个映像所需要的 ROM 空间大小,不含 ZI 和 Debug 数据。
Total RO Size:表示 Code 和 RO 数据所占空间大小,本例程为: 13452 字节。
Total RW Size:表示 RW 和 ZI 数据所占空间大小,即本映像所需 SRAM 空间的大小,本例程为: 3032 字节。
Total ROM Size:表示 Code、 RO 和 RW 数据所占空间大小,即本映像所需 FLASH空间的大小,本例程为: 13484 字节。

打开debug后的Image component sizes
在这里插入图片描述

在这里插入图片描述
关闭debug后的Image component sizes
在这里插入图片描述

在这里插入图片描述

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

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

相关文章

如何用GO语言实现冒泡排序算法?

本章教程,介绍一下如何用GO语言实现基础排序算法中的冒泡排序。 一、程序代码 package mainimport ("fmt""math/rand""time" )// bubbleSort 函数实现冒泡排序算法 func bubbleSort(arr []int) {n

【面试干货】 Java 中的 HashSet 底层实现

【面试干货】 Java 中的 HashSet 底层实现 1、HashSet 的底层实现2、 HashSet 的特点3、 总结 💖The Begin💖点点关注,收藏不迷路💖 HashSet 是 Java 集合框架中的一个重要成员,它提供了不存储重复元素的集合。但是&am…

诺瓦星云入职认知能力SHL测验Verify职业性格问卷OPQ可搜索带解析求职题库

欢迎您开启诺瓦星云的求职旅程 恭喜您进入测评环节,接下来您需要作答两个测验,分别是职业性格问卷OPQ和认知能力测验Verify,总共用时大约1小时,祝您作答顺利! 【华东同舟求职】由资深各行业从业者建立的一站式人才服务网络平台&a…

蓝桥杯 经典算法题 合并排序数组

题目: 题解: leetcode上也有这道题一模一样。和归并排序的小过程基本一模一样,只不过因为题目要求只能将arr2中元素合并到arr1中,一种可行的方法是按元素从大到小,顺序从每个序列尾部开始操作,第一填的位置…

Introduction to linear optimization 第 2 章课后题答案 11-15

线性规划导论 Introduction to linear optimization (Dimitris Bertsimas and John N. Tsitsiklis, Athena Scientific, 1997), 这本书的课后题答案我整理成了一个 Jupyter book,发布在网址: https://robinchen121.github.io/manual-introdu…

2024年AI+游戏赛道的公司和工具归类总结

随着人工智能技术的飞速发展,AI在游戏开发领域的应用越来越广泛。以下是对2024年AI+游戏赛道的公司和工具的归类总结,涵盖了从角色和场景设计到音频制作,再到动作捕捉和动画生成等多个方面。 2D与3D创作 2D创作工具:专注于角色和场景的平面设计,提供AI辅助的图案生成和风…

【GUI】LVGL无操作系统移植以及移植过程错误处理

目录 介绍 1. 删除源码 2. 导入lvgl到项目screen_mcu中 3. keil添加分组和头文件 4. 移植显示 5. 移植触摸 6. 添加测试案例 6.1. 测试按钮 6.2. 测试音乐界面 7. 提供时钟 错误处理 L6218E错误 出现花屏 屏幕颜色不对 内存分配 介绍 本文 主要介绍GD32移植…

网络编程(TCP协议,UDP协议)

目录 网络编程三要素 IP IPv4 InetAddress类 端口号 协议 UDP协议 UDP协议发送数据 UDP协议接收数据 UDP的三种通信方式(代码实现) TCP协议 TCP通信程序 三次握手和四次挥手 练习 1、客户端:多次发送数据服务器:接收多次接收数据,并打印 2、客户端…

Mysql安装 /lib64/libc.so.6: version `GLIBC_2.28‘ not found 缺少 glibc-2.28.tar.gz

问题:安装Mysql出现 Error mysql/bin/mysqld: /lib64/libm.so.6: version GLIBC_2.27 not found (required by mysql/bin/mysqld) mysql/bin/mysqld: /lib64/libc.so.6: version GLIBC_2.28 not found (required by mysql/bin/mysqld) mysql/bin/mysqld: /lib64/lib…

云计算之CDN

目录 一.什么是CDN? 二.使用CDN的好处: 三.主要特点: 四.关键功能: 一.什么是CDN? 1.CDN的全称是Content Delivery Network,即内容分发网络。其基本思路是尽可能避开互联网上有可能影响数据传输速度和…

LabVIEW电动汽车核心部件检测系统

LabVIEW开发的电动汽车核心部件检测系统,通过硬件接入板和数据采集卡实现信号采集和分析。系统具备智能诊断、模块化设计和用户友好的特点,能够快速、精确地定位故障,提高电动汽车的维护效率和可靠性,支持新能源汽车市场的快速发展…

【教程】PVE下uhd630核显直通HDMI输出 以NUC9为例村雨Murasame

大家好,村雨本雨又来发教程了 最近在搞小主机,之前hp400g3仅仅200多元成功核显直通HDMI,作为简单NAS、解码机、伺服机、中控都非常棒,待机仅9w 村雨Murasame:【教程】7代核显直通HDMI成功输出画面 PVE下7代intel核显…

多路h265监控录放开发-(8)完成摄像机管理的修改和删除功能

xviewer.h public:XViewer(QWidget* parent Q_NULLPTR);//编辑摄像机void SetCam(int index);//121 public slots:void AddCam(); //新增摄像机配置120void SetCam(); //121void DelCam(); //121 private:Ui::XViewerClass ui;QMenu left_menu_; xviewer.cpp void XView…

2024最新1小时零基础编写uniapp和小程序管理后台,基于uniadmin和vue3实现uniapp小程序的网页管理后台

一,创建uniAdmin项目 打开开发者工具Hbuilder,然后点击左上角的文件,点新建,点项目。如下图。 选择uniadmin,编写项目名,然后使用vue3 记得选用阿里云服务器,因为最便宜 点击创建,等待项目创…

Postman 接口测试 安装使用教程

1 下载官网:https://www.postman.com/downloads/ 2 方便下载,特提供百度云网盘: 链接:Postman 3 windows10 安装,点击安装包 #自动安装,并打开 4 举例,比如豆瓣,get 查询时间,图片登 5 举例&#xff0…

Android网络编程之Http通信

//使用HttpURLConnection打开连接 2.HttpURLConnection urlConn (HttpURLConnection) url.openConnection(); //得到读取的内容(流) 4.InputStreamReader in new InputStreamReader(urlConn.getInputStream()); // 为输出创建BufferedReader BufferedReader buffer new …

小米测开二面—80min中核

小米测开二面—80min中核 3.28 无自我介绍直接开问!你的第一份实习是一个开发工作你的第二实习为什么又跑到测试了你的第一份实习遇到了哪些挑战你的逆向开发的开发目标是什么,使用了什么工具你最终开发落地是用在了什么方面上,比如机器人路…

【FPGA + Nvidia/算能GPU+AI】自动驾驶多核异构实现 16路车载摄像头实时AI分析解决方案

基于 Xilinx 公司ZYNQ Ultrascale MPSoC系列 FPGA 芯片设计,应用于无人驾驶、慢速特种车及数据采集车、车载仿真测试系统等自动驾驶领域 自动驾驶:16通道车载摄像头PCIE采集卡方案。 16 通道摄像头 最多支持 16 通道 GMSL1/2 摄像头输入 8MP 摄像头 最…

[火灾警报系统]yolov5_7.0-pyside6火焰烟雾识别源码

国内每年都会发生大大小小的火灾,造成生命、财产的损失。但是很多火灾如果能够早期发现,并及时提供灭火措施,将会大大较小损失。本套源码采用yolov5-7.0目标检测算法结合pyside6可视化界面源码,当检测到火灾时,能否发出…

BGP路由反射器实验

实验内容: 通过本实验验证bgp路由反射器的规则 1. 从client收到的路由更新,反射到non-client和client,同时发送给EBGP邻居 2. 从non-client收到的路由更新,只反射到client,同时发送给EBGP邻居 3. 从EBGP邻居收到的路…