STM32学习-keil的编译过程
首先我们简单了解下MDK的编译过程,它与其它编译器的工作过程是类似的 这是一个大致的流程 我们可以在工程中找到批处理文件看到更加详细的流程
批处理文件如下,前面几行是一些固定的信息,包括cpu类型,时钟,路径地址等信息。红色框中显示的是具体的编译信息,可以看到最前面的ARMCC\bin下就是keil使用的编译器了。我们跳转到该目录进行查看
ARM\bin下的各种编译器
-
使用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)数量。
我们以main.c为例子,依次查看编译的整个过程找到指令 可以看到,这个指令就是使用armcc来处理某个目录下的main.i文件。.i文件就是c文件经过预处理之后的文件 我们打开看一下这个main.i文件
main.i文件的内容
这些都是执行armcc命令带的参数,-c,-I -g是比较通用,--cpu显然是指明CPU的类型,编写makefile的时候可以直接借用。我们询问一下gpt
这条指令是一个编译命令,通常用于嵌入式系统开发中,特别是针对基于ARM Cortex-M3架构的微控制器(例如STM32F1系列)的项目。以下是对该指令各部分的解释:
-
--c99
:指定使用C99标准进行编译。 -
-c
:表示只进行编译,不链接。编译器将生成目标文件(.o 文件),而不是可执行文件。 -
--cpu Cortex-M3
:指定目标CPU架构为Cortex-M3。 -
-g
:生成调试信息,以便在调试器中使用。 -
-O0
:关闭优化,便于调试和查看生成的代码(优化级别为0)。 -
--apcs=interwork
:指定APCS(ARM Procedure Call Standard)为interwork模式,这通常用于支持ARM和Thumb代码之间的互操作。 -
--split_sections
:将生成的代码分成多个部分,以便更好地控制内存布局。 -
-I .\start -I .\User -I .\Library -I .\Systerm -I .\Hardware -I .\RTE\_Target_1
:这些是包含目录的路径,编译器在编译时会在这些目录中查找头文件。 -
-ID:\Keil_v5\ARM\PACK\Keil\STM32F1xx_DFP\2.3.0\Device\Include
和-ID:\Keil_v5\ARM\CMSIS\Include
:这些是额外的包含目录,通常包含特定于设备的头文件和CMSIS(Cortex Microcontroller Software Interface Standard)库的头文件。 -
-D__UVISION_VERSION="524"
:定义一个预处理宏__UVISION_VERSION
,其值为"524"。这个宏可能用于代码中以特定于uVision IDE的方式进行条件编译。 -
-DSTM32F10X_MD
和-DUSE_STDPERIPH_DRIVER
:定义预处理宏,以便在代码中可以根据这些宏进行条件编译,通常用于选择特定的功能或驱动。 -
-o .\objects\main.o
:指定输出目标文件的路径和名称,这里是将生成的目标文件命名为main.o
,并将其放在objects
目录中。 -
--omf_browse .\objects\main.crf
:生成OMF(Object Module Format)浏览文件,这个文件可以用于后续的调试或分析,文件名为main.crf
,位于objects
目录中。 -
--depend .\objects\main.d
:生成依赖文件,记录源文件与头文件之间的依赖关系,通常用于自动化构建系统。 -
"User\main.c"
:指定要编译的源文件,这里是User
目录中的main.c
。
总体来看,这条指令的目的是编译一个C语言源文件main.c
,生成未链接的目标文件main.o
,并包含调试信息和多个包含目录,以便后续的开发和调试。也就是使用ARMCC来编译main.c文件生成main.o的目标文件
那么我们再继续查看main.o文件,到这里就已经不知道是什么了,经过查询得知其内容主要是从源文件编译得到的机器码,包含了代码、数据以及调试使用的信息;
那么回到前面的框图中,我们可以看到很多文件都使用ARMCC进行编译,就是把我们编写的各种.c文件编译成.o目标文件 那么看最后,还会使用一个ARMLink,他是一个链接器,会把前面生成的各种.o目标文件链接起来
这条指令是一个命令行调用,用于在 Keil MDK (Microcontroller Development Kit) 开发环境中使用 ARMCC 工具链的链接器(ArmLink)来链接一个项目文件。我们可以逐部分解释这条指令:
-
D:\Keil_v5\ARM\ARMCC\Bin\ArmLink:这是链接器(ArmLink)的可执行文件的路径。该工具负责将编译后的目标文件和库文件链接成最终的可执行文件。
-
–Via:这是 ArmLink 命令行参数,表示后续将使用一个链接描述文件(linker description file)。该文件通常包含了链接过程中的各种设置和指令。
-
“.\Objects\project.lnp”:这是链接描述文件的路径,通常以
.lnp
为后缀。该文件包含了关于如何链接目标文件的信息,例如输入文件、输出文件的名称、内存布局等。
我们再看一下 project.lnp文件
前面的就是各种输入文件,最后的.axf文件就是输出的文件
-
–strict:启用严格模式,链接器将按照严格的标准进行链接,通常会更严格地检查输入文件和链接规则。
-
–scatter “.\Objects\project.sct”:指定一个散布文件(scatter file),用来定义程序在内存中的布局。该文件通常包含起始地址、结束地址以及各个段(如代码段、数据段等)的分配信息。
-
–summary_stderr:将链接过程的摘要信息输出到标准错误流(stderr),而不是标准输出流(stdout)。
-
–info summarysizes:请求链接器提供关于各个段大小的摘要信息,包括代码段、数据段等的大小。
-
–map:生成映射文件,它包含了程序中各个符号及其在内存中地址的详细信息。
-
–load_addr_map_info:生成加载地址的映射信息,这是链接器的一个选项,用于记录符号和它们在内存中的加载地址。
-
–xref:生成交叉引用(cross-reference)信息,帮助开发者分析各个符号之间的关系。
-
–callgraph:生成调用图,显示函数调用之间的关系,帮助开发者理解程序的结构。
-
–symbols:输出符号表信息,包含程序中定义的所有符号及其地址。
-
–info sizes:请求链接器输出各个段的详细大小信息。
-
–info totals:请求链接器输出总的程序大小信息,包括所有段的总大小。
-
–info unused:请求链接器输出未使用的符号和段的信息,有助于识别不必要的代码或数据。
-
–info veneers:请求链接器输出有关 “veneer” 的信息。Veneer 是一种在 ARM 架构中用于跨越大距离调用的技术,通常用于中断或异常处理。
-
–list “.\Listings\project.map”:指定生成一个列表文件(.map 文件),该文件通常包含链接的详细信息,如符号地址、段信息等,帮助调试和分析。
-
-o .\Objects\project.axf:指定输出文件的路径和名称。在这里,生成的可执行文件将被命名为
project.axf
,存放在.\Objects\
目录下。
这条指令指定了链接过程中的各种选项和输出,帮助开发者更好地理解和调试生成的程序。这些选项能够提供丰富的链接信息。
若编译过程无误,即可把工程生成前面对应的*.axf文件,而在MDK中使用下载器(DAP/JLINK/ULINK等)下载程序或仿真的时候,MDK调用的就是*.axf文件,它解释该文件,然后控制下载器把*.axf中的代码内容下载到STM32芯片对应的存储空间,然后复位后芯片就开始执行代码了。
然而,脱离了MDK或IAR等工具,下载器就无法直接使用*.axf文件下载代码了,它们一般仅支持hex和bin格式的代码数据文件。默认情况下MDK都不会生成hex及bin文件,需要配置工程选项或使用fromelf命令。
这是在选用生成hex文件之后的最后指令,使用fromelf命令把axf文件格式化成hex文件
hex文件内容 纯粹的机器码
最后给出一些文件类型
参考文章
基于makefile的STM32编译方法探索(armcc编译链)_stm32 make编译-CSDN博客
48. MDK的编译过程及文件类型全解 — [野火]STM32 HAL库开发实战指南——基于野火F7与H7系列开发板 文档