历史上的今天

今天是:2024年11月01日(星期五)

正在发生

2021年11月01日 | stm32专题三十六:MDK编译过程和文件类型(三)

发布者:SecretWhisper 来源: eefocus关键字:stm32  MDK  编译过程  文件类型 手机看文章 扫描二维码
随时随地手机看文章

生成 bin 和 hex文件


若编译过程无误,即可把工程生成前面对应的*.axf 文件,而在 MDK 中使用下载器(DAP/JLINK/ULINK 等)下载程序或仿真的时候, MDK 调用的就是*.axf 文件,它解释该文件,然后控制下载器把*.axf 中的代码内容下载到 STM32 芯片对应的存储空间,然后复位后芯片就开始执行代码了。


然而,脱离了 MDK 或 IAR 等工具,下载器就无法直接使用*.axf 文件下载代码了,它们一般仅支持 hex 和 bin 格式的代码数据文件。默认情况下 MDK 都不会生成 hex 及 bin 文件,需要配置工程选项或使用 fromelf 命令。


fromelf的命令描述:

bin 和 hex 文件详解


bin文件就是纯二进制数据,无特殊格式。


hex 是 Intel 公司制定的一种使用 ASCII 文本记录机器码或常量数据的文件格式,这种文件常常用来记录将要存储到 ROM 中的数据,绝大多数下载器支持该格式。


hex格式的具体描述如下所示,非常重要。

5个记录,每部分的具体意义:

接下来,我们分析一下这几条hex文件的内容和意义:

用vscode打开我们生成的hex文件如下,可以看到,与上述hex格式编码要求一致。

为了更清楚地对比 bin、 hex 及 axf 文件的差异,我们来查看这些文件内部记录的信息来进行对比:

注意,bin文件直接用记事本打开会乱码,因为windows记事本默认是ASCII编码格式,而bin文件不是ASCII格式存储,所以记事本打开会是乱七八糟的乱码。


接下来,我们对比看一下bin hex文件的大小:


bin文件:


可以看到,bin文件大小为1440字节,而占用的空间是4096字节。为什么会有这个区别?


因为博主使用的windows系统,一个文件最小是4096字节,文件占用的空间都必须是4096的倍数。再进一步分析,为什么bin文件是1440字节?

实际上,1440 = 1096 + 336 + 8,bin文件的大小,就是实际上要存储在flash的数据大小。所以,bin文件是一种很纯粹的数据格式。


hex文件:

可以看到,hex的实际大小为4101字节(>4096),只比4096字节超出一点点。但windows使用的文件系统,就是会占用到


8192 = 2 * 4096字节的存储空间。


axf文件:

axf文件,可以看到,要比bin文件和hex文件大很多,因为其中还存储了各种MDK文件类型信息。我们可以直接使用fromelf工具,来对axf文件进行反汇编,来得到汇编代码,进而破解别人的程序。

下面是bin hex elf反汇编的比较:

 

 

htm静态调用图文件

我们打开对应的流水灯.htm文件,如下所示:

该文件说明了本工程的静态栈空间最大占用 40 字节(Maximum Stack Usage:40bytes),这个占用最深的静态调用为“ main->LED_GPIO_Config->GPIO_Init”。注意这里给出的空间只是静态的栈使用统计,链接器无法统计动态使用情况,例如链接器无法知道递归函数的递归深度。在本文件的后面还可查询到其它函数的调用情况及其它细节。利用这些信息,我们可以大致了解工程中应该分配多少空间给栈,有空间余量的情况下,一般会设置比这个静态最深栈使用量大一倍,在 STM32 中可修改启动文件改变堆栈的大小;如果空间不足,可从该文件中了解到调用深度的信息,然后优化该代码。

map文件




如何打开 map 文件?1 直接在Listing目录下打开;2 在 MDK 中双击目标选项,即可打开 map 文件;

注意,在查看 map 文件时,要勾选 MDK 的如下选项配置:

选项One ELF Section per Function的主要功能是对冗余函数的优化。通过这个选项,可以在最后生成的二进制文件中将冗余函数排除掉(虽然其所在的文件已经参与了编译链接),以便最大程度地优化最后生成的二进制代码。


