摩登3新闻554258:_[STM32] 教你在vscode下用stm32+makefile+gcc实现编译仿真下载一条龙服务

出品 21ic论坛   791314247



生命在于运动,技术在于折腾,你是否厌倦了在keil、iar下孜孜不倦的写代码、debug,是否玩累了在外部编辑器下写代码,然后在转到ide下进行仿真、下载等操作呢?

这个教程将介绍下如何在vscode下实现这些操作,真正实现一个vscode可以吃天、实现编译仿真下载一条龙服务,而你只需要在vscode下的终端敲几个命令而已。。。

本教程以阿波罗开发板stm32f429igt6为例,先瞅瞅最终界面

最终可以用的功能如下:

1,vscode终端下执行make指令,即可在build文件下编译出.hex .bin .elf文件,中间文件放在build/Obj/文件夹下

2,执行make clean,可清除build文件夹

3,执行make download,可一键下载hex到目标板子并让板子复位运行,相当于keil的一键下载按钮

4,执行make reset,可以让板子复位运行一下

5,执行make commit,可一键推送到你的github或者giteee远程服务器上去,但前提是你自己创建了这个工程的git

教程如下:

环境:
1,下载vscode及必要插件,令需要一个插件Cortex_debug

2,Windows下安装arm-none-eabi-gcc工具链,推荐q4版本
下载及安装教程:https://blog.csdn.net/qq_35333978/article/details/110398968

3,Windows下安装Jlink最新版驱动(V6.88a)
附件上传不上去,故分享个网盘永久链接
链接:加HTTP加斜杠pan.baidu.com/s/11YnBjWtl9L9V7YCQABC60Q
提取码:ysgp安装、下载的教程也在上面的链接。


4,GNU make

百度网盘链接和安装教程、添加环境变量教程也在上边的链接。。。

5,git bash

这个不用说,大家都会有的吧,然后需要把vscode的终端换成git bash。百度一下,太容易了。

好了,环境就搭好了,不要嫌麻烦,现在越麻烦,你用起来越方便!

编译:编译只需在vscode终端中执行make指令就行,如下图:

仿真:仿真的话需要vscode下的插件cortex debug,这个教程我粘贴上我之前写的国产芯片fm33lc02x的教程,大家只要把芯片名字换成STM32F429就行


(1) vscode下载插件cortex debug插件



(2) 创建launch.json文件


如下图所示:



然后选择Cotrex Debug即可创建好launch.json文件





(3) 配置launch.json文件
稍微按照自己的芯片修改下就好,以FM33LC026为例:







然后将厂商提供的.svd文件放到你的工程根目录即可开始仿真,可以看变量、看外设寄存器、内核寄存器等等,还可以保存你的断点等。


然后实现这一切的核心就是makefile文件,不用管,我已经帮你写好了,而且全部中文注释,各种参数也是取自stm32cube的makefile参数,放心的用,放心的学!
然后我将在附件提供一个基于阿波罗开发板stm32f429igt6的点灯例程。如果的芯片不是stm32f429,但只要你的核是arm核,本例程本makefile,通通能用!
换芯片后你需要改以下内容:


1,找到你的芯片的基于gcc的启动文件和链接脚本,一般问厂商要肯定有的,不用自己写,然后替换到根目录下的2个对应文件



2,改以下内容,是不是看起来特简单。






然后,就搞定了,具体的参数可以去stm32cube上生成一个对应内核的makefile,然后参考下就行了,其实其他核是更简单的。教程可能有点乱,后期我会在整理下。

