【嵌入式】基于makefile的STM32编译方法探索

0.前言

初学单片机的时候通常使用IDE(通常是keil),IDE的好处是上手快捷;但是IDE将很多东西屏蔽了,例如什么是编译、链接、加载文件等。编译、链接功能均是由一个个命令实现的,如果把这些命令比作工地上干活的工人,那么makefile就是指导工人干活的图纸,make命令这是负责解读makefile这张图纸的工程师。出于好奇心驱使决定尝试使用makefile方式编译stm32的程序。

先介绍总体思路,makefile只是一个工具,makefile也需要调用IDE背后的命令工具,所以要想实现用makefile编译STM32 程序需要分两步走:

  • 搞懂keil怎么将一个个源码程序转换为可以下载到芯片中的文件。
  • 用makefile的方式将IDE做的工作实现。

1.解密keil

1.1 IDE的bat文件

在keil下新建一个工程,


图1 设置工程属性
图2 选择生成batch file

如图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命令,设置了一些变量;第二段是ArmCC,ArmAsm,ArmLink,fromelf.exe命令构成,但是 --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

现在清楚了,编译一个文件需要指定各种编译选项,这些选项可以直接写在命令行中,同时可以将这些命令选项写在一个文件中,然后使用“--via”指明该文件。
打开生成的main.__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"

这些都是执行armcc命令带的参数,-c,-I -g是比较通用,--cpu显然是指明CPU的类型,编写makefile的时候可以直接借用。

1.3 链接

执行ArmLink命令时候的使用的命令参数在文件led.lnp中,其中内容如下:

--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",表示链接生成的目标文件。
知识点:hex,axf,bin,elf格式文件文件

  • bin文件:最纯粹的二进制文件,就是汇编程序直接汇编成为二进制代码,在裸机
    条件下运行的是bin文件。可以说bin文件是没有其他几种格式文件复杂的格式。
    文件本身不包含任何地址信息,在将bin文件烧写到flash中必须要指定地址。
  • hex文件:intel格式文件,它里面除包含精华的bin部分还有其他的一些信息,
    hex文件常常被用做很多ISP工具的文件格式。
  • axf文件:arm调试文件格式,同样这个文件格式的文件除包含bin文件部分,还包含
    了一些调试相关的信息。
  • elf文件:是一种目标文件格式,在有操作系统条件下例如linux中的目标文件就是
    采用elf文件格式,这种文件需要在有OS的支持下才可以运行。如果将elf文件放到
    裸机中运行,肯定会出错。
  • 联系 这几种文件格式中bin文件是最为基本的,bin文件是没有任何的
    “杂质”的机器码文件,其他的几种格式的文件都是在这种文件的基础上加入其他相关的信息形成的。

1.4 生成hex文件

fromelf.exe "led.axf" --i32combined --output "led.hex" 命令是讲生成的axf文件转换为hex文件,isp下载的使用的就是hex文件。

2.编写makefile

由之前的分析,知道了,怎么用命令将源文件转换为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的内容如下

%.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内容如下

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内容如下

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

命令行中执行make命令,成功编译输出bin,hex文件。

Paste_Image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容