而该选项实现的机制是将每一个函数作为一个优化的单元,而并非整个文件作为参与优化的单元。

选项One ELF Section per Function所具有的这种优化功能特别重要,尤其是在对于生成的二进制文件大小有严格要求的场合。人们习惯将一系列接口函数放在一个文件里,然后将其整个包含在工程中,即使这个文件将只有一个函数被用到。这样,最后生成的二进制文件中就有可能包含众多的冗余函数,造成了宝贵存储空间的浪费。


选项One ELF Section per Function对于一个大工程的优化效果尤其突出,有时候甚至可以达到减半的效果。当然,对于小工程或是少有冗余函数的工程来说,其优化效果就没有那么明显了。


打开“流水灯.map”文件,可看到它的第一部分——节区的跨文件引用(Section Cross References):


我们来看一下 map 文件:

在这部分中,详细列出了各个*.o 文件之间的符号引用。由于*.o 文件是由 asm 或 c/c++源文件编译后生成的,各个文件及文件内的节区间互相独立,链接器根据它们之间的互相引用链接起来,链接的详细信息在这个“Section Cross References”一一列出。例如,开头部分说明的是 startup_stm32f10x.o 文件中的“RESET”节区分为它使用的“__initial_sp” 符号引用了同文件“STACK”节区。


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

可以了解到,这些跨文件引用的符号其实就是源文件中的函数名、变量名。

 


常见的调试错误:


比如,我们现在改一下函数名(改成LED_GPIO_Config0),如下:

直接编译文件,没有问题,结果如下:


而当点击build(编译链接)时,就会出现错误如下:


其实,我在写代码时,有时会经常遇到这个错误。它提示的是,在main.o中,没有找到引用的函数(符号)LED_GPIO_Config,实际上,main.o是main.c编译后生成的目标文件,这个目标文件引用的LED_GPIO_Config在所有的目标文件中都没有找到,因为我们把函数名修改成了LED_GPIO_Config0。找不到,那么自然就提示错误了。

删除无用节区


map 文件的第二部分是删除无用节区的说明(Removing Unused input sections from the image)

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

再看一下gpio,因为我们之前使用了gpio_init的初始化函数,进行对比一下:

对比左右两边可以发现,我们在程序中调用过的GPIO_Init函数,没有出现在删除无用节区的列表中。而没有调用到的函数,被直接被删除掉以节省存储空间。


符号映像表


map 文件的第三部分是符号映像表

 

这个表列出了被引用的各个符号在存储器中的具体地址、占据的空间大小等信息。如我们可以查到 LED_GPIO_Config 符号存储在 0x08000251 地址,它属于 Thumb Code 类型,大小为 92 字节,它所在的节区为 bsp_led.o 文件的 i.LED_GPIO_Config 节区。


存储器映像索引

 

本工程的存储器映像索引分为 ER_IROM1 及 RW_IRAM1 部分,它们分别对应 STM32内部 FLASH 及 SRAM 的空间。相对于符号映像表,这个索引表描述的单位是节区,而且它描述的主要信息中包含了节区的类型及属性,由此可以区分 Code、 RO-data、 RW-data及 ZI-data。


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

 

映像组件大小

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


首先是前面的表格数据,可以明显的看到中断向量表和启动文件栈空间:

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

数据分析:

关键字:stm32  MDK  编译过程  文件类型 引用地址:stm32专题三十六:MDK编译过程和文件类型(三)

上一篇:stm32专题三十六:MDK编译过程和文件类型(二)
下一篇:stm32专题三十六:MDK编译过程和文件类型(四)

推荐阅读

        三星全新一代翻盖安卓机皇W2019已经于10月10日获得入网许可,这款手机依然保持了上一代的翻盖造型,当然,这已经成为了W系列的最明显的一个设计语言。          三星W2019的外观设计和该系列已经发布的上代机型并没有很大的区别,包括翻盖、双屏、实体键盘等。该机的机身旁除了电源键、音量键之外,还有另外的一枚按键,有可能...
