Vscode下调试STM32N6系列单片机的方法

Vscode 下调试 STM32N6 系列单片机的方法


是的,你没有看错,本文就是在有ST官方出的那么多的免费的工具的情况下,还是要自己搞一个调试环境。既然你也点进来看了,那十成十就是你也和我一样,想搞个调试环境,那么这个就是为咱们而书写的。

首先,对于新出的 STM32N6 系列单片机,包括 ST 官方还是非常受欢迎的正点原子,他们使用的开发工具都是 STM32CubeIDE,对于这个开发工具在习惯使用 VScode/Visual Studio 系列开发的我来说实在是不敢恭维。调试归调试,卡慢自不用说,而且常规的调试快捷键也不是通用的。。。并且给单片机中烧写程序还得使用 STM32CubeProg 软件。而且这两个软件搭配一起用的时候对于 STLink v2 的调试更是各种不兼容。。。(STM32CubeIDE 检测到 STLink 版本过低必须要升级才能进行调试,STM32CubeProg 又检测不到被 STM32CubeIDE 升级过的 STLink,只能换一个没升级的才能正常连接进行下载,而且下载程序 STM32CubeProg 还动不动的卡死无响应,牛马不易,实在是严重影响个人情绪呀)。

是的是的,对于当前流行的开发利器,敬爱的ST官方也是提供了一套非常完美的插件 "STM32CubeIDE for Visual Studio Code",让我们可以轻松地在Vscode中进行STM32的开发,但是,我要说但是了哈,如果想要流畅的使用这个插件,首先需要我们配置一个cmake相关的环境和配置,当然这些呢通过STM32CubeMX可以轻松地完成,想要修改呢也是比较简单方便的,但就是文件比较多(模块化,各功能分离、独立配置等),对于源码文件已经很多的情况下对于这种棉裤套秋裤的方式个人是不太喜欢的。其次呢就是想要在仿真的话还要通过鼠标点击这个按钮那个按钮,完全抛弃了cmake通过指令操作的便捷性(仁者见仁智者见智)。当然最重要的就是今天配置好的可以正常仿真的环境,第二天他就可能不好使了,而且你想要重新配置再试的话如果临时文件删除不干净的话照样各种错误报警,而且vscode的版本升级还是比较频繁的,如果vscode升级了同样了会导致兼容性问题导致仿真需要重新配置或者干脆就是不管怎么样就是不行,而且而且还会莫名其妙的出现生成cmake相关配置的时候巨卡无比,导致开发和调试的激情全无。。。。

以上纯属一个初级萌新在进行 STM32N6 系列单片机开发过程中遇到的一些问题或者现象,都是因为 个人学习能力有限、知识储备不足、使用的开发工具使用不熟练、办公电脑硬件配置低 等等原因造成的,并不代表上面提到的开发工具不好用哈。并且哈,每个人在学习和开发中都会遇到各种各样的问题,唯有不断学习、不断思考,才能真正的解决问题。


1 Vscode安装

VSCode 的安装详细过程,请参考如下的资料,此处不再赘述。

手把手配置在Windows下用VsCode开发STM32(保姆级)

对于其他的插件此处将不再进行说明,基本上上述链接中的所有推荐插件均安装即可,下面开始说明的插件是针对 STM32N6 系列单片机。

上面说了那么多,想要开发 STM32N6 还是躲不开官方提供的插件,没办法,毕竟技术不到位,所以还是得用官方的。不过相较于官方推荐的安装插件,本文中说明的调试方式还是省去了不必要的多多余的插件,也基本上跳过了原本调试方式所需要的一且配置和步骤,相对来说更加简单快捷。

在插件商店中搜索"STM32Cube Debug STLink GDB Server",即可找到该插件进行安装,并且会自动按照相关依赖的插件,安装完成即可使用。其依赖的插件安装完应该就如下图中所示的这样。

3 Makefile编写

是的,工程的编译还是使用Makefile,所以还是需要编写Makefile文件。

不管是开发windows应用还是linux应用的开发管理,Makefile和Cmake都是很完善的,也各有千秋,并且cmake因为其跨平台的属性可能更胜一筹,个人在进行软件开发时,一般也是优先选择使用CMake文件进行工程管理。但是对于STM32开发尤其是对于STM32N6来说,如果使用CMake进行工程管理,那么就会触发STM32Cube相关插件的插手,从而将简单的事情反而变得复杂,索性就不用Cmake,省去了插件那躁动不安的检测和无缘无故的界面弹窗(当然,仅限于个人不喜欢哈,他们提供的插件和工具还是非常非常的厉害的哈)。

要编写一个简单的Makefile文件,首先要对整个工程架构了解,哪些文件要参与编译,哪些文件要参与链接、要包含什么头文件等等。本示例中使用的工程架构如下所示。

json 复制代码
stm32n647_vscode_debug_demo_fsbl
├── Drivers
│   ├── CMSIS
│   │   ├── Device
│   │   │   └── ......
│   │   └── Include
│   │       ├── core_cm55.h
│   │       └── tz_context.h
│   │       └── ......
│   └── STM32N6xx_HAL_Driver
│       ├── Inc
│       │   ├── Legacy
│       │   │   └── stm32_hal_legacy.h
│       │   ├── stm32_assert_template.h
│       │   ├── stm32n6xx_hal.h
│       │   ├── ......
│       └── Src
│           ├── stm32n6xx_hal.c
│           ├── stm32n6xx_hal_cortex.c
│           ├── stm32n6xx_hal_crc.c
│           ├── stm32n6xx_hal_crc_ex.c
│           ├── ......
├── HyperRAM
│   ├── hyperram.c
│   └── hyperram.h
├── Makefile
├── NORFlash
│   └── ***.c/h
├── Output
├── STM32CubeIDE
│   ├── .cproject
│   ├── .project
│   ├── STM32N647X0HXQ_AXISRAM2_fsbl.ld
│   └── postbuild.sh
├── STM32_ExtMem_Manager
│   ├── boot
│   │   ├── ***.c/h
│   └── ......
├── SVD
│   └── STM32N647.svd
├── Startup
│   └── startup_stm32n647x0hxq_fsbl.s
├── System
│   ├── syscalls.c
│   └── sysmem.c
├── User
│   ├── extmem
│   │   ├── extmem_manager.c
│   │   ├── extmem_manager.h
│   │   └── stm32_extmem_conf.h
│   ├── it
│   │   ├── stm32n6xx_it.c
│   │   └── stm32n6xx_it.h
│   ├── main
│   │   ├── main.c
│   │   └── main.h
│   ├── stm32n6xx_hal_conf.h
│   ├── stm32n6xx_hal_msp.c
│   ├── system_stm32n6xx_fsbl.c
│   ├── ulog
│   │   ├── uLog.c
│   │   └── uLog.h
│   └── usart
│       ├── usart.c
│       └── usart.h
└── vscode.code-workspace

上面树形结构中的特殊标识说明

... : 代表其他省略的文件或文件夹

**.c/h :代表所有的 .c/h文件
STM32CubeIDE目录:工程中还是保留了STM32CubeIDE工程文件,所以可以直接使用STM32CubeIDE工程文件进行编译、调试等。就是为了在某些时候因为某系原因出现不可预知的问题时,还能表现出从从容容游刃有余,不至于匆匆忙忙连滚带爬。

有了上面的清晰的文件结构,那闲言少叙,直接上硬菜。

makefile 复制代码
TARGET = STM32N647_FSBL

# IMPORTANT 请注意此处将会开启调试模式,将会有大量的日志输出并性能下降,请在正式发布之前关闭调试模式。
DEBUG_ENABLE ?= 0
# debug build?
DEBUG_MODE ?= $(DEBUG_ENABLE)
# optimization
OPT ?= -Os
# Og:优化调试体验。 -Og应该是标准edit-compile-debug周期的优化级别选择,
#     它提供了足够的优化以提高代码执行速度,同时保持了良好的调试体验。
# Os:这个选项是在-O2的基础之上,尽量的降低目标代码的大小,也是编译目标文件最小的选项
# O2:该优化选项会牺牲部分编译速度,除了执行-O1所执行的所有优化之外,还会采用几乎所有的目标
#     配置支持的优化算法,用以提高目标代码的运行速度
# O3:该选项除了执行-O2所有的优化选项之外,一般都是采取很多向量化算法,提高代码的并行执行程度,
#     利用现代CPU中的流水线,Cache等