最后附上我的整个makefile



  1.    #*************************************************************************  

  2. #  **  

  3. #  ** File         : Makefile  

  4. #  ** Abstract     : This is the introduction to the document  

  5. #  ** Author       : wr  

  6. #  ** mail         : 791314247@q.com  

  7. #  ** Created Time : 20201122日 星期日 115806秒  

  8. #  ** copyright    : COPYRIGHT(c) 2020  

  9. #  **  

  10. #  ************************************************************************/  

  11.   

  12. ifneq ($(V),1)  

  13. Q := @  

  14. else  

  15. Q :=  

  16. endif  

  17.   

  18. ################################以下项目需用户根据需要更改##########################  

  19. # 输出文件的名称,默认为main(main.elf main.bin main.hex)  

  20. TARGET := main  

  21.   

  22. #链接文件名称和所在路径  

  23. LDSCRIPT := ./STM32F429IGTx_FLASH.ld  

  24.   

  25. #启动文件名称和所在路径  

  26. START_FILE_SOURCES := ./startup_stm32f429xx.s  

  27.   

  28. #内核选择,FPU, FLOAT-ABI可为空  

  29. CPU       := -mcpu=cortex-m4  

  30. FPU       := -mfpu=fpv4-sp-d16  

  31. FLOAT-ABI := -mfloat-abi=hard  

  32.   

  33. #系统宏定义  

  34. C_DEFS    := \  

  35. -DUSE_HAL_DRIVER \  

  36. -DSTM32F429xx  

  37.   

  38. # 芯片型号,用于Jlink仿真调试、下载  

  39. CHIP      := STM32F429IG  

  40.   

  41. # 选择优化等级:  

  42. 1. gcc中指定优化级别的参数有:-O0、-O1、-O2、-O3、-Og、-Os、-Ofast。  

  43. 2. 在编译时,如果没有指定上面的任何优化参数,则默认为 -O0,即没有优化。  

  44. 3. 参数 -O1、-O2、-O3 中,随着数字变大,代码的优化程度也越高,不过这在某种意义上来说,也是以牺牲程序的可调试性为代价的。  

  45. 4. 参数 -Og 是在 -O1 的基础上,去掉了那些影响调试的优化,所以如果最终是为了调试程序,可以使用这个参数。不过光有这个参数也是不行的,这个参数只是告诉编译器,编译后的代码不要影响调试,但调试信息的生成还是靠 -g 参数的。  

  46. 5. 参数 -Os 是在 -O2 的基础上,去掉了那些会导致最终可执行程序增大的优化,如果想要更小的可执行程序,可选择这个参数。  

  47. 6. 参数 -Ofast 是在 -O3 的基础上,添加了一些非常规优化,这些优化是通过打破一些国际标准(比如一些数学函数的实现标准)来实现的,所以一般不推荐使用该参数。  

  48. 7. 如果想知道上面的优化参数具体做了哪些优化,可以使用 gcc -Q –help=optimizers 命令来查询。  

  49. OPT       := -Og  

  50.   

  51. # 是否将debug信息编译进.elf文件,默认打开  

  52. DEBUG     := 1  

  53.   

  54. # 输出文件夹,.hex .bin .elf放在此文件夹下,.o .d文件放在此文件的子目录Obj下(自动创建)  

  55. BUILD     := ./build  

  56.   

  57. # 支持双系统编译,故需选当前系统,0为linux,1为windows  

  58. SYS    := 1  

  59. # 若指定了windows系统,则需确认编译器的路径,若安装时以默认路径安装,则正确  

  60. ifeq ($(SYS), 1)  

  61. GCC_PATH = “/c/Program Files (x86)/GNU Tools Arm Embedded/9 2019-q4-major/bin”  

  62. JLINK_PATH = “/c/Program Files (x86)/SEGGER/JLink”  

  63. endif  

  64. ###################################用户修改结束###################################  

  65.   

  66. # 编译器定义  

  67. PREFIX = arm-none-eabi-  

  68. ifdef GCC_PATH  

  69. SUFFIX = .exe  

  70. CC      := $(GCC_PATH)/$(PREFIX)gcc$(SUFFIX)  

  71. SZ      := $(GCC_PATH)/$(PREFIX)size$(SUFFIX)  

  72. OBJCOPY := $(GCC_PATH)/$(PREFIX)objcopy$(SUFFIX)  

  73. GDB     := $(GCC_PATH)/$(PREFIX)gdb$(SUFFIX)  

  74. BIN     := $(OBJCOPY) -O binary -S  

  75. HEX     := $(OBJCOPY) -O ihex  

  76. else  

  77. CC      := $(PREFIX)gcc  

  78. SZ      := $(PREFIX)size  

  79. OBJCOPY := $(PREFIX)objcopy  

  80. GDB     := $(PREFIX)gdb  

  81. BIN     := $(OBJCOPY) -O binary -S  

  82. HEX     := $(OBJCOPY) -O ihex  

  83. endif  

  84.   

  85. # Jlink定义,用于支持一键下载和gdb仿真  

  86. ifdef JLINK_PATH  

  87. SUFFIX = .exe  

  88. JLINKEXE       := $(JLINK_PATH)/JLink$(SUFFIX)  

  89. JLINKGDBSERVER := $(JLINK_PATH)/JLinkGDBServer$(SUFFIX)  

  90. else  

  91. JLINKEXE       := JLinkExe  

  92. JLINKGDBSERVER := JLinkGDBServer  

  93. endif  

  94.   

  95.   

  96. #################### CFLAGS Config Start ##########################  

  97. MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)  

  98.   

  99. #搜索所有的h文件,并输出携带-I的.h文件路径  

  100. C_INCLUDES := $(addprefix -I,$(subst ./,,$(sort $(dir $(shell find ./ –type f -iname “*.h”)))))  

  101.   

  102. #编译参数  

  103. CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -fdata-sections -ffunction-sections  

  104. #开关警告  

  105. CFLAGS += -Wall -W -Wno-unused-parameter  

  106. #标准  

  107. CFLAGS += -std=c99  

  108.   

  109. #当开启DEBUG功能时携带DEBUG参数  

  110. ifeq ($(DEBUG), 1)  

  111. CFLAGS += -g -gdwarf-2  

  112. endif  

  113.   

  114. #自动生成依赖文件  

  115. CFLAGS += -MMD -MP -MF”$(@:%.o=%.d)”  

  116. #################### CFLAGS Config End ##########################  

  117.   

  118. # libraries  

  119. LIBS = -lc -lm -lnosys  

  120. LIBDIR =  

  121. #链接指令集-specs=nosys.specs  

  122. LDFLAGS = $(MCU) -T$(LDSCRIPT) -specs=nano.specs $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD)/Obj/$(TARGET).map,–cref  

  123. #是否开启优化掉未使用的函数和符号  

  124. LDFLAGS += -Wl,–gc-sections  

  125.   

  126. #制作启动文件依赖Obj,输出去掉路径的.o文件,可兼容.s和.S  

  127. START_FILE_OBJ     = $(addsuffix .o, $(basename $(notdir $(START_FILE_SOURCES))))  

  128. OBJECTS            = $(addprefix $(BUILD)/Obj/, $(START_FILE_OBJ))  

  129.   

  130. #搜索所有的c文件,制作所有的.c文件依赖Obj  

  131. C_SOURCES          = $(subst ./,,$(shell find ./ –type f -iname “*.c”))  

  132. OBJECTS           += $(addprefix $(BUILD)/Obj/, $(notdir $(C_SOURCES:%.c=%.o)))  

  133. #PS:去掉终极目标的原始路径前缀并添加输出文件夹路径前缀(改变了依赖文件的路径前缀,需要重新指定搜索路径)  

  134.   

  135. #指定makefile搜索文件的路径(假如终极目标的依赖文件不携带.c文件所在的路径,  

  136. #且不指定搜索路径,makefile会报错没有规则制定目标)  

  137. vpath %.c $(sort $(dir $(C_SOURCES)))  #取出路径并去重和排序(以首字母为单位)  

  138. vpath %.s $(dir $(START_FILE_SOURCES))  

  139. vpath %.S $(dir $(START_FILE_SOURCES))  

  140.   

  141.   

  142. #指定为伪目标跳过隐含规则搜索,提升makefile的性能,并防止make时携带的参数与实际文件重名的问题  

  143. .PHONY:all clean printf JLinkGDBServer debug download reset commit  

  144.   

  145. all : $(BUILD)/$(TARGET).elf $(BUILD)/$(TARGET).bin $(BUILD)/$(TARGET).hex  

  146.   

  147.   

  148. #链接所有的.o生成.elf文件  

  149. $(BUILD)/$(TARGET).elf : $(OBJECTS) | $(LDSCRIPT)  

  150.         $(Q)$(CC) $(LDFLAGS) -o $[url=home.php?mod=space&uid=72445]@[/url] $(OBJECTS)  

  151.         $(Q)echo “make $@:”  

  152.         $(Q)$(SZ) $@  

  153.   

  154.   

  155. #编译启动文件  备用参数:#-x assembler-with-cpp  

  156. $(BUILD)/Obj/$(START_FILE_OBJ) : $(START_FILE_SOURCES) Makefile | $(BUILD)/Obj  

  157.         $(Q)echo “buid $(subst ./,,[        DISCUZ_CODE_34        ]lt;)”  

  158.         $(Q) $(CC) -c $(CFLAGS) -o $@ [        DISCUZ_CODE_34        ]lt;  

  159.   

  160. #编译工程  

  161. $(BUILD)/Obj/%.o : %.c Makefile | $(BUILD)/Obj  

  162.         $(Q)echo “buid $(subst ./,,[        DISCUZ_CODE_34        ]lt;)”  

  163.         $(Q) $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(@:%.o=%.lst) -o $@ [        DISCUZ_CODE_34        ]lt;  

  164.   

  165. $(BUILD)/Obj :  

  166.         $(Q)mkdir -p $@  

  167.         $(Q)echo “mkdir $@”  

  168.   

  169. %.bin : $(BUILD)/$(TARGET).elf  

  170.         $(Q) $(BIN) [        DISCUZ_CODE_34        ]lt; $@  

  171.         $(Q)du -h $(BUILD)/$(TARGET).bin  

  172.   

  173. %.hex : $(BUILD)/$(TARGET).elf  

  174.         $(Q) $(HEX) [        DISCUZ_CODE_34        ]lt; $@  

  175.   

  176. #用于检查链接脚本和启动文件是否存在,不存在则报错误  

  177. $(START_FILE_SOURCES):  

  178.         $(Q)echo ERROR: The startup file does not exist or has the wrong path !;\  

  179.         exit 1  

  180. $(LDSCRIPT):  

  181.         $(Q)echo ERROR: The link file does not exist or has the wrong path !;\  

  182.         exit 2  

  183.   

  184. clean:  

  185.         $(RM) -rf $(BUILD)  

  186.   

  187. printf:  

  188.         $(Q)echo $(info $(LDFLAGS))  

  189.   

  190.   

  191. JLinkGDBServer:  

  192.         $(Q)JLinkGDBServer -select USB -device $(CHIP) \  

  193.         -endian little –if SWD -speed 4000 -noir -LocalhostOnly  

  194.   

  195. debug:  

  196.         $(Q)make  

  197.         $(Q)echo target remote localhost\:2331 > gdb.gdb  

  198.         $(Q)echo monitor reset >> gdb.gdb  

  199.         $(Q)echo monitor halt >> gdb.gdb  

  200.         $(Q)echo load >> gdb.gdb  

  201.         $(Q)echo b main >> gdb.gdb  

  202.         $(Q)echo – >> gdb.gdb  

  203.         $(Q)echo c >> gdb.gdb  

  204.         $(Q)-$(GDB) $(BUILD)/$(TARGET).elf –command=gdb.gdb  

  205.         $(Q)$(RM) gdb.gdb  

  206.   

  207. download:  

  208.         $(Q)make  

  209.         $(Q)echo “h” > jlink.jlink  

  210.         $(Q)echo “loadfile” $(BUILD)/$(TARGET).hex >> jlink.jlink  

  211.         $(Q)echo “r” >> jlink.jlink  

  212.         $(Q)echo “qc” >> jlink.jlink  

  213.         $(Q)$(JLINKEXE) -device $(CHIP) -Speed 4000 -IF SWD -CommanderScript jlink.jlink  

  214.         $(Q)$(RM) jlink.jlink  

  215.   

  216. reset:  

  217.         $(Q)echo “r” >> jlink.jlink  

  218.         $(Q)echo “qc” >> jlink.jlink  

  219.         $(Q)$(JLINKEXE) -device $(CHIP) -Speed 4000 -IF SWD -CommanderScript jlink.jlink  

  220.         $(Q)$(RM) jlink.jlink  

  221.   

  222. commit:  

  223.         $(Q)git add .  

  224.         $(Q)status=‘$(shell git status | grep “git pull”)’;\  

  225.         if test -n “$status“;then echo “Need to do git pull !”;exit 10;fi  

  226.         $(Q)explain=‘$(shell read -p “Please input git commit explain:” explain;echo “$explain”)’;\  

  227.         if test -z “$explain“;then git commit -m “Daily development submission”; \  

  228.         else git commit -m “$explain“;fi  

  229.         $(Q)git push  



免责声明:本文内容由21ic获得授权后发布,版权归原作者所有,本平台仅提供信息存储服务。文章仅代表作者个人观点,不代表本平台立场,如有问题,请联系我们,谢谢!