在2019年中国国际信息通信展暨5G商用启动仪式上,工信部联合三大运营商正式宣布5G商用,5G套餐资费也终于出炉。 中国联通董事长王晓初在演讲中表示,中国联通已从打造精品网络、培育应用生态、推动终端发展等各方面,为5G商用做好了充分的准备。 网络能力方面,中国联通坚定不移推进共建共享,与中国电信共同打造全球首张5G共建共享网,通过共建共享,使用...
摩托罗拉在 7 月份发布了名为 Moto G 5G Plus 的新机,显然这意味着还会有标准版的 Moto G 5G。现在代号为 “Kiev”的 Moto 设备已经现身,据称该机就是 Moto G 5G。据悉,Moto G 5G 将搭载新的骁龙 750G 芯片组,能够以比较低的价格提供 5G 支持,包括 mmWave 和 AI 噪点抑制,该处理器首发于小米 10T Lite。其他据称 Moto...
DAC简介:stm32只有2个DAC,每个DAC有1个独立的通道,这和ADC有区别(有3个ADC,每个ADC有16个通道),特征如下:DAC 功能框图功能说明:1 参考电压:2 数模转换 输出通道:注意,在使用DAC时,GPIO引脚一定要配置成模拟输入,不然没有输出,中文参考手册的描述:3 触发源及DHRx寄存器:双DAC 模式:DAC 的寄存器描述:1 控制寄存器DAC_CR2 DAC ...

史海拾趣

问答坊 | AI 解惑

用水果供电的AVR单片机——挑战MSP430的低功耗

引自:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=1333173&bbs_page_no=1&bbs_id=9999 我本来觉得水果电池驱动LCD只是展示会上的噱头,三片柠檬的电力,应该足够带动LCD的。不过最初当我用 Mega8L做了一个电路却不能用水果电池驱动时, ...…

查看全部问答∨

12864 带字库 图片显示

今天弄了一个12864显示图片的程序,网上有不少例程,我找的不够详细,比如取模时的设置那些,我就是在取模的设置费了不少时间,很是郁闷,还以为程序有问题呢。应该说是战略问题,一开始用的图片很复杂,后来才用简单的直线来揣摩出取模的正确设置 ...…

查看全部问答∨

wince下用I/O口作为输入,驱动程序要自己写吗?

wince下用I/O口作为输入,外接一个按键,我只接收按键的命令。我用的EVC写的应用程序,请问要自己写驱动吗?怎么写?…

查看全部问答∨

wince怎么入门啊?

想学学wince 怎么入门呢? (1)入门要看什么书啊?推荐些经典的! (2)wince是不是就是嵌入式的意思? ARM是和wince什么关系啊? 问题很菜吧,呵!…

查看全部问答∨

急切请高手指点PCMCIA总线驱动的一个问题

小弟目前在做一款PCMCIA无线网卡在wince下的驱动程序,但一开始就遇到麻烦,我用下面的代码查找总线上的无线网卡的VenderID,但返回值一直是0x8000FF00,请各位指点一下. for (bus = 0; bus < PCI_MAX_BUS; bus++) {   for (device = 0; ...…

查看全部问答∨

请问:platform manager 与platform builder有什么区别呀,是不是一个意思呀?

platform manager 与platform builder有什么区别呀,是不是一个意思呀…

查看全部问答∨

USB充电器套件制作原理解说

本帖最后由 jameswangsynnex 于 2015-3-3 19:59 编辑 USB充电器套件,又名MP3MP4充电器,输入AC160-240V,50/60Hz,额定输出:DC 5V 250mA(标签贴纸为500mA,如果要长期输出更大电流,请更换Q1为13003)。MP3和MP4在全国范围大量流行,不过作为 ...…

查看全部问答∨

我准备开个上位机VC或C#教程,大家觉得从什么方面开始

我准备开个VC和C#教程,大家觉得从什么方面开始,我觉得还是从做个实用的小程序开始,慢慢积累大家的兴趣,大家多提意见啊?我准备了几个方面:1、串口通信方面的,如串口调试助手2、通信控制显示方面的,用串口通信实现上位机显示单片机信息和下发 ...…

查看全部问答∨

【信号处理】:DSP+FPGA实时信号处理系统中FPGA设计的关键问题

简要分析了DSP+FPGA系统的特点和优越性,并且结合一个实时信号处理板的开发,提出在此类系统中,FPGA设计的几个关键问题,并且给出了详实的分析和解决方案。  …

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多每日新闻

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved