历史上的今天

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

正在发生

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

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

MDK编译过程和文件类型

1 编译过程

(1)编译:MDK 软件使用的编译器是 armcc 和 armasm,它们根据每个 c / c++和汇编源文件编译成对应的以“.o”为后缀名的对


象文件(Object Code,也称目标文件),其内容主要是从源文件编译得到的机器码,包含了代码、数据以及调试使用的信息;


编译器:

.o文件(每个.c文件,编译完都会生成.o目标文件):


(2)链接:链接器 armlink 把各个.o 文件及库文件链接成一个映像文件 “.axf” (MDK)或 “.elf”(IAR) ;

(3)对链接器生成的 elf 映像文件利用格式转换器fromelf 转换成“.bin”或“.hex”文件,交给下载器下载到芯片的FLASH中;

MDK 软件的编译过程:

2 程序的组成、存储和运行


MDK的编译信息:

在工程的编译提示输出信息中有一个语句“ Program Size: Code=xx RO-data=xx RWdata=xx ZI-data=xx”,它说明了程序各个域的大小,编译后,应用程序中所有具有同一性质的数据(包括代码)被归到一个域,程序在存储或运行的时候,不同的域会呈现不同的状态,这些域的意义如下:

接下来,看一下const关键词和编译器优化,对代码大小的影响(均在优化等级 Level 0 下进行测试):

代码如下,很简单的电灯程序,编译完的大小为:

可以看到,RO_data只读数据域的大小为 320字节。接下来,进行测试,使用const关键词,定义一个大的全局数组,观察RO_data的大小变化:

可以看到,无论是代码域,还是只读数据域,所有的大小都没有发生改变。为什么?实际上是因为,我们虽然定义了这个数组,但并没有在程序中有效使用,所以这个数组会直接被编译器优化掉。再看一个例子:

我们虽然在程序中使用到了数组,但实际上,这个语句并没有起到任何作用,所以一样会被编译器优化。


如果我们真正的使用了这个数组,再看一下编译大小:

这次,编译的结果就明显不同。首先,代码域增大,这个很明显时因为我们增加了一些有效代码;比较重要的时,RO-data最开始为320字节,现在为1344字节,1344 - 320 = 1024,正好就是我们定义的const数组。


接下来,再看一下编译器优化等级对编译效果的影响(开到最高等级Level 3):

可以看到,代码域明显变小,其他的空间域无变化。

RW-data,正常时会存储到 Flash 空间,在程序运行时,会被加载到 RAM 区,此时这些数据就可以被修改,进行测试:


未定义前:

接下来,去掉前面定义的大数组的 const,看看编译结果:

可以看到,RW-data增加了1024字节。


ZI-data与RW-data不同,它不需要先存储在Flash中,而是在程序运行时,直接在RAM空间划分一个区域,把这些数据全部初始化为0,后续的运行就和RW-data一致。如果在定义变量时没有初始化,MDK 编译器会默认初始化为0。也就是说,ZI-data的数据不占用Flash空间,如果我们定义ZI-data,就可以节省空间。

后续的运行就和RW-data一致。如果在定义变量时没有初始化,MDK 编译器会默认初始化为0。也就是说,ZI-data的数据不占用Flash空间,如果我们定义ZI-data,就可以节省空间。

实际测试一下:


#define SOFT_DELAY Delay(0x0FFFFF);

uint8_t largeArray[1024] = {0, 1, 2};

编译结果如下,初始时ZI-data  = 1024字节

然后我们将变量的初始值设置为0,再编译:


#define SOFT_DELAY Delay(0x0FFFFF);

uint8_t largeArray[1024] = {0};

可以看到,ZI-data增加了1024字节。


总结一下,我们要存储到 Flash 中的数据大小总共为:Code + RO-data + RW-data(字节)


ZI-data 堆栈空间

stm32中,使用的堆栈空间,其实是输入ZI-data。为什么要使用栈和堆?首先是栈,在进行函数调用时,会使用到函数内部定义的局部变量,当然了,这些局部变量也需要临时存储,而且有一个特点,进入函数时申请,退出函数时释放,整一个的生命周期很短,使用栈可以自动申请和释放局部变量以节省内存空间。试想一下,我们定义的一个普通变量,如int a = 8; 它就会一直存在于内存中占用几个字节,没办法释放掉。而使用栈空间,就能够自动的存储和释放局部变量。堆空间的原理类似,主要用于动态内存分配。


注意,如果不使用malloc申请堆空间,则编译器会优化,不把堆空间计算到ZI-data中。我们来看一下,为什么ZI-data为1024?


这是启动文件中,默认定义的栈空间和堆空间的大小,可以看到,栈空间为1024字节,堆空间为512字节。而在我们的函数中,如果不使用malloc函数申请内存,堆空间会直接被编译器优化掉。

可以看到,ZI-data的大小就是分配的栈空间大小。我们尝试一下修改掉启动文件,增加栈的大小,看ZI-data会有什么变化?


如图所示,我们设置的栈大小为2048,将启动文件中的栈设置为0X800,再重新编译:

编译结果如下,与我们预期的结果相同。

