0.前言
初學(xué)單片機的時候通常使用IDE(通常是keil),IDE的好處是上手快捷谴麦;但是IDE將很多東西屏蔽了蠢沿,例如什么是編譯、鏈接匾效、加載文件等舷蟀。編譯、鏈接功能均是由一個個命令實現(xiàn)的面哼,如果把這些命令比作工地上干活的工人野宜,那么makefile就是指導(dǎo)工人干活的圖紙,make命令這是負(fù)責(zé)解讀makefile這張圖紙的工程師精绎。出于好奇心驅(qū)使決定嘗試使用makefile方式編譯stm32的程序速缨。
先介紹總體思路,makefile只是一個工具代乃,makefile也需要調(diào)用IDE背后的命令工具旬牲,所以要想實現(xiàn)用makefile編譯STM32 程序需要分兩步走:
- 搞懂keil怎么將一個個源碼程序轉(zhuǎn)換為可以下載到芯片中的文件仿粹。
- 用makefile的方式將IDE做的工作實現(xiàn)。
1.解密keil
1.1 IDE的bat文件
在keil下新建一個工程原茅,
如圖2 所示吭历,在output->Create Batch File,編譯后在工程目錄下找到了led.BAT文件,
SETPATH=F:\keil\ARM\BIN40\;C:\Python27\Lib\sitepackages\PyQt4;C:\PROGRAMDATA\ORACLE\JAVA\JAVAPATH;C:\Windows\SYSTEM32;C:\Windows;C:\Windows\SYSTEM32\WBEM;C:\Windows\SYSTEM32\WINDOWSPOWERSHELL\V1.0\;D:\FLASH MAGIC;D:\PROGRAM FILES (X86)\MATLAB\RUNTIME\WIN64;D:\PROGRAM FILES (X86)\MATLAB\BIN;D:\PROGRAM FILES (X86)\MATLAB\POLYSPACE\BIN;D:\PROGRAM FILES (X86)\FLASH MAGIC;D:\software\Bluetooth Software\;D:\software\Bluetooth Software\syswow64;D:\Program Files\common;C:\Program Files (x86)\Microsoft SQL Server\90\Tools\binn\;C:\Program Files\CMake\bin;C:\Python27;F:\Program Files (x86);F:\keil\ARM\BIN40
SET ARMCC41INC=F:\keil\ARM\RV31\INC
SET ARMCC41LIB=F:\keil\ARM\RV31\LIB
SET CPU_TYPE=STM32F103C8
SET CPU_VENDOR=STMicroelectronics
SET UV2_TARGET=led
SET CPU_CLOCK=0x00000000
"F:\keil\ARM\BIN40\ArmCC" --Via "main.__i"
"F:\keil\ARM\BIN40\ArmCC" --Via "stm32f10x_it.__i"
"F:\keil\ARM\BIN40\ArmAsm" --Via ".\startup_stm32f10x_md._ia"
"F:\keil\ARM\BIN40\ArmCC" --Via "stm32f10x_gpio.__i"
"F:\keil\ARM\BIN40\ArmCC" --Via "stm32f10x_rcc.__i"
"F:\keil\ARM\BIN40\ArmCC" --Via "core_cm3.__i"
"F:\keil\ARM\BIN40\ArmCC" --Via "system_stm32f10x.__i"
"F:\keil\ARM\BIN40\ArmLink" --Via "led.lnp"
F:\keil\ARM\BIN40\fromelf.exe "led.axf" --i32combined --output "led.hex"
神奇的是擂橘,運行該bat文件(PS:bat是windows下的一種批處理文件晌区,類似于linux下的shell腳本),竟然就可以生成想要的hex文件通贞±嗜簦看來keil的奧秘就藏在這個bat文件中了。bat文件分為兩段昌罩,第一段是 幾個SET命令哭懈,設(shè)置了一些變量;第二段是ArmCC茎用,ArmAsm遣总,ArmLink,fromelf.exe命令構(gòu)成轨功,但是 --Via “main.__i” 這種是什么鬼就不得而知旭斥。
1.2 編譯
查看keil的幫助文檔:
--via=filename*
This option instructs the compiler to read additional command-line options
from a specified file. The options read from the file are added to the current
command line. Via commands can be nested within via files.
Syntax
--via=*filename
Where:
*filename
is the name of a via file containing options to be included on the command line.
Example
Given a source file main.c, a via file apcs.txt containing the line:
--apcs=/rwpi --no_lower_rwpi --via=L_apcs.txt
and a second via file L_apcs.txt containing the line:
-L--rwpi -L--callgraph
compiling main.c with the command line:
armcc main.c -L-o”main.axf" --via=apcs.txt
compiles main.c using the command line:
armcc --no_lower_rwpi --apcs=/rwpi -L--rwpi -L--callgraph -L-o"main.axf" main.c
現(xiàn)在清楚了,編譯一個文件需要指定各種編譯選項古涧,這些選項可以直接寫在命令行中垂券,同時可以將這些命令選項寫在一個文件中,然后使用“--via”指明該文件蒿褂。
打開生成的main.__i文件圆米,內(nèi)容如下:
-c
--cpu Cortex-M3
-g
-O0
--apcs=interwork
-IE:\src\stm32\CMSIS -IE:\src\stm32\StartUp -IE:\src\stm32\StdPeriph_Lib\inc -IE:\src\stm32\led -I "F:\keil\ARM\INC" -I "F:\keil\ARM\INC\ST\STM32F10x"
-DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER
-o "main.o"
--omf_browse "main.crf" --depend "main.d" "E:\src\stm32\led\main.c"
這些都是執(zhí)行armcc命令帶的參數(shù),-c啄栓,-I -g是比較通用娄帖,--cpu顯然是指明CPU的類型,編寫makefile的時候可以直接借用昙楚。
1.3 鏈接
執(zhí)行ArmLink命令時候的使用的命令參數(shù)在文件led.lnp中近速,其中內(nèi)容如下:
--cpu Cortex-M3 "main.o" "stm32f10x_it.o" ".\startup_stm32f10x_md.o" "stm32f10x_gpio.o" "stm32f10x_rcc.o" "core_cm3.o" "system_stm32f10x.o" --strict --scatter "led.sct"
--autoat --summary_stderr --info summarysizes --map --xref --callgraph --symbols
--info sizes --info totals --info unused --info veneers
--list ".\led.map" -o "led.axf"
注意其中的--scatter "led.sct",該選項表示鏈接器ArmLink使用的鏈接文件led.sct; -o "led.axf",表示鏈接生成的目標(biāo)文件堪旧。
知識點:hex削葱,axf,bin淳梦,elf格式文件文件
- bin文件:最純粹的二進(jìn)制文件析砸,就是匯編程序直接匯編成為二進(jìn)制代碼,在裸機
條件下運行的是bin文件爆袍∈追保可以說bin文件是沒有其他幾種格式文件復(fù)雜的格式作郭。
文件本身不包含任何地址信息,在將bin文件燒寫到flash中必須要指定地址弦疮。 - hex文件:intel格式文件夹攒,它里面除包含精華的bin部分還有其他的一些信息,
hex文件常常被用做很多ISP工具的文件格式胁塞。 - axf文件:arm調(diào)試文件格式咏尝,同樣這個文件格式的文件除包含bin文件部分,還包含
了一些調(diào)試相關(guān)的信息啸罢。 - elf文件:是一種目標(biāo)文件格式编检,在有操作系統(tǒng)條件下例如linux中的目標(biāo)文件就是
采用elf文件格式,這種文件需要在有OS的支持下才可以運行伺糠。如果將elf文件放到
裸機中運行蒙谓,肯定會出錯。 - 聯(lián)系 這幾種文件格式中bin文件是最為基本的训桶,bin文件是沒有任何的
“雜質(zhì)”的機器碼文件,其他的幾種格式的文件都是在這種文件的基礎(chǔ)上加入其他相關(guān)的信息形成的酣倾。
1.4 生成hex文件
fromelf.exe "led.axf" --i32combined --output "led.hex" 命令是講生成的axf文件轉(zhuǎn)換為hex文件舵揭,isp下載的使用的就是hex文件。
2.編寫makefile
由之前的分析躁锡,知道了午绳,怎么用命令將源文件轉(zhuǎn)換為hex文件,下面就用makefile將這些命令組合起來映之。
2.1 安裝windows版make工具
下載一個windows版的GNU make工具 拦焚,安裝到本地。http://www.gnu.org/software/make/manual/make.html
2.2 編寫makefile
編寫一個點亮LED的程序杠输,程序本身由startup_stm32f10x_md.s和main.c兩個文件組成赎败。整個編譯makefile由三個文件組成,分別是common_compile.mk,common_config.mk,Makefile
common_compile.mk的內(nèi)容如下
%.o:%.c
$(ARMCC) $(CFLAGS) $(INC) $(CMACRO) $< -o $@
%.o:%.s
$(ARMASM) $(ASMFLAGS) $(INC) $(CMACRO) $< -o $@
all:$(OBJS)
$(ARMLINK) --libpath "$(KEIL_PATH)\RV31\LIB" $(LINKFLAGS) $(MAP) $(INFO) $^ -o $(TARGET).axf
$(FROMELF) --bin -o $(TARGET).bin $(TARGET).axf
$(FROMELF) --i32 -o $(TARGET).hex $(TARGET).axf
del $(OBJHTM) $(OBJAXF) $(OBJS)
# 若只是生成LIB庫蠢甲,只需要以下一條命令就可以了
# $(ARMAR) $(APPNAME).lib -r $(OBJS)
.PHONY : clean
clean:
-del $(OBJS) *.map *.htm
common_config.mk內(nèi)容如下
SHELL=cmd.exe
KEIL_PATH = F:\Keil\ARM
ARMCC = $(KEIL_PATH)\BIN40\armcc
ARMASM =$(KEIL_PATH)\BIN40\armasm
ARMAR = $(KEIL_PATH)\BIN40\armar
ARMLINK =$(KEIL_PATH)\BIN40\armlink
FROMELF = $(KEIL_PATH)\BIN40\fromelf
TARGET =.\output\stm32
OBJMAP := .\stm32.map
OBJHTM := .\output\*.htm
OBJAXF := .\output\*.axf
CFLAGS := -c --cpu Cortex-M3 -D__MICROLIB -g -O0 --apcs=interwork
CMACRO :=
ASMFLAGS := --cpu Cortex-M3 -g --apcs=interwork --pd "__MICROLIB SETA 1"
LINKFLAGS := --cpu Cortex-M3 --library_type=microlib --scatter=led.sct --strict
MAP := --autoat --summary_stderr --info summarysizes --map --xref --callgraph --symbols
INFO := --info sizes --info totals --info unused --info veneers
Makefile內(nèi)容如下
include ./common_config.mk
OBJS = .\main.o .\startup_stm32f10x_md.o
INC += -I$(KEIL_PATH)\INC\St\STM32F10x
INC += -I$(KEIL_PATH)\RV31\INC
include ./common_compile.mk
命令行中執(zhí)行make命令僵刮,成功編譯輸出bin,hex文件鹦牛。