F407/103MAP文件

news2024/11/16 19:38:59

认识MAP文件

MDK编译工程,会生成一些中间文件(如.o.axf.map 等),最终生成hex文件,以便下载到MCU上面执行。这些文件分为 11 个类型,其中4种文件比较重要。

比如:

本文主要讲解map文件。

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 文件进行详细介绍:

1map 文件的 MDK 设置

2map 文件的基础概念

3map 文件的组成部分说明

map 文件的 MDK 设置

要生成 map 文件,我们需要在 MDK 的魔术棒Listing 选项卡里面,进行相关设置,如图 2.1.1 所示:

图 2.1.1 .map 文件生成设置

2.1.1 中红框框出的部分就是我们需要设置的,默认情况下,MDK 这部分设置就是全勾选的,如果我们想取消掉一些信息的输出,则取消相关勾选即可(一般不建议)。

如图 2.1.1 设置好 MDK 以后,我全编译当前工程,当编译完成后(无错误),就会生成.map文件。在 MDK 里面打开.map 文件的方法如图 2.1.2 所示:

注意,如果双击没反应,则需要调整Listing到对应的存放位置。

map 文件的基础概念

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

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

RORead Only 的缩写,包括只读数据(RO data)和代码(RO code)两部分内容,

占用 FLASH 空间

RWRead Write 的缩写,包含可读写数据(RW data,有初值,且不为 0),占用 FLASH

(存储初值)和 RAM(读写操作)

ZIZero initialized 的缩写,包含初始化为 0 的数据(

ZI data),占用 RAM 空间。

.text:相当于 RO code

.constdata:相当于 RO data

.bss:相当于 ZI data

.data:相当于 RW data

map 文件的组成部分说明

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

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

所示:

上图中,红框框出的部分: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 的入口地址。

