ARM Compiler 6.14 编译STM32过程(keil)
打开keil stm32工程,Options->Output, 勾选Create Batch File, 重新编译工程会在工程文件目录下生成一个.BAT文件,文件名应该是你的工程名, 研究此文件便可明白编译全过程
.BAT文件
SET PATH=C:\MDK5\ARM\AC6.14\Bin;C:\Java\bin;C:\Java\.....(此行较长省略)
SET CPU_TYPE=STM32F103ZE
SET CPU_VENDOR=STMicroelectronics
SET UV2_TARGET=Template
SET CPU_CLOCK=0x007A1200
"C:\MDK5\ARM\AC6.14\Bin\ArmAsm" --Via "..\obj\startup_stm32f10x_hd._ia"
"C:\MDK5\ARM\AC6.14\Bin\ArmClang.exe" @"..\obj\main.__i"
"C:\MDK5\ARM\AC6.14\Bin\ArmClang.exe" @"..\obj\delay.__i"
"C:\MDK5\ARM\AC6.14\Bin\ArmClang.exe" @"..\obj\sys.__i"
"C:\MDK5\ARM\AC6.14\Bin\ArmClang.exe" @"..\obj\adc.__i"
"C:\MDK5\ARM\AC6.14\Bin\ArmClang.exe" @"..\obj\gpio.__i"
...
..
.
...........(省略n多行)
"C:\MDK5\ARM\AC6.14\Bin\ArmLink" --Via "..\OBJ\Template.lnp"
"C:\MDK5\ARM\AC6.14\Bin\fromelf.exe" "..\OBJ\Template.axf" --i32combined --output "..\OBJ\Template.hex"
C:\MDK5\ARM\AC6.14\bin\fromelf.exe --bin -o ..\OBJ\out.bin ..\OBJ\Template.axf
解读:
第一行SET PATH=…设置一个临时的环境变量路径,并将编译器路径添加进去,路径很长是因为它先将系统环境变量全部读取了出来。注意第一条路径是编译器路径,如果你更换编译器编译的话,这条路径也会相应改变。
第二条开始往下几条SET,应该是定义了几条设备相关的控制符,暂时没有发现他们作用在哪儿。
继续往下会发现编译器开始正式调用编译了“C:\MDK5\ARM\AC6.14\Bin\ArmAsm” --Via “…\obj\startup_stm32f10x_hd._ia” 调用ArmAsm,ArmAsm用于编译汇编文件,输入文件obj\startup_stm32f10x_hd._ia ,对应的汇编文件是startup_stm32f10x_hd.s, 这个._ia文件的作用跟下面.__i的作用一样,后面会放到一起说明。
“C:\MDK5\ARM\AC6.14\Bin\ArmClang.exe” @"…\obj\xxx.__i" 使用ArmClang编译工程中的xxx.c文件,工程中有几个c文件,就会调用几次,因此会有非常多条这个指令。
ArmAsm以及ArmClang会将.c或.s文件编译生成目标文件: .o文件, 然后随便打开一个\obj\xxx._i(或者._ia):
-xc -std=c99 --target=arm-arm-none-eabi -mcpu=cortex-m3 -c
-mexecute-only -fno-rtti -flto -funsigned-char -fshort-enums -fshort-wchar
-D__MICROLIB -gdwarf-3 -Os -fno-function-sections -Wno-packed -Wno-missing-variable-declarations -Wno-missing-prototypes -Wno-missing-noreturn -Wno-sign-conversion -Wno-nonportable-include-path -Wno-reserved-id-macro -Wno-unused-macros -Wno-documentation-unknown-command -Wno-documentation -Wno-license-management -Wno-parentheses-equality -I ../USER -I ../SYSTEM/delay -I ../SYSTEM/sys -I xx/xx/... (省略一堆-I参数)
-IC:/MDK5/ARM/PACK/ARM/CMSIS/5.5.1/CMSIS/Core/Include
-IC:/MDK5/ARM/PACK/Keil/Jansson/1.0.0/src
-IC:/MDK5/ARM/PACK/Keil/STM32F1xx_DFP/1.0.5/Device/Include
-D__UVISION_VERSION="528" -D_RTE_ -DSTM32F10X_HD -DSTM32F10X_HD
-o ../obj/main.o -MD "main.c"
以-xxx 开头被称为编译控制字符串,用于告诉编译器使用的c语言标准、目标平台等信息,比如如果你要编译stm32f4, 那么 -mcpu应该=cortex-m4, -I, -IC 参数后面全是路径,看到这个,你应该能猜到这是啥了吧>_> -o …/obj/main.o 好了,我们已经告诉编译器我们要的目标文件了。
回到.BAT文件
“C:\MDK5\ARM\AC6.14\Bin\ArmLink” --Via “…\OBJ\Template.lnp” 调用链接器ArmLink开始链接,又用到了Template.lnp,打开这个文件吧:
--cpu Cortex-M3 --lto
"..\obj\startup_stm32f10x_hd.o"
"..\obj\main.o"
"..\obj\delay.o"
....(省略n多行)
"..\obj\gt9147.o"
"..\obj\sram.o"
"C:\MDK5\ARM\PACK\Keil\Jansson\1.0.0\lib\jansson_CM3LE.lib"
"..\obj\jansson_config.o"
--library_type=microlib --strict --scatter "..\OBJ\Template.sct"
--summary_stderr --info summarysizes --map --load_addr_map_info --xref --callgraph --symbols
--info sizes --info totals --info unused --info veneers
--list ".\Listings\Template.map" -o ..\OBJ\Template.axf
哦看到没,是不是跟前面的套路一样,把所有编译出来的.o文件输入给链接器。好像看到了一个新面孔jansson_CM3LE.lib,这是因为我在工程里用到了keil提供的json库(jansson),原来这种库是以lib文件的新式加入到链接环节里来的,最后我们看到-o输出了Template.axf文件,即可执行文件(ELF文件格式),该格式文件包含大量调试信息。
回到BAT文件,最后三行调用了格式转换工具生成了hex 和bin文件,然后就可以愉快的烧写代码了。
总结一下几个比较重要的文件
-
.__i ._ia 编译器调用文件。
-
.lnp 链接控制文件,由µVision生成的要传递到命令行,链接器(ArmLink)的输入文件。
-
.sct 分散加载文件(手动指定),这个文件非常有用,也非常值得研究研究。在.lnp文件中被引用。
-
.map 由链接器生成,里面包含着丰富的编译信息,这个文件还是非常有用的。
总结
ARMCC(即Arm Compiler)是ARM公司提供的编译工具链,你可以在ARM的官网上下载到它,目前最新的版本好像是6.14.1。
你可以独立使用,或者将其集成到keil mdk中(mdk手动添加ARMCC参考:http://www.keil.com/support/man/docs/uv4/uv4_armcompilers.htm)