# Build path
BUILD_DIR = build
OUTPUT_DIR = Output

# CPP sources
CPP_SOURCES =  \

# C sources
C_SOURCES =  \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_cortex.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_dma.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_dma_ex.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_exti.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_gpio.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_pwr.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_pwr_ex.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_rcc.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_rcc_ex.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_uart.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_uart_ex.c \
    Drivers/STM32N6xx_HAL_Driver/Src/stm32n6xx_hal_xspi.c \
    STM32_ExtMem_Manager/boot/stm32_boot_xip.c \
    STM32_ExtMem_Manager/stm32_extmem.c \
    STM32_ExtMem_Manager/psram/stm32_psram_driver.c \
    STM32_ExtMem_Manager/sal/stm32_sal_sd.c \
    STM32_ExtMem_Manager/sal/stm32_sal_xspi.c \
    STM32_ExtMem_Manager/sdcard/stm32_sdcard_driver.c \
    STM32_ExtMem_Manager/nor_sfdp/stm32_sfdp_data.c \
    STM32_ExtMem_Manager/nor_sfdp/stm32_sfdp_driver.c \
    STM32_ExtMem_Manager/user/stm32_user_driver.c \
    User/extmem/extmem_manager.c \
    User/main/main.c \
    User/ulog/uLog.c \
    User/usart/usart.c \
    User/stm32n6xx_hal_msp.c \
    User/it/stm32n6xx_it.c  \
    User/system_stm32n6xx_fsbl.c \

