使用VSCode开发STM32 (通用版本)

本文以启明欣欣的工控板举例,讲述如何使用VSCode来开发STM32。MCU是STM32F407ZGT6

一 准备

1. 交叉编译器

打开https://gitlab.arm.com/tooling/gnu-toolchains-for-arm,找到编译器列表,

选择一个合适的,这里选最新的15.3.rel1,点击进入后下拉,找到如下Windows hosted交叉编译器,

选择红框中的任意一个,第一个是安装版,第二个是免安装版,本人下载了第二个,下载后找个目录解压,然后把目录下的bin目录添加到系统环境变量PATH里,例如本人的解压路径是D:\SW\arm-gnu-toolchain-15.3.rel1,

然后把D:\SW\arm-gnu-toolchain-15.3.rel1\bin添加到系统环境变量Path里,

  • 右键 "此电脑" → "属性" → "高级系统设置" → "环境变量"
  • 在 "系统变量" 中找到 Path,点击 "编辑",添加:D:\SW\arm-gnu-toolchain-15.3.rel1\bin

2. ninja

ninja用来代替make做实际的编译工作。

打开https://github.com/ninja-build/ninja/releases/,在Assets里找到Windows版本,

下载后解压到一个目录,然后把这个目录地址添加到系统环境变量Path了

3. openocd

打开https://github.com/xpack-dev-tools/openocd-xpack/releases,在Assets里找到Windows版本,

解压后把bin目录添加到系统环境变量Path里

4. CMake

下载Windows版本并安装,也要添加系统环境变量Path里,不再赘述

5. VSCode插件

安装CMake Tools和Cortex-Debug这2个插件即可

6. CubeMX工程

可以参考https://blog.csdn.net/whahu1989/article/details/144226202来创建CubeMX工程,同时把PE3,PE4和PG9配置成输出的GPIO,可以操作板子上的灯

在生成项目时注意以下几点,

Toolchain / IDE选择Makefile,这样生成的启动汇编文件和链接器脚本可以直接复用,另外勾选如下,


二 移植到VSCode

创建个目录然后使用VSCode打开,然后创建如下目录和文件,

然后按照如下步骤进行拷贝,

  • CubeMX工程的Core目录里的东西拷贝到VSCode工程的Core目录里
  • CubeMX工程的Drivers目录里的东西拷贝到VSCode工程的Drivers目录里
  • CubeMX工程的STM32F407xx_FLASH.ld拷贝到VSCode工程的ld目录
  • CubeMX工程的startup_stm32f407xx.s拷贝到VSCode工程的startup目录

CMakeLists.txt的内容如下,

bash 复制代码
cmake_minimum_required(VERSION 3.20)


set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")

# 交叉编译器
set(TOOLCHAIN_PREFIX arm-none-eabi-)
set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}g++)
set(CMAKE_ASM_COMPILER ${TOOLCHAIN_PREFIX}gcc)
set(CMAKE_OBJCOPY ${TOOLCHAIN_PREFIX}objcopy)
set(CMAKE_OBJDUMP ${TOOLCHAIN_PREFIX}objdump)

project(STM32F407_APP LANGUAGES C CXX ASM)

# ================= STM32F407 M4F 配置 =================
set(MCU_CORE cortex-m4)

# 编译标志:每个参数单独一项,禁止空格拼接长字符串
add_compile_options(
    -mcpu=${MCU_CORE}
    -mthumb
    -mfpu=fpv4-sp-d16
    -mfloat-abi=hard
    -Og
    -g3
    -Wall
    -ffunction-sections
    -fdata-sections
    -std=c99
)

# 汇编文件启用cpp预处理
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-xassembler-with-cpp>)

# 链接参数同样!拆成独立元素,不要长字符串
add_link_options(
    -mcpu=${MCU_CORE}
    -mthumb
    -mfpu=fpv4-sp-d16
    -mfloat-abi=hard
    -T${CMAKE_SOURCE_DIR}/ld/STM32F407xx_FLASH.ld
    -Wl,--gc-sections
    -Wl,-Map=${PROJECT_NAME}.map
    --specs=nano.specs
    --specs=nosys.specs
)

# ================= 文件列表 =================
file(GLOB_RECURSE USER_SOURCES
    Core/Src/*.c
    Drivers/STM32F4xx_HAL_Driver/Src/*.c
    Drivers/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c
)

# GCC启动汇编
set(ASM_SOURCES startup/startup_stm32f407xx.s)

# 头文件路径
include_directories(
    Core/Inc
    Drivers/STM32F4xx_HAL_Driver/Inc
    Drivers/CMSIS/Device/ST/STM32F4xx/Include
    Drivers/CMSIS/Include
)

# 预定义宏(和CubeMX保持一致)
add_definitions(
    -DSTM32F407xx
    -DUSE_HAL_DRIVER
)

add_executable(${PROJECT_NAME}.elf ${USER_SOURCES} ${ASM_SOURCES})

# 生成hex、bin、反汇编
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
    COMMAND ${CMAKE_OBJCOPY} -O ihex ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
    COMMAND ${CMAKE_OBJCOPY} -O binary ${PROJECT_NAME}.elf ${PROJECT_NAME}.bin
    COMMAND ${CMAKE_OBJDUMP} -d ${PROJECT_NAME}.elf > ${PROJECT_NAME}.lst
)

.vscode目录下创建settings.json和launch.json,

settings.json内容如下,

bash 复制代码
{
    "cmake.generator": "Ninja",
    "cmake.buildDirectory": "${workspaceFolder}/build",
    "C_Cpp.default.compilerPath": "arm-none-eabi-gcc",
    "C_Cpp.default.includePath": [
        "${workspaceFolder}/**"
    ],
    "C_Cpp.default.defines": [
        "STM32F407xx",
        "USE_HAL_DRIVER"
    ]
}

launch.json内容如下,

bash 复制代码
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug STM32F407 STLink",
            "type": "cortex-debug",
            "request": "launch",
            "servertype": "openocd",
            "executable": "${workspaceFolder}/build/STM32F407_APP.elf",
            "configFiles": [
                "interface/stlink.cfg",
                "target/stm32f4x.cfg"
            ],
            "runToEntryPoint": "main",
            "cwd": "${workspaceFolder}",
            "svdFile": "${workspaceFolder}/STM32F407.svd"
        }
    ]
}

注意:CMakeLists.txt里设定的输出目标名字是STM32F407_APP.elf,所以在launch.json里配置"executable"时也要使用相同的文件


三 编译

在工程目录下打开终端,然后执行下面的命令进行编译,

bash 复制代码
cmake -GNinja -B build -S .
cmake --build build

编译完成后可以在build目录下看到生成的elf,hex和bin文件,


四 下载和调试

launch.json里设定了下载和调试,此时打开左侧的"Run and Debug",可以看到在已经有一个调试配置,这个名字和launch.json里设定的是一样的

点击这个名字左侧的绿色三角调试按钮,就可以自动下载并开启调试,直接走到main函数里并停下。用户可以在main.c里加点操作GPIO的代码来验证效果。


五 小结

本文讲述了如何使用VSCode开发STM32,可能会问为什么不使用ST提供的VSCode插件?或者为什么不使用PlatformIO?本人是为了简化和通用性,ST的插件只能用在ST的芯片,如果有其它厂的芯片就用不了,PlatformIO感觉有点重而且它不是使用CMake的。

最重要的一点是,如果项目已经很成熟,MCU及其外设什么的都是固定的,那么这样做就会简单很多,降低维护成本。

相关推荐
小黄蚁21 小时前
使用状态机实现按键消抖
stm32·单片机
FlightYe1 天前
音视频修炼之视频基础(一):视频基础理论
android·c++·vscode·音视频·androidx·android runtime
我要见SA姐11 天前
VsCode 使用指南(配置 + 美化)
ide·vscode·编辑器
CodeQingqing1 天前
STM32HAL + FreeRTOS:改时基进入HardFault_Handler
stm32·单片机·嵌入式硬件
科芯创展1 天前
1.8VIN,3.3/5VOUT,电荷泵升压芯片,XZ3110
stm32
W_326001 天前
VSCode 进阶
c语言·vscode
茯苓gao2 天前
嵌入式开发笔记:CAN与CAN FD完全指南——从帧格式差异到MCU选型实战
网络·笔记·stm32·嵌入式硬件·学习·汽车
木木_王2 天前
嵌入式学习 | STM32 裸板驱动开发(Day06) | DHT11温湿度传感器超详解(单总线时序+全套驱动代码+智能温湿度报警项目)
驱动开发·stm32·学习
洛兮银儿2 天前
VScode注释快捷键的修改
ide·vscode·编辑器