如何在 VScode 创建 stm32 项目?

如何在 VScode 创建 stm32 项目?

一、参考来源

VSCode开发STM32快速搭建开发环境零基础教程!哔哩哔哩bilibili

上面的链接是主要参考的来源。

二、工具链

本次使用的工作有

  • arm-none-eabi-gcc 来作为编译器;

  • pyocd 作为烧写器;

  • vscode 作为编辑器;

  • vscode 的插件 cortex-debug 作为调试工具;

  • STM32cubeMX 作为模板的生成;

  • make 作为构建工具。

三、VScode 的相关插件

C\C++ 插件:作为 C 语言的主要插件。

360截图17700510535946.png

Cortex-debug 插件:作为调试的插件。

360截图177005105359406.png

四、配置过程

4.1 使用 stm32cubeMX 生成模板

使用 stm32cubeMX 的目的是使用其生成的 makefile 文件,嘻嘻。因为其他的不会用,现不深究。但有一点要注意, stm32cubeMX 使用的是 stm 公司新推出的 hal 库 ,而当前项目使用的却是其另一种推出的 stm32标准库。因此,在后面的演示,我会把除 makefile 外的文件均删除。。。

现演示的是怎生成模板:

打开 stm32cubeMX ,点击 ACCESS TO MCU SELECTOR

360截图17700510535946-1651573567296.png

使用英文输入法输入你想要的芯片型号。

360截图17700510535946-1651573695124.png

并在右侧的列表中选择芯片,注意其封装。

360截图177005105359406-1651573772126.png

其他配置不在当前演示的重点,日后学到,再作重视。

360截图17700510535946-1651573981925.png

这里的重点是 (4) 。我们选择 makefile 。而toolchain folder location的话,我未设置,好像也行,因为我把 arm-none-eabi-gcc 已经加载到环境变量了。

360截图17700510535946-1651574222999.png

上图,就是生成的目录。我把其他文件都删去,只保留 Makefile (好像有点傻傻的样子,哈哈,T^T)。

其中包括 .s 文件和 .ld 文件 ,因为我还未测试过,所以在演示中,我选择用回固件库里的。

4.2 搭建以固件库为基础的项目架构

项目的基本目录

360截图17700510535946-1651574884821.png

其中我定义了

  • Driver 放 stm32 标准库的内容

  • src 放自己写的业务代码

  • Makefile 构建工具

360截图17700510535946-1651574986088.png

上图为 Driver 目录下的结构,其中

  • CMSIS 放 core 代码,对应标准库里的
360截图17700510535946-1651575102566.png
360截图177005105359406-1651575116915.png

即,

360截图17700510535946-1651575151141.png
  • FWLB 放的是外设的文件,直接把标准库里的 inc 目录和 src 目录复制过来就行,标准库里的如下图,
360截图17700510535946-1651575261219.png
  • LINK_SCRIPTS 选择的是
360截图17700510535946-1651575382866.png

即,project -> template -> TrueSTUDIO -> STM3210E-EVAL -> stm32_flash.ld。此目录放的是链接脚本。STM公司已经帮我们为不同的编译工具和不同芯片类型写了一个模板。

其中 TrueSTUDIO 适用于 gcc 工具。 stm3210e 里放的是大容量的,而其他的区别,日后再作研究。

  • STARTUP 放的是启动文件。
360截图17700510535946-1651575633839.png

同样,我们选择 TrueSTUDIO 里提供的模板,好像 gcc-ride7 里的也行,未测试过。

最后,还要把一些中断之类的文件从模板中复制过来。

360截图17700510535946-1651575835854.png

请注意systme_stm32f10x.c 就不要复制了,因为在上面中已经有复制到其他地方了。不然在链接阶段会报 重复定义

这样,我们的基本项目架构就完成了。

4.3 在 vscode 里构建智能提示

vscode 使用快捷键 Ctrl+Shift+P 。键入 C/C++ ,选择 C/C++: Edit Configurations(UI)

360截图17700510535946-1651576148224.png
360截图177005105359406-1651576164217.png

把编译器改为 gcc, 而 IntelliSense 改为 windows-gcc-arm

这里的作用是为了在智能提示里的 uint32_t 不报错。

360截图17700510535946-1651576270291.png

当你有其他库的头文件不在当前项目里,请在这里增加路径。不过一般不用修改,但在插件 keil assistent 里就有这样的应用。

360截图17700510535946-1651576360898.png

添加相应的宏。这很重要,在 stm32cubeMX 里和 stm32 固件库 里的有不同,请注意。

在这里,我们会增加两个

  • USE_STDPERIPH_DRIVER 表明我们使用的是标准固件库

  • STM32F10X_HD 表明我们的芯片是 F1 系列的大容量产品

另外,加一些补充

  • __CC_ARM 若使用 keil assistent 插件导入 keil 项目时,就要加入这个才能使 uint32_t 不会报错

  • 同时,其头文件也要包含 ARMCC 的 include 和 include/rw 目录。

不过插件会做好配置,不用我们操心 。

4.4 修改 makefile ,搭建 task

main.c 文件里键入测试代码

 #include "stm32f10x.h"
 
 void GPIO_config(void);
 
 void LED_on(void);
 void LED_off(void);
 
 void delay(uint32_t i);
 
 int main(void) {
  GPIO_config();
 
  while (1) {
  LED_off();
  delay(0x0FFFFF);
 
  LED_on();
  delay(0x0FFFFF);
  }
 
  return 0;
 }
 
 void GPIO_config(void) {
  GPIO_InitTypeDef GPIO_init_args;
 
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 
  GPIO_init_args.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_init_args.GPIO_Pin  = GPIO_Pin_1;
  GPIO_init_args.GPIO_Speed = GPIO_Speed_50MHz;
 
  GPIO_Init(GPIOB, &GPIO_init_args);
 }
 
 void LED_on(void) {
  GPIO_ResetBits(GPIOB, GPIO_Pin_1);
 }
 
 void LED_off(void) {
  GPIO_SetBits(GPIOB, GPIO_Pin_1);
 }
 
 void delay(volatile uint32_t i) {
  while (i--);
 }

然后,我们还要修改 makefile 里的内容。

  • TAGET 生成的目标名称

  • C_SOURCE C/C++ 文件,例

