美文网首页程序员我爱编程
【嵌入式】基于makefile的STM32编译方法探索

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

作者: 追日填海 | 来源:发表于2017-05-18 22:29 被阅读1542次

    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

    相关文章

      网友评论

        本文标题:【嵌入式】基于makefile的STM32编译方法探索

        本文链接:https://www.haomeiwen.com/subject/juvftxtx.html