MDK是一款IDE软件,具有,编辑,编译,链接,下载,调试等等的功能。
1.编译器介绍: MDK可以编译C/C++文件和汇编文件,MDK只是一款IDE软件,那他内部使用的是什么编译器呢?我们打开MDK安装目录,在\ARM\ARMCC\bin文件夹下包含armasm.exe和armcc.exe两个文件,前者用来编译汇编代码,后者用来编译C代码。他们的主要作用是编译源代码得到机器码,生成以.o为后缀的对象文件。.o文件包含代码,数据,和调试信息。注意:工程中的每个源文件(.c文件或.s文件)经过编译后生成一个对应的.o文件。
2.链接器介绍:MDK使用的链接器是armlink,armlink和编译器在同一级目录下,链接器armlink把各个.o文件以及库文件链接最终生成一个映像文件(.axf文件或.elf文件)。注意:是把工程中各个.o文件最终链接成一个.axf文件或.elf文件。
3.格式转换器介绍:链接以后得到了.axf文件或.elf文件。使用转换工具fromelf将.axf文件或.elf文件转换为hex文件或bin。转换器fromelf和编译器连接器在同一级目录下。
我们随便找一个MDK工程编译一下,整个编译过程如下图。
我们最最最关心的就是 链接以后Programma Size:这一行的输出了。
下面分别介绍Code,RO-data,RW-data,ZI-data。
Code:编译器编译以后生产的机器指令。这些指令占用ROM空间,存储在ROM区。
RO-data: read only data的简写,是只读数据,程序运行的时候只能读取,不能修改。就是平时说的常量了。因为不需要修改,所以编译器干脆就把他们分配到ROM空间,所以说 RO-data占用ROM空间,存储在ROM区。
RW-data:read write data的简写,是可读可写数据,程序运行的时候可以读取也可以修改,就是平时说的变量了,变量占用RAM空间,这里特别注意,只有初始值不为0的变量才分配到RW-data。为什么呢?变量占用RAM空间这一点毫无疑问。大家都知道RAM是随机存储器,RAM的特点是随时可读可写,掉电数据丢失,上电以后初始值是随机数,而我们的需求却是上电以后是一个指定的非0值,怎么办,这不是为难我胖虎吗?办法总比困难多,我们把这些变量保存到ROM区,程序运行的时候再从ROM区复制到RAM区。这样就达到我们的目的了。
ZI-data: zero init data的简写,初始化为0的变量,这就简单了,不像RW-data那么腻歪人,程序运行的时候直接在RAM中分配空间就行。
了解了以上我们貌似就知道我们代码占用多少ROM空间和多少RAM空间了。
占用ROM空间是 Code + RO data + RW data
占用RAM空间是 RW data + ZI data
RW之所以占用两份空间是因为他是初始值为非0的变量,程序运行后需要从ROM空间复制到RAM空间。
可能有的大兄弟写了一个很简单的测试代码,比如LED闪烁灯的代码,明明没有定义那么多变量,编译以后ZI data 却是 1K多或2K的样子,这是为什么呢?
ZI data 包含3部分 ,栈空间 + 堆空间 + 程序员定义的一些初始值为0的全局变量,所以那1K多2K多基本上都是栈空间和堆空间吃掉的。这里注意,如果程序中没有使用malloc动态申请内存,编译器会把堆空间优化掉。比如我刚才打开一个测试例程代码,栈空间分配1K ,堆空间分配512字节,程序中定义了一些全局变量,没有使用malloc动态申请内存,编译以后ZI data是1136字节。如果大兄弟们发现 ZI data小于堆空间+栈空间的时候不要大惊小怪,可能是你没有使用malloc,编译器帮你优化掉了堆空间。
MDK工程编译以后会产生大量的中间文件,这些文件在调试程序阶段是非常重要的甚至是必不可少的,当我们调试完毕以后,把工程保存到电脑硬盘或网盘上,此时我们希望整个工程占用较小的存储空间。整个工程包含源文件,工程文件,中间文件,目标文件等等。源文件,工程文件肯定不能删除,我们只能删除掉中间文件或目标文件,怎么删除呢?手动删除?辣么多文件,手动删除不仅慢而且容易出错。我们编写一个脚本来删除。
因为这个脚本只是来删除一些文件,我们只用到一个del命令。
del jack.txt 删除jack.txt 文件
del *.txt /s删除所有子目录下所有的**.txt**文件,也就是递归删除。我们用到的就是这个这行命令。
在windows命令行中输入 **del /?**可以查看del的用法。
接下来我们动手写一个删除中间文件的脚本
新建一个后缀为.bat的文件,编辑内容如下
del *.bak /s
del *.ddk /s
del *.edk /s
del *.lst /s
exit
删除所有子目录后缀为.bak的文件。
删除所有子目录后缀为.ddk的文件。
删除所有子目录后缀为.edk的文件。
删除所有子目录后缀为.lst的文件。
最后执行exit命令退出命令行。
如果需要删除其他文件可以仿照着写。
编写指令生成bin文件。
生成bin文件要依靠fromelf工具。
MDK生成bin文件不能像生成hex文件那么简单了,需要在options选项卡下user选项中输入命令。
fromelf需要根据工程的.axf文件转换得到bin文件,工程构建完成以后生成了axf文件,所以命令要输入到 After Build/Rebuild一栏中。
例子指令:
fromelf --bin --output …\Output\jack.bin …\Output\application.axf
fromelf --bin --output 是固定的,前边的路径是输出路径,后边的路径是输入路径。
指令路径该如何写,这需要理解,因工程而异。
指令的路径是以.uvprojx工程文件为中心去找输入文件和输出文件。在Windows中…表示上一级目录。