# 包含目录下的所有的.c文件
C_SOURCES += $(wildcard System/*.c)
C_SOURCES += $(wildcard HyperRAM/*.c)
C_SOURCES += $(wildcard NORFlash/*.c)
# ASM sources
ASM_SOURCES =  \
    Startup/startup_stm32n647x0hxq_fsbl.s

# link script
LDSCRIPT = \
    STM32CubeIDE/STM32N647X0HXQ_AXISRAM2_fsbl.ld

# C includes
C_INCLUDES =  \
    -IDrivers/STM32N6xx_HAL_Driver/Inc \
    -IDrivers/CMSIS/Device/ST/STM32N6xx/Include \
    -IDrivers/STM32N6xx_HAL_Driver/Inc/Legacy \
    -ISTM32_ExtMem_Manager \
    -ISTM32_ExtMem_Manager/boot \
    -ISTM32_ExtMem_Manager/sal \
    -ISTM32_ExtMem_Manager/nor_sfdp \
    -ISTM32_ExtMem_Manager/psram \
    -ISTM32_ExtMem_Manager/sdcard \
    -ISTM32_ExtMem_Manager/user \
    -IDrivers/CMSIS/Include \
    -INORFlash \
    -IHyperRAM \
    -IUser/extmem \
    -IUser/it \
    -IUser/ulog \
    -IUser/main \
    -IUser/usart \
    -IUser \

# AS includes
AS_INCLUDES =

# 指定编译工具链的路径,使用CubeIDE带的编译器
ifeq ($(OS), Windows_NT)
	GCC_PATH:=D:/SongshuaiWorkInstall/Stm32CubeIDE/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3.rel1.win32_1.0.0.202411081344/tools/bin
else
	GCC_PATH:=/mnt/d/SongshuaiWorkInstall/Stm32CubeIDE/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.13.3.rel1.win32_1.0.0.202411081344/tools/bin
endif

# binaries
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc.exe
CXX = $(GCC_PATH)/$(PREFIX)g++.exe
AS = $(GCC_PATH)/$(PREFIX)gcc.exe -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy.exe
SZ = $(GCC_PATH)/$(PREFIX)size.exe
else
CC = $(PREFIX)gcc
CXX = $(PREFIX)g++
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
ELF = $(PREFIX)gcc
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S

# cpu With -mcpu=cortex-m55+nomve should be equivalent to -march=armv8.1-m.main+dsp
CPU=-mcpu=cortex-m55

# fpu
FPU =-mfpu=fpv5-d16

# float-abi
FLOAT-ABI =-mfloat-abi=hard
# mcu
MCU = $(CPU) $(FPU) $(FLOAT-ABI)

# macros for gcc
# AS defines
AS_DEFS =

C_STANDARD = -std=gnu11   #c++14

# C defines
C_DEFS =  \
-DUSE_HAL_DRIVER \
-DSTM32N647xx  \

# compile gcc flags
ASFLAGS += $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) $(C_STANDARD) -Wall -fdata-sections -ffunction-sections --specs=nano.specs

CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) $(C_STANDARD) -Wall -fdata-sections -ffunction-sections
# for  warning: 'cmse_nonsecure_call' attribute ignored without '-mcmse' option
CFLAGS += -fstack-usage -fcyclomatic-complexity  -mcmse --specs=nano.specs

# 配置为debug模式
ifeq ($(DEBUG_MODE), 1)
OPT = -O0
CFLAGS += -g3 -DDEBUG -DULOG_ENABLED
endif

# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
# 增加C++的支持
# CFLAGS += -Wl,--start-group -lstdc++ -Wl,--end-group

# libraries
LIBS = -Wl,--start-group -lc -lm -Wl,--end-group
# add .a library like this way! like "-L ./Libraries/ -lKinematic"
LIBDIR =

LDFLAGS = $(MCU) \
-T $(LDSCRIPT) $(LIBDIR) $(LIBS) \
-Wl,-Map=$(BUILD_DIR)/$(TARGET).map \
-Wl,--gc-sections \
--specs=nano.specs \
--specs=nosys.specs \

# -mthumb -u _printf_float \

# 配置FLASH的地址
FLASH_ADDR := 0x70000000

# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).bin  $(OUTPUT_DIR)/$(TARGET).hex

# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(CPP_SOURCES:.cpp=.o)))
vpath %.cpp $(sort $(dir $(CPP_SOURCES)))
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))
# list of ASMM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASMM_SOURCES:.S=.o)))
vpath %.S $(sort $(dir $(ASMM_SOURCES)))

$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
	$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
	$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
	$(AS) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
	$(AS) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
	$(ELF) $(OBJECTS) $(LDFLAGS) -o $@
	$(SZ) $@

$(OUTPUT_DIR)/$(TARGET).hex: $(OUTPUT_DIR)/$(TARGET)-trusted.bin | $(OUTPUT_DIR)
	$(HEX) -I binary $< --change-addresses $(FLASH_ADDR) $@

$(BUILD_DIR)/$(TARGET).bin: $(BUILD_DIR)/$(TARGET).elf | $(BUILD_DIR)
	$(BIN) $< $@

$(OUTPUT_DIR)/$(TARGET)-trusted.bin: $(BUILD_DIR)/$(TARGET).bin | $(OUTPUT_DIR) clean
	make sign

$(BUILD_DIR):
	@mkdir $@

$(OUTPUT_DIR):
	@mkdir $@

# SECTION 配置下载使用的工具路径
# 使用STM32CubeIDE自带的编译工具链,直接通过全路径指定,也可以使用自己安装的编译工具链,修改对应路径即可
ifeq ($(OS), Windows_NT)
PROTOOL_DIR:=D:/SongshuaiWorkInstall/Stm32CubeIDE/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_2.2.200.202503041107/tools/bin
else
PROTOOL_DIR:=/mnt/d/SongshuaiWorkInstall/Stm32CubeIDE/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_2.2.200.202503041107/tools/bin
endif

# 因为.exe的缘故,传入参数的路径得是win环境下的路径,所以使用固定的路径和文件,兼容WSL环境,Linux环境请自行修改
EXTMEM_LOADER=D:/SongshuaiWorkInstall/Stm32CubeIDE/STM32CubeIDE_1.19.0/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_2.2.200.202503041107/tools/bin/MX25UM25645G_ATK-CNN647B_ExtMemLoader.stldr
# !SECTION 配置下载使用的工具路径

# 输出的目标bin文件
.PHONY:sign
sign:
	STM32_SigningTool_CLI.exe -bin $(BUILD_DIR)/$(TARGET).bin -nk -of 0x80000000 -t fsbl -o  $(OUTPUT_DIR)/$(TARGET)-trusted.bin -hv 2.3 -dump $(OUTPUT_DIR)/$(TARGET)-trusted.bin

# 下载文件到flash中,使用STM32_Programmer_CLI.exe
.PHONY:download
download:
	$(PROTOOL_DIR)/STM32_Programmer_CLI.exe -c port=SWD freq=4000 -w $(OUTPUT_DIR)/$(TARGET).hex  -v  -el $(EXTMEM_LOADER)

# 下载文件到flash中,使用STM32_Programmer_CLI.exe
.PHONY:download_bin
download_bin:
	$(PROTOOL_DIR)/STM32_Programmer_CLI.exe -c port=SWD freq=4000 -w $(OUTPUT_DIR)/$(TARGET)-trusted.bin $(FLASH_ADDR) -v -el $(EXTMEM_LOADER)

# win环境下删除子目录中的文件 (需加 /S 参数),并且下面指令如果前面加@的话在不存在目标文件的情况下会报错出来导致编译中断
.PHONY:clean
clean:
ifeq ($(OS), Windows_NT)
	del /S /F /Q $(OUTPUT_DIR)\*.bin $(OUTPUT_DIR)\*.hex
else
	@rm -rf $(OUTPUT_DIR)/*.bin $(OUTPUT_DIR)/*.hex
endif

.PHONY:cleanall
cleanall:clean
ifeq ($(OS), Windows_NT)
	@del  /S /F /Q $(BUILD_DIR) $(OUTPUT_DIR) .clangd  User/$(BUILD_DIR) User/.settings
else
	@rm -rf $(BUILD_DIR) $(OUTPUT_DIR) .clangd  User/$(BUILD_DIR) User/.settings
endif

.PHONY:debug
debug:
	$(MAKE) DEBUG_ENABLE=1 all -j16

# dependencies
-include $(wildcard $(BUILD_DIR)/*.d)

至于上面的Makefile文件,就是最简单的最基础的一些语法,我相信大家都能明白而且注释和说明已经非常详细,就不再赘述了。

4 工程配置文件编写

Vscode下面的配置三件套,没什么可以描述的,如果还有不太理解的地方,可以参考下面这篇文章。

手把手配置在Windows下用VsCode开发STM32(保姆级)

4.1 c_cpp_properties.json

json 复制代码
>{
    "configurations": [
        {
            "name": "STM32N6xx",
            "includePath": [
                "${default}",
                "${workspaceFolder}/**",
                "${workspaceFolder}/Drivers/STM32N6xx_HAL_Driver/Inc/**",
                "${workspaceFolder}/Drivers/CMSIS/Device/ST/STM32N6xx/Include/**",
                "${workspaceFolder}/Drivers/STM32N6xx_HAL_Driver/Inc/Legacy/**",
                "${workspaceFolder}/STM32_ExtMem_Manager/**",
                "${workspaceFolder}/STM32_ExtMem_Manager/boot/**",
                "${workspaceFolder}/STM32_ExtMem_Manager/sal/**",
                "${workspaceFolder}/STM32_ExtMem_Manager/nor_sfdp/**",
                "${workspaceFolder}/STM32_ExtMem_Manager/psram/**",
                "${workspaceFolder}/STM32_ExtMem_Manager/sdcard/**",
                "${workspaceFolder}/STM32_ExtMem_Manager/user/**",
                "${workspaceFolder}/Drivers/CMSIS/Include/**",
                "${workspaceFolder}/NORFlash/**",
                "${workspaceFolder}/HyperRAM/**",
                "${workspaceFolder}/User/extmem/**",
                "${workspaceFolder}/User/it/**",
                "${workspaceFolder}/User/ulog/**",
                "${workspaceFolder}/User/main/**",
                "${workspaceFolder}/User/usart/**",
                "${workspaceFolder}/User/**"
            ],
            "defines": [
                "USE_HAL_DRIVER",
                "STM32N647xx",
                "DEBUG",
                "ULOG_ENABLED",
                "uint8_t=unsigned char",
                "uint16_t=unsigned int",
                "uint32_t=unsigned long",
                "int8_t=char",
                "int16_t=int",
                "int32_t=long",
                "bool=unsigned char",
                "static=",
                "UNICODE",
                "__GNUC__"
            ],
            "intelliSenseMode": "${default}"
        }
    ],
    "version": 4
}

4.2 launch.json

重点就是这个配置文件,由于STM32N6系列与其他的STM32系列的不同,导致上面文章中的同样配置无法进行调试,所以才有了这篇文章。

下面这些配置的内容依赖于插件,所以必须要安装 STM32Cube Debug STLink GDB Server 插件。

json 复制代码
{
    "configurations": [
        {
            "type": "stlinkgdbtarget",
            "request": "launch",
            "name": "Debug STM32N647 FSBL STLINK",
            "cwd": "${workspaceFolder}",
            "runEntry": "main",
            "preLaunchTask": "build",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${workspaceFolder}/build/STM32N647_FSBL.elf"
                }
            ],
            "verbose": false,
            "deviceName": "STM32N647X0H3Q",
            "deviceCore": "Cortex-M55",
            "deviceTrustzone": "Secure-only",
            "svdPath": "${workspaceFolder}/SVD/STM32N647.svd",
            "serverApID": "1",
            "serverReset": "Connect under reset",
            "serverInterface": "SWD",
            "serverInterfaceFrequency": "Auto",
            "serverShared": false,
            "serverHaltAllCores": false,
            "serverHost": "localhost",
            "serverPort": "61234",
            "openGdbConsole": false,
            "faultDivByZero": true,
            "faultUnalignedAccess": false,
            "faultHaltOnException": true
        }
    ]
}

好像也没有什么是需要特殊说明的,只要是按照这个配置文件来,就可以正常使用了。

4.3 tasks.json

json 复制代码
{
    "version": "2.0.0",
    "tasks": [
        {
            // 编译任务
            "label": "build",
            "type": "shell",
            "command": "make",
            "args": [
                "DEBUG_ENABLE=1",
                "-j16"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [
                "$gcc"
            ],
            "detail": "Build the project using Makefile."
        }
    ]
}

5 开始调试

5.1 正常调试

按照上面的配置,直接打开到调试页面,点击调试按钮,就可以开始调试了。省去了很多CubeIDE中需要手动配置的步骤。

当然了,在调试过程中,从出现输出信息

json 复制代码
Start address 0x3418ef34, load size 65804
Transfer rate: 147 KB/sec, 5483 bytes/write.
set *(int *)0xE000ED14=*(int *)0xE000ED14|0x10
set *(int *)0xE000EDFC=*(int *)0xE000EDFC|0xff0

json 复制代码
Temporary breakpoint 1, main () at User/main/main.c:42
42	    SCB_EnableICache();
...

这个过程中,还是稍微等了点时间,大概5~6秒钟的样子,但是这个时间相较于使用CubeIDE或者插件中使用cmake调试来说还是可以接受的。下面就是调试的显示效果图。

5.2 可能遇到的问题及解决方法

1. 弹出不识别的类型,如下如所示。

解决方法:

都说了要安装依赖的插件,安装之后再试试,要是还不行的重启Vscode再试试。

2. 弹出连接超时的提示,如下如所示。

解决方法:

只要会一点英语知识会知道,说的是STLink初始化错误,没有发现单片机,只要打开开发板的电源、或者把STLink重新插拔一下、或者检查一下连接线是不是接对了等等,问题就解决了。

3. 调试时发现程序运行与实际代码不符,如下图所示。

解决方法:

没什么大不了的哈,这个是因为本次调试使用的 ***.elf 与调试的源代码没有关系,大概两个方面的原因:

1. launch.json配置内容中 "imageFileName" 指定的文件路径不是正确的文件路径

2. 本次调试的是因为源代码有错误导致编译失败,调试中使用的上次生成的 ***.elf 文件

至此,才真正开始快乐的调试了。


2025.12.20日补充说明:

最近的开发中想要进行调试的时候,每次在首次打开Vscode工程,或者在调试过程中异常断开之后,再次进行调试的时候,点击这个调试开始按钮,都会出现很长时间的等待过程,就像下图中一直得转圈圈等待。

直到等了三天之后再右下角弹出信息提示框,点击"Yes"或者"No"之后才能正常开始编译下载调试。

每次搞得人心态要爆炸,TNN的这ST的GOUPI插件每次都能整个大的恶心人,要不是项目时间紧张高低给他换了。后续有时间了再研究研究使用openocd的方式吧。


2026.01.06日补充说明:

前段时间调试其他设备就先把插件给禁用了,今天要调试 STM32N647 ,结果那代码运行调试时,就开始提示如下图所示的信息。

TMD真是够了,重新启用之后自动给升级到了 V1.1.0 的版本了,但是刚开始一致没有注意到,走了许多的弯路。后来将版本降下来 V1.0.2 的版本就正常了,真是 我去年买了个表呀, 关闭自动更新应该可以用一段时间了吧。

哈哈哈哈哈,高兴的太早了,隔了个周末重新开机就尼玛又不行了,同样的在 调试控制台 页面中显示的信息是 ERROR: Couldn't locate STM32CubeProgrammer in '..\STM32CubeProgrammer\bin\', use -cp <path>,同样的报错信息(上上个图中)。遂开始在我的机器上查找每一个 "ST-LINK_gdbserver.exe" 所在的位置,并且修改名称后重新启动调试,就要看看这个破插件到底调用的是哪个目录下的 "ST-LINK_gdbserver.exe",经过一番努力,终于知道了原来它调用的位置在这儿。

既然已经知道大概率是版本升级的问题的话,那就大胆的删除了 7.12.0+st.2 目录,然后重新启动调试,哎嘿,又可以了。

管他呢,先用着吧。。。。


好啦,废话不多说,总结写作不易,如果对本文的内容有任何疑问或者建议,请随时联系并欢迎讨论,由于本人学识与精力有限,难免会有一些错误或不足,欢迎大佬指出并斧正。如果你觉得此文章对你有帮助,烦请帮忙点个赞鼓励一下,你的鼓励将是我继续坚持努力的动力。

相关推荐
余生皆假期-2 小时前
永磁同步电机下桥三电阻采样方式的电机电流重构方法
单片机·嵌入式硬件·嵌入式
蓬荜生灰3 小时前
STM32(12)-- GPIO输入,按键检测
stm32·单片机·嵌入式硬件
DLGXY3 小时前
STM32——ADC、多通道转换(十三)
stm32·单片机·嵌入式硬件
日更嵌入式的打工仔3 小时前
嵌入式MPU、MCU与SoC的本质区别
单片机·嵌入式硬件
__万波__4 小时前
STM32L475看门狗
stm32·单片机·嵌入式硬件
wanglong37134 小时前
51单片机STC8G1K08输出PWM
单片机·嵌入式硬件·51单片机
量子炒饭大师13 小时前
【一天一个计算机知识】—— VScode 极速搭建:打造你的全能代码武器库
ide·vscode·编辑器
程序员贵哥13 小时前
彻底还原VSCode:Windows下完全重置VS Code配置的方法
vscode
石国13 小时前
windows10 win10 pyside6 vscode 安装与配置
vscode·pyside6·windows10