文章目录
- 39.1 编译过程
-
- 39.2 程序的组成、存储与运行
- 39.3 编译工具链
-
- 39.3.1 MDK编译文件
- 39.3.2 设置环境变量
- 39.3.3 运行
- 39.3.4 armcc、armasm 及 armlink
-
- 39.3.4.1 armcc
- 39.3.4.2 查询具体的MDK编译选项的具体信息
- 39.3.4.3 armasm
- 39.3.4.4 armlink
- 39.3.4.5 armar、fromelf 及用户指令
39.1 编译过程
39.1.1 编译过程简介
编译,MDK 软件使用的编译器是 armcc 和 armasm
- 它们根据每个 c/c++ 和汇编源文件编译成对应的以“.o”为后缀名的对象文件 (Object Code,也称目标文件)
- 其内容主要是从源文件编译得到的机器码,包含了代码、数据以及调试使用的信息;
链接,链接器 armlink 把各个.o 文件及库文件链接成一个映像文件“.axf”或“.elf”;
格式转换
- 一般来说 Windows 或 Linux 系统使用链接器直接生成可执行映像文件 elf 后,内核根据该文件的信息加载后,就可以运行程序了
- 在单片机平台上,需要把该文件的内容加载到芯片上,所以还需要对链接器生成的 elf 映像文件利用格式转换器 fromelf 转换成“.bin”或“.hex”文件,交给下载器下载到芯片的 FLASH 或 ROM 中
编译完成
- 提示信息的第一部分说明构建过程调用的编译器。
- 图中的编译器名字是“V5.06(build 20)”,后面附带了该编译器所在的文件夹。
- 在电脑上打开该路径,可看到该编译器包含图 39‑3 中的各个编译工具,如 armar、armasm、armcc、armlink 及 fromelf,后面四个工具已在图 39‑1中已讲解,而 armar 是用于把.o 文件打包成 lib 文件的。
- 使用 armasm 编译汇编文件。
- 图中列出了编译 startup 启动文件时的提示,编译后每个汇编源文件都对应有一个独立的.o 文件。
- 使用 armcc 编译 c/c++ 文件。
- 图中列出了工程中所有的 c/c++ 文件的提示,同样地,编译后每个 c/c++ 源文件都对应有一个独立的.o 文件。
-
使用 armlink 链接对象文件,根据程序的调用把各个.o 文件的内容链接起来,最后生成程序的 axf 映像文件,并附带程序各个域大小的说明,包括 Code、RO-data、RW-data 及 ZI-data的大小。
-
使用 fromelf 生成下载格式文件,它根据 axf 映像文件转化成 hex 文件,并列出编译过程出现的错误 (Error) 和警告 (Warning) 数量。
-
最后一段提示给出了整个构建过程消耗的时间。
在工程的“Output”及“Listing”目录下找到由以上过程生成的各种文件
每个 C 源文件都对应生成了.o、.d 及.crf 后缀的文件,还有一些额外的.dep、.hex、.axf、.htm、.lnp、.sct、.lst 及.map 文件。
39.2 程序的组成、存储与运行
CODE、RO、RW、ZI Data 域及堆栈空间参见STM32的内存管理
程序的加载与执行见SCF文件
39.3 编译工具链
39.3.1 MDK编译文件
MDK编译工程,会生成一些中间文件(.o .axf .map等),最终会生成HEX文件,以便下载到MCU上面执行,我们通常使用STM32工程中,output文件夹下面会生成十多种文件类型。
- .o文件:它是由编译器编译.c/.s文件时所产生的可重定向对象文件。
- 【注:①可重定向是指该文件包涵数据、代码,但是没有指定地址,他的地址可以由后续链接的时候进行指定,②不可重定向是指这种文件所包含的数据/代码都已经指定地址了,不能再改变】
- .axf文件:它是由armlink链接器,将整个工程参与编译的.o文件链接成一个可执行对象文件。它是不可重定向的。
- 【注】各类仿真器,在进行下载调试的时候都是用的,axf文件
- .hex文件:它是由.axf转换而来的一个可执行对象文件。
-
.hex文件和.bin文件的区别是:.bin文件不含地址信息,全部是可执行代码;而hex文件则是包含地址信息的可执行代码。同样的.bin文件也是由.axf文件转换而来的。可理解为带存储地址描述格式的 bin 文件。
-
在使用ISP软件进行程序下载的时候,一般使用的是.hex文件包含的地址信息来实现程序下载。 而我们在进行BootLoader升级的时候,一般使用的是.bin文件,地址有Bootloader程序指定。
- .htm文件:它是编译器在编译代码的时候生成的一个列表文件,包含了整个工程的静态调用图,最大用处就是可以查看栈深度(最小深度),方便设置栈的大小。.htm文件可以直接由浏览器打开。
- .map文件.map文件时编译器链接时生成的一个文件,它主要包含了交叉链接信息。通过.map文件,我们可以知道整个工程的函数调用关系、FLASH和RAM 占用情况及其详细的汇总信息。能具体到单个源文件(.c/.s)的占用情况,根据这些信息,我们可对代码进行优化。
若希望使用 MDK 编译生成 bin 文件的,需要在 MDK中输入指令控制 fromelf 工具;在本章后面讲解 AXF 及 O 文件的时候,需要利用 fromelf 工具查看其文件信息,这都是无法直接通过 MDK 做到的。
- 关于这些工具链的说明,在 MDK 的帮助手册《ARM Development Tools》都有详细讲解
- 点击 MDK 界面的“help->uVision Help”菜单可打开该文件。
39.3.2 设置环境变量
调用这些编译工具,需要用到 Windows 的“命令行提示符工具”,为了让命令行方便地找到这些工具,我们先把工具链的目录添加到系统的环境变量中。
- 查看本机工具链所在的具体目录可根据上一小节讲解的工程编译提输出信息中找到,如本机的路径为“D:workkeil5ARMARMCCbin”。
39.3.3 运行
打开 Windows 的命令行,点击系统的“开始菜单”,在搜索框输入“cmd”
- 在弹出的命令行窗口中输入“fromelf”回车,若窗口打印出 formelf 的帮助说明,那么路径正常
MDK 本质上也是如此调用工具链的,只是它集成为 GUI,相对于命令行对用户更友好
39.3.4 armcc、armasm 及 armlink
39.3.4.1 armcc
armcc 用于把 c/c++ 文件编译成 ARM 指令代码,编译后会输出 ELF 格式的 O 文件
第一部分是 armcc 版本信息,第二部分是命令的用法,第三部分是主要命令选项。
输入命令armcc [options] file1 file2 ⋯filen
- 在 [option] 位置可输入下面的“–arm”、“–cpu list”等选项
- 若选项带文件输入,则把文件名填充在 file1 file2⋯的位置,这些文件一般是 c/c++ 文件。
“–cpu list”可列出编译器支持的所有 cpu,我们在命令行中输入“armcc –cpu list”
打开 MDK 的 Options for Targe->c/c++ 菜单,可看到 MDK 对编译器的控制命令
它调用了-c、-cpu –D –g –O1 等编译选项
- 当我们修改 MDK 的编译配置时,可看到该控制命令也会有相应的变化。
- 然而我们无法在该编译选项框中输入命令,只能通过 MDK 提供的选项修改。
39.3.4.2 查询具体的MDK编译选项的具体信息
如c/c++选项中的“Optimization:Leve 1(-O1)”是什么功能呢?
查看 MDK 的帮助手册,在 armcc 编译器说明章节:
39.3.4.3 armasm
armasm 是汇编器,它把汇编文件编译成 O 文件。
- 与 armcc 类似,MDK 对 armasm 的调用选项可在“Option for Target->Asm”页面进行配置
39.3.4.4 armlink
armlink 是链接器,它把各个 O 文件链接组合在一起生成 ELF 格式的 AXF 文件
- AXF 文件是可执行的,下载器把该文件中的指令代码下载到芯片后,该芯片就能运行程序了;
- 利用 armlink 还可以控制程序存储到指定的 ROM 或 RAM 地址。
- 在 MDK 中可在“Option for Target->Linker”页面配置 armlink 选项
链接器默认是根据芯片类型的存储器分布来生成程序的,该存储器分布被记录在工程里的 sct 后缀的文件中,有特殊需要的话可自行编辑该文件,改变链接器的链接方式
39.3.4.5 armar、fromelf 及用户指令
armar 工具用于把工程打包成库文件,fromelf 可根据 axf 文件生成 hex、bin 文件,hex 和 bin 文件是大多数下载器支持的下载文件格式
在 MDK 中,针对 armar 和 fromelf 工具的选项几乎没有,仅集成了生成 HEX 或 Lib 的选项
例如如果我们想利用 fromelf 生成 bin 文件,可以在 MDK 的“Option for Target->User”页中添加调用 fromelf 的指令
在 User 配置页面中,提供了三种类型的用户指令输入框,在不同组的框输入指令,可控制指令的执行时间
- 分别是编译前 (Before Compile c/c++ file)、构建前 (Before Build/Rebuild) 及构建后(After Build/Rebuild) 执行。
- 这些指令并没有限制必须是 arm 的编译工具链,例如如果您自己编写了 python 脚本,也可以在这里输入用户指令执行该脚本。
图中的生成 bin 文件指令调用了 fromelf 工具
- 由于 fromelf 是根据 axf 文件生成 bin 的,而 axf 文件又是构建 (build) 工程后才生成,所以我们把该指令放到“After Build/Rebuild”一栏