接下来,我们在函数中添加动态内存相关的程序,看对编译结果的影响(栈设置为1024字节):


可以看到,当我们使用动态内存分配时,编译器的ZI-data就不再优化堆空间,此时ZI-data = 初始值为0的全局变量 + 栈空间 + 堆空间,如下所示:

编译结果如下所示,ZI-data = 1024(栈)+ 512(堆)+ 1000(0初始值全局变量)= 2536

程序的存储与运行:

stm32的程序运行描述:

总结一下:

在 MDK 编译器中,只要选择好了芯片型号,就会自动对应的给出Falsh起始地址+大小,内存起始地址+大小,下面以stm32vet6(64 + 512)为例说明:

首先是Flash,我们看一下中文参考手册中的描述:

类似的,关于SRAM

编译工具链


1 Windows cmd路径命令(与Linux系统不太一样)


通常情况下,我们要进入其他盘符下的任意目录,需要在CMD窗口运行两次命令:第一次,进入盘符,第二次进入指定目录


#进入D盘


d: 


#进入D盘下的Keil5文件夹


cd test


cls  清除命令行


如下所示:

2 之前有提高编译器的文件夹,里面包含了好几个编译和链接工具,现在使用Windows PowerShell来查看:

可以看到,该文件夹下有5个编译和链接工具,我们尝试来运行一下 fromelf.exe,直接在命令行输入 .fromelf.exe,然后会打印出许多提示信息(包括MDK版本,编译器版本、功能选项等):

3 配置环境变量:


为什么要配置环境变量?刚才,我们是进入到/ARM/ARMCC/bin/路径下,打开的fromelf工具。那么,我们能不能任意路径下都直接打开fromelf呢?可以尝试一下

结果显示,我们直接在c盘下输入fromelf,并不能运行,因为系统在该目录下没找到对应的文件,所以提示错误。当我们输入正确的路径后,fromelf可以运行。那么,每次都要输入这么长的路径吗?看一下windows系统对于环境变量的说明:

很明显,我们可以通过将/ARM/ARMCC/bin/这个路径添加到系统的环境变量,这样就更方便我们程序的执行:


环境变量添加完成后(win10需要重启),直接就能任意路径下运行:

4 工具链的作用(armcc  armasm  armlink):


4.1 armcc


 用于把 c/c++文件编译成 ARM 指令代码,编译后会输出 ELF 格式的 O 文件(对象、目标文件)。


首先来看armcc(MDK推荐使用Level 1 一级优化):

命令说明:


使用 armcc --cpu list,打印当前所有的cpu列表.可以看到,其中包含了Cortex-M0 M3 M4等内核的CPU。

接下来看MDK对armcc编译器的控制命令:

当我们在 MDK 中进行勾选时,实际上就是对armcc编译器进行对应的配置:

4.2 armasm 


armasm 是汇编器,它把汇编文件编译成 O 文件。


然后看一下 armasm,其实和 armcc 非常类似:

这里,我们也是通过 MDK 进行勾选来配置:

4.3 armlink


armlink 是链接器,它把各个 O 文件链接组合在一起生成 ELF 格式的 AXF 文件,AXF文件是可执行的,下载器把该文件中的指令代码下载到芯片后,该芯片就能运行程序了;利用 armlink 还可以控制程序存储到指定的 ROM 或 RAM 地址。


armlink 链接器:

同样的,在 MDK 软件中进行勾选配置(注意,这里可以用来配置ROM和RAM的基地址):

链接器默认是根据芯片类型的存储器分布来生成程序的,该存储器分布被记录在工程里的 sct 后缀的文件中,有特殊需要的话可自行编辑该文件,改变链接器的链接方式。


4.4 armar


armar 工具用于把工程打包成静态链接库 .lib文件,.lib文件可以提供给别人使用(别人能够使用,但不能查看源代码),从而保护源代码,勾选可以生成 .lib文件。


4.5 fromelf


 fromelf 可根据 axf 文件生成 hex、bin文件, hex 和 bin 文件是大多数下载器支持的下载文件格式。可以在下图加入一些指令:

关于User配置的描述:

接下来,我们尝试利用fromelf 手动生成 bin文件和hex文件:


1 我们复制生成的 .axf到文件夹,如图所示,并在此路径下打开windows powershell:


可以看到,在此路径下,此时只有一个 流水灯.axf 文件,接下来,查看一下 fromelf 的说明:


根据说明提示,来生成bin文件,使用的命令如下:


fromelf --bin --output 流水灯.bin 流水灯.axf 

结果如下,bin文件生成成功。

同理,再生成 Intel 格式的hex文件:


fromelf --i32 --output 流水灯.hex 流水灯.axf  


hex文件已经生成了,我们还需要看一下,利用fromelf和MDK生成的hex,是不是完全一致,结果如下:


这里还有一个地方值得注意,那就是 .axf 的路径一定要正确。实际上,MDK的相对路径,是从uvprojx工程开始的,如下所示:

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

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