######################################
# source
######################################
# C sources
C_SOURCES += $(wildcard Driver/CMSIS/*.c)
C_SOURCES += $(wildcard Driver/FWLB/src/*.c)
 C_SOURCES += $(wildcard src/*.c)
  • ASM_SOURCE 启动文件或汇编文件,例

     # ASM sources
     ASM_SOURCES = Driver/STARTUP/startup_stm32f10x_hd.s
    
  • LDSCRIPT 链接脚本,例

#######################################
# LDFLAGS
#######################################
# link script
LDSCRIPT = Driver/LINK_SCRIPTS/stm32_flash.ld
  • C_INCLUDE C/C++ 的头文件搜索目录,例
# C includes
C_INCLUDES =  \
-Isrc \
-IDriver/CMSIS \
-IDriver/FWLB/inc 
  • C_DEFS 一些配置用的宏定义,一般用来指定开启某些功能用的,例
# C defines
C_DEFS =  \
-DUSE_STDPERIPH_DRIVER \  # 不定义的话,FWLB的内容不会被包含
-DSTM32F10X_HD           # 定义设备

4.5 构建编译任务

构建 tasks 。菜单中选择 Terminal --> Configure Tasks... --> 选择 gcc.exe 生成(其实,哪个都行,反正都要改)。然后把 tasks.json 化简,并把部分信息整理下。下面是我的例子,

{
  "version": "2.0.0",
  "tasks": [
  {
  "type": "shell",     // 不知是有何用的,我仿别人的
  "label": "build",  // 这会在 Ctrl+Shift+B 时显示
  "command": "make",  // 这是运行的程序
  "args": [          // 例如 > make

  ]
  "group": "build",  // 这个好像很重要,其与下一组 tasks 一样才能做选择
  }
  ]
 }

然后选择 Ctrl+Shift+B ,因为只有一个任务,故 vscode 自动运行了。

但是,运行了一会儿,就出现报错,

C:\Users\11207\AppData\Local\Temp\cczTFbui.s: Assembler messages:
C:\Users\11207\AppData\Local\Temp\cczTFbui.s:599: Error: registers may not be the same -- `strexb r0,r0,[r1]'
 C:\Users\11207\AppData\Local\Temp\cczTFbui.s:629: Error: registers may not be the same -- `strexh r0,r0,[r1]'
 make: *** [Makefile:141: build/core_cm3.o] Error 1

解决方法,参考自 (20条消息) VS Code + GCC 搭建 STM32 开发环境qq_32166451的博客-CSDN博客vs开发stm环境

问题出在标准固件库里,这里的汇编与 gcc 的不一致,故要修改文件 core_cm3.c

在文件 core_cm3.c 里搜索 strexbstrexh ,把两行语句里的 =r 修改成 =&r

保存后,可再尝试。最后编译成功会得出下面类型的语句

arm-none-eabi-size build/stm_gcc.elf
text    data     bss     dec     hex filename
1376       8     540    1924     784 build/stm_gcc.elf
arm-none-eabi-objcopy -O ihex build/stm_gcc.elf build/stm_gcc.hex
arm-none-eabi-objcopy -O binary -S build/stm_gcc.elf build/stm_gcc.bin

4.6 烧录程序

烧录的程序,我们使用的是 pyocd 。其可以通过 pip install pyocd 来安装。可参考 玩转 pyocd - 哈拎 - 博客园 (cnblogs.com)

我记录一些基本应用。

> > pyocd list
#   Probe                          Unique ID
--------------------------------------------------
0   Keil Software Fire CMSIS-DAP   HS-00012048

当你连接上仿真器后,使用此命令就可以读出其类型。

其与 keil MDK 一样,其有些芯片不在自身的库内,可以使用命令下载 ,但很慢 。庆幸的是,也可以其与 keil 芯片包通用。

360截图17700510535946-1651590929435.png

我把从野火论坛下载的包放出来。因为我的芯片是 stm32f103ve6 ,所以我选择了 F1xx 的包。

Documentation — pyOCD

从其文档里得到一信息,包导入的方式可以是在命令行里以额外参数的方式,也可以在项目里键入配置信息。我这使用第二种方法。

创建 pyocd.yaml 文件

pack:
  - Keil.STM32F1xx_DFP.2.4.0.pack

注: - keil... 是指其路径。

然后使用 pyocd list -t-t 即是 --taget 。可以行一些信息,

> > pyocd list -t
 ......
  stm32f103rb               STMicroelectronics      STM32F103RB                  STM32F1 Series, STM32F103   pack
  stm32f103rc               STMicroelectronics      STM32F103RC                                              builtin
  stm32f103rd               STMicroelectronics      STM32F103RD                  STM32F1 Series, STM32F103   pack
  stm32f103re               STMicroelectronics      STM32F103RE                  STM32F1 Series, STM32F103   pack
  stm32f103rf               STMicroelectronics      STM32F103RF                  STM32F1 Series, STM32F103   pack
  stm32f103rg               STMicroelectronics      STM32F103RG                  STM32F1 Series, STM32F103   pack
  stm32f103t4               STMicroelectronics      STM32F103T4                  STM32F1 Series, STM32F103   pack
  stm32f103t6               STMicroelectronics      STM32F103T6                  STM32F1 Series, STM32F103   pack
  ......

这里说明,当前环境下,存在了 F10x 的芯片了。

然后就是配置烧录任务。在 tasks.json 里键入

{
  "tasks": [
  {
  ...
  },
  {
  "type": "shell", 
  "label": "update",
  "command": "pyocd", 
  "args": [
  "load",              // 烧录命令
  "-t",              // 选择目标芯片
  "stm32f103ve",      // 芯片型号
  "./build/test2.elf"  // 下载文件,可以是 elf, hex, bin。其中 bin 文件 
  // File to write to memory. Binary files can have an optional base address appended to the file name as '@<address>', for instance 'app.bin@0x20000'.
  ],
  "group": "build",
  }
  ]
 }

当然还有其他功能,日后再细看。

4.7 调试程序

点击左侧面板的调试,选择创建 launch.json 文件

360截图17700510535946-1651592703906.png

然后选择 GDB 那一行。

点击右下角的 add configuration... 选择 cortext-debug: PyOcd

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
  {
  "cwd": "${workspaceFolder}",
  "executable": "./build/stm_gcc.elf",     // 修改成相应的 elf 路径 
  "name": "Debug with PyOCD",
  "request": "launch",
  "type": "cortex-debug",
  "runToEntryPoint": "main",
  "showDevDebugOutput": "none",
  "servertype": "pyocd"

  /* 重点 */
  "targetId": "stm32f103ve",                  // 芯片型号
  "cmsisPack": "Keil.STM32F1xx_DFP.2.4.0.pack"  // 包路径
  }
 
  ]
 }

配置完,就能像平时那样调试了。

五、祝君好运 ~~

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

推荐阅读更多精彩内容