网站管理登录,网站投票功能,铁岭做网站哪家好,域名备案官网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 文… 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 区也是存放在 ROMFLASH里面的在执行 main 函数之前 RW有初值且不为 0 的变量数据会被拷贝到 RAM 区同时还会在 RAM 里面创建 ZI 区初始化为 0 的变量。
序号描述① 处表示映像的入口地址也就是整个程序运行的起始地址为 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占用大小为 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 文件编译后所占代码空间的大小。 每个项所代表的意义如下
类型作用Codeinc.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