删除映像未使用的程序段(Removing Unused input sections from the image

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

上图中,列出了所有被移除的程序段,比如 stm32h7xx_hal_usart_ex.c 文件里面的

USARTEx_SetNbDataToProcess 函数就被移除了,因为该例程没用到这个函数。

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

MCU 节省了 43234 字节的程序空间。

为了更好的节省空间,我们一般在 MDK魔术棒C/C++选项卡里面勾选:One ELF Section per Function,如图 2.1.2.2 所示:

映像符号表(Image Symbol Table

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

本地符号Local Symbols

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

图中红框框处部分,表示 sys.c 文件中的 sys_stm32_clock_init 函数的入口地址为:0x08002bc8,类型为:Section(程序段),大小为 0。因为:i. sys_stm32_clock_init 仅仅表示sys_stm32_clock_init 函数入口地址,并不是指令,所以没有大小。在全局符号段,会列出sys_stm32_clock_init 函数的大小。

全局符号Global Symbols

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

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

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

映像内存分布图(Memory Map of the image

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

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

了解了加载域和运行域的作用及关系,我们再来看映像内存分布图(H750 例程),如图

2.1.4.2 所示:

① 处,表示映像的入口地址,也就是整个程序运行的起始地址,为:0X0800 0299。实际地址为:0X0800 0298Thumb 指令最低位是 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;占用大小为:0X00002D6C;最大地址范围为: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 的代码,都应该放到这个运行域里面。

2.1.4.2 中,列出了所有加载域及其运行域的具体内存分布,我们可以很方便的查看任何一个函数所在的运行域、入口地址、占用空间等信息。如 sys_stm32_clock_init 函数:

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

映像组件大小(Image component sizes

映像组件大小(Image component sizes)给出了整个映像所有代码(.o)占用空间的汇

总信息,对我们比较有用,如图 2.1.5.1 所示:

上图中,框出的三处信息对我们比较有用,接下来分别介绍:

① 处,表示.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:表示 CodeRO RW 数据所占空间大小,即本映像所需 FLASH空间的大小,本例程为:13484 字节。

2.1.5.1 中,我们未框出的:Library Name 部分,实际和②处是一个意思,只是 Library Name 说明了②处的那些.o 文件来自什么库,这里实际上就是:fpinit.o 来自 fz_wv.l 库,其 他部分来自 c_w.l 库。fz_wv.l c_w.l 是库名字。

MAP 文件的分析就给大家介绍到这里。

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

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

相关文章

第四章 死锁

目录 一、死锁的概念 1.1 什么是死锁 1.2 死锁、饥饿、死循环的区别 1.2.1 死锁 1.2.2 饥饿 1.2.3 死循环 1.2.4 三者间的异同 1.3 死锁产生的必要条件 1.3.1 互斥条件 1.3.2 不剥夺条件 1.3.3 请求和保持条件 1.3.4 循环等待条件 1.4 什么时候会发生死锁 1.5 …

深入理解Java中的synchronized

文章目录 前言正文一、多线程操作同一数据时的问题二、问题分析三、synchronized 解决问题四、synchronized 是怎么解决问题的五、Java1.6时的优化5.1 自旋锁5.2 自适应锁5.3 锁消除5.4 锁粗化5.5 偏向锁(单线程高效场景)5.2 轻量级锁(多线程…

MySQL数据表查询

😇作者介绍:一个有梦想、有理想、有目标的,且渴望能够学有所成的追梦人。 🎆学习格言:不读书的人,思想就会停止。——狄德罗 ⛪️个人主页:进入博主主页 🗼专栏系列:进入MySQL知识专…

IO、存储、文件系统的简单介绍

目录 一.什么是IO 第一类:存储器IO 第二类:设备IO 二.存储 三:文件系统 总结 一.什么是IO I(input):放入数据 O(output):取出数据 所以我们平时说的IO,实际上就是放入数据和存储数据的意思 在这里,我们一般将IO又分为两大类 第一类:存储器IO 这类IO主要针对的是计算机中…

2023年最新同步网盘排行榜,了解哪些平台适合您的文件同步需求!

在数码领域,同步盘是一个极其受欢迎的工具,它可以帮助人们在不同设备之间共享文件。作为同步盘用户,我们关心的一个很重要的问题就是,在同步盘市场上,哪些同步盘是最好的? 今天我们综合了不同的产品测评网站…

Vulnhub: Corrosion:2靶机

kali:192.168.111.111 靶机:192.168.111.131 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.131 通过nmap脚本枚举出8080端口存在backup.zip文件,下载后解压发现需要密码,利用john爆破压缩包密…

【SSM项目整合流程】

目录 一.用Maven创建一个project项目 1.1新建一个项目,选择Maven然后点击下一步 1.2设置项目名称和AGV后点击完成 1.3在pom.xml文件中导入依赖和配置打包方式 二.添加web工程 2.1在Project Structure中型添加一个web工程 2.2配置web.xml 三.创建SpringMVC的…

2.设置Salesforce开发环境

文章目录 前言1. 关于Salesforce DX环境2. 配置Visual Studio Code2.1 安装CLI2.2 设置Visual Studio Code 3. 创建一个Hello World Lightning web component 来检证开发环境3.1 创建一个Salesforce DX project3.2 将deploy好的组件加到lightning App中 前言 此处解释关于本文…

数据结构——C语言实现常见排序(插入排序、希尔排序、选择排序、堆排序、冒泡排序)

引言: 现在是北京时间2023年6月23日13点19分,度过了一个非常愉快的端午节。由于刚从学校回家,一下子伙食强度直升了个两三个档次。这也导致我的肠胃不堪重负,我也准备等会去健身房消耗一下盈余的热量。回到家陪伴爷爷走人生最后的…

C++11 线程库—线程操作(更新中)

前言 在C11推出线程库前,Windows和Linux操作系统的线程操作并不同,这就导致多线程程序无法跨平台,如果想要跨平台,会很麻烦并且容易出错。C11推出的线程库就解决了这一问题。 因为在Windows和Linux操作系统中有一些独特的常量&am…

OpenGL 鼠标拾取模型

1.简介 在我们的场景中,使用鼠标光标点击或“挑选”一个3d对象是很有用的。一种方法是从鼠标投射3d光线,通过相机,进入场景,然后检查光线是否与任何物体相交。这通常被称为光线投射。 我们不是从局部空间中的网格开始&#xff0c…

gRPC 实践

RPC 包管理,1.12前;旧版本要设置GO111MODULEoff;查找gopath/src;goroot/src;几乎没有包管理; 新版本;go.mod; module xxx go version设置GO111MODULEon 是什么 远程过程调用; …

Windows页面置换算法与文件操作

实验一 一、实验内容或题目: 随机产生页面访问序列,并实现LRU, FIFO, OPT三种算法进行缺页比较 二、实验目的与要求: 1、编写程序,随机产生页面访问序列,并实现LRU, FIFO, OPT三种算法进行缺页比较。 2、理解三种算…

自监督学习简介

1.  自监督学习 自监督学习是可以看做是一种特殊的无监督学习的一个子类别(但并非无监督学习),因为它利用了未标记的数据。 关键思想是让模型无需手动标签即可学习数据表示。一旦模型学会了如何表示数据,那么它就可以用较少量的…

liunx+docker+rabbitmq安装延迟队列插件

安装版本 rabbit: RabbitMQ 3.8.16 erlang: Erlang 23.3.2 rabbit: rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez 准备 1.rabbmitMQ 安装 docker pull rabbitmq 2.rabbmitMQ 启动 docker run -d --hostname my-rabbit --name rabbit -e RABBITMQ_DEFAULT_USER用户…

10 种分布式系统必备模式

在当今的技术领域中,分布式系统已成为许多大型应用程序和平台的核心。构建高性能、可伸缩和可靠的分布式系统是一个复杂的挑战,需要合理的架构设计和模式选择。本文将介绍10个必备的分布式系统模式,帮助您更好地理解和应用这些模式以提升系统…

pytorch笔记:RNN 系列

来自B站视频,API查阅,TORCH.NN RNN可以处理变长序列,是因为其每个时刻的参数是共享的RNN每算出一个时刻都可以输出,适合流式输出,但串行计算比较慢,无法获取太长的历史信息RNN 初始隐状态不提供默认是0&am…

一、枚举类型——用枚举实现状态机

枚举类型很适合用来实现状态机。状态机可以处于有限数量的特定状态。它们通常根据输入,从一个状态移动到下一个状态,但同时也会存在瞬态。当任务执行完毕后,状态机会立即跳出所有状态。 每个状态都有某些可接受的输入,不同的输入…

你应该知道的 Python 自动化脚本

概要 我们都有一些需要重复做的任务。幸运的是,我们可以将其中一些过程自动化,这样我们就可以专注于做其他真正需要精力和注意力的事情。 在这篇文章中,我们将谈论一些 Python 自动化脚本,你可以轻松地用它们来执行自动化任务。重…

巨星内马尔为孕期出轨道歉了!喊话女友:“我不能想象失去你”

近日,巴西球星内马尔在女友布鲁娜孕期出轨的传闻引起了社会广泛关注。 22日凌晨,内马尔在自己的社交媒体上发文回应并道歉,表示自己在球场内外都会犯错,但私生活的问题他会在家里解决。 他还重申了自己已经为犯下的错误和不必要的…