推荐阅读

        中兴通讯公布,于2018年10月31日,公司与中兴新(控股股东)订立借款合同,据此,中兴新同意提供合共不超过人民币10亿元的借款。根据借款合同,公司同意质押公司持有于中兴微电子的16.17%股本权益予中兴新,以担保公司根据借款合同的偿还责任;及公司与中兴新应就中兴微电子质押签署一份质押合同。        借款将由公司用于产品研发...
11月1日,据外媒报道,韩国初创公司Bitsensing公司研发了一种雷达设备,采用物联网(IoT)技术嵌入传感器,用于智能监控、天气预报、自动驾驶和交通管理。该雷达设备的4D成像系统可以在所有天气条件下保持工作状态,甚至在火或高温等恶劣环境中也能正常工作。该雷达还支持GPS和Wi-Fi,随时随地可用。此外,该装置非常紧凑,易于组装,价格合理,易于使用...
苹果昨天发布了 2020 财年第四季度财报,其中 Mac 收入 90 亿美元,创下了新的季度记录。而苹果今年的 Mac 年度收入为 286 亿美元,也创历史新高。苹果今天在美国证券交易委员会提交的年度 10-K 报告中指出,与 2019 财年相比,2020 财年 Mac 销量增加了,这主要归功于 MacBook Pro 的销量增加。苹果在本财年第一季度推出了新的 16 ...
仿真报错 error30220在用STVD软件仿真程序的时候,有时候报错。弹出一个error30220的警告窗口。 引起这个问题原因有可能是烧写软件STVP软件刚烧写过程序,STLINK 被烧写软件占用了,这时可以把烧写软件STVP关掉,然后重新仿真,就能正常使用了。如果还不行就拔掉STLINK烧写器,关掉软件。重新打开软件,连接烧写器。烧写程序时报错有时候在烧写程序的...

史海拾趣

问答坊 | AI 解惑

丰田ES300轿车自动变速器打滑

车型:丰田ES300轿车,A540E型自动变速器。  故障症状:该车D档位前进时,车速不能随油门加大而随之增速,而且逐渐下降,有打滑现象。  诊断与排除:经拆检发现一组摩擦片烧坏,变速器有焦味,更换摩擦片后试车正常。但经高速行驶1500公里后又 ...…

查看全部问答∨

应用技巧/一种红外感应泵液器的单片机应用设计

摘要:红外微电脑自动泵液晶是21世纪一个实用的全新的小家电产品。它采用红外技术感应人手,由单片机控制出液量,具有抗干扰能力强、无误操作、省电节能等特点。       关键词:红外 泵液晶 单片机       随 ...…

查看全部问答∨

制版经验2

五、焊盘   焊盘的直径和内孔尺寸:焊盘的内孔尺寸必须从元件引线直径和公差尺寸以及搪锡层厚度、孔径公差、孔金属化电镀层厚度等方面考虑,焊盘的内孔一般不小于0.6mm,因为小于0.6mm的孔开模冲孔时不易加工,通常情况下以金属引脚直径值加上0 ...…

查看全部问答∨

3个教程教你学会看元器件的时序图

前一段时间在论坛看到有人问如何看元器件的时序图,我也曾经发了一个讨论帖 今天在网上看到这个帖子,不敢专享,共享出来,希望对大家有用 1、如何读单片机的时序图,国外的一个培训文档,讲解得很精细,有兴趣有朋友好好读读。 2、MCU ...…

查看全部问答∨

请问如果30层的PCB,共有多厚?

来自EEWORLD合作群:arm linux fpga 嵌入0(49900581)…

查看全部问答∨

谁知道,电子产品的检测方法是什么?

电子产品功能测试,怎么测试啊?如工作电压怎么测试?各个参数存储功能的测试?什么测试方法啊?多谢了?…

查看全部问答∨

谁能提供一个单片机的比较好的论坛?

谁能提供一个单片机的比较好的论坛? www.2@1ic.com   如何? …

查看全部问答∨

MouseMove消息异常,请大家帮忙分析原因

系统:CE5,开发工具:EVC4 用DirectShow开发MP3播放器,功能已经实现。但昨天测试发现一个问题,先描述一下: 播放MP3,触笔点击播放进度条调整播放进度,然后正常播放。此时一切正常! 但是当这首歌播放完毕,自动转到下一首时,出现异常:不是 ...…

查看全部问答∨

MAKEIMAGE时的错误,望指教

本人欲移植一个com的test程序(从ARM平台到x86平台),所用的编译平台是pb4.2和evc4.0,源代码(MFC程序)给编译完后可以在arm机器上正常运行,本人在evc中重选了wince x86编译器并且使用的是STANDARSDK_500(4.2有STANDSDK吗?网上没找到),用PB ...…

查看全部问答∨

tmega128单片机如何设置偶校验

CSR0B = 0x00; UCSR0A = 0x02 ; UCSR0C = 0x26 ;   //偶校验 请问是不是UCSR0C的bit5 bit4这两位 设置成  1 0 完成了偶校验的饿设置之后,UCSROC= 0x26  单片机的硬件部分就能自动把软件代码部分自动执行偶校验? ...…

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

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

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

更多每日新闻

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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