VSCode上调试 MCU 程序,以 OpenOCD 和 JLink 为例
环境准备
需要下载的软件:
需要准备的硬件
-
JLink OB
-
STM32F407 的开发板
MSYS2的配置
安装 make 和 cmake
暂时只用到了 make,之后可能会用到 cmake,就一起都安装了
安装命令:pacman -Sy make cmake
查看 make 版本信息:make -v
查看 cmake 版本信息:cmake --version
卸载已经安装的包
如果错误安装了其它包,可以使用如下命令卸载
卸载命令:pacman -Rs [pkg name|...]
安装 OpenOCD
将下载好的 OpenOCD 的压缩包解压到 /opt
目录下
查看 OpenOCD 版本信息:openocd -v
安装交叉编译工具链
在这一步大多都会使用 pacman 安装 MSYS2 提供的工具链,但安装完之后,该工具链的 gdb 无法运行,所以这里使用 SysProgs 提供的工具链:
-
先运行安装包,将工具链安装到指定位置
-
再将工具链从指定位置复制到
/mingw32
-
删除
/mingw32/bin/make.exe
,否则它可能会覆盖之前安装的 make -
查看工具链版本信息
-
gcc 版本:
arm-none-eabi-gcc -v
-
gdb 版本:
arm-none-eabi-gdb -v
-
不直接安装到 /mingw32 是为了安全,因为 pacman 可能会破坏工具链
VSCode 的配置
插件安装
一、需要安装的插件
-
C/C++,完成智能感知与自动补全
-
HEX Editor,查看二进制文件和内存
-
Cortex-Debug,完成调试配置
二、推荐额外安装的插件
-
C/C++ Themes
-
Material Icon Theme
-
Chinese(Simplified)
-
CMake
-
Git History
使用 MSYS2 作为默认 shell
settings.json
{
"terminal.integrated.defaultProfile.windows": "MSYS2",
"terminal.integrated.profiles.windows": {
"PowerShell": {
"source": "PowerShell",
"icon": "terminal-powershell"
},
"Command Prompt": {
"path": [
"${env:windir}\\Sysnative\\cmd.exe",
"${env:windir}\\System32\\cmd.exe"
],
"args": [],
"icon": "terminal-cmd"
},
"Git Bash": {
"source": "Git Bash"
},
"MSYS2": {
"path": "${msys_root}/usr/bin/bash.exe"
}
},
"terminal.integrated.env.windows": {
"MSYSTEM": "MINGW32",
"CHERE_INVOKING": "1",
"MSYS2_PATH_TYPE": "inherit",
"PATH":"/mingw32/bin:/usr/local/bin:/usr/bin:/opt/OpenOCD/bin"
}
}
${msys_root}/usr/bin/bash.exe 是一个绝对路径,将${msys_root}替换成自己的 MSYS2 安装根目录
项目生成与配置
首先使用 STM32CubeMX 生成一个 Makefile 项目,假设其根目录为 Project/
然后使用 VSCode 打开 Project/
智能感知配置
.vscode\c_cpp_properties.json
{
"configurations": [
{
"name": "STM32",
"includePath": [
"${workspaceFolder}/**",
"${workspaceFolder}/Drivers/STM32F4xx_HAL_Driver/Inc",
"${workspaceFolder}/Core/Inc"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE",
"USE_HAL_DRIVER",
"STM32F407xx"
],
"compilerPath": "${msys_root}/mingw32/bin/arm-none-eabi-gcc.exe",
"intelliSenseMode": "windows-gcc-arm"
}
],
"version": 4
}
填写说明
属性 | 功能 |
---|---|
name | 项目名称 |
includePath | 项目头文件包含路径 |
defines | 预定义,启用 HAL,设置板件类型 |
compilerPath | 编译器完整路径 |
intelliSenseMode | 智能感知模式 |
调试启动配置
.vscode\launch.json
{
"configurations": [
{
"preLaunchTask": "download",
"cwd": "${workspaceRoot}",
"executable": "build/cubxmx_f407ig.elf",
"name": "OpenOCD",
"request": "launch",
"type": "cortex-debug",
"servertype": "openocd",
"configFiles": [
"jlink_swd.cfg",
"stm32f4x.cfg"
],
"searchDir": [],
"runToEntryPoint": "main",
"showDevDebugOutput": "none",
"gdbPath": "${msys_root}/mingw32/bin/arm-none-eabi-gdb.exe"
}
]
}
填写说明
属性 | 值 | 功能 |
---|---|---|
preLaunchTask | download | 程序下载操作 |
cwd | ${workspaceRoot} | 当前工作目录 |
executable | *.elf | 待调试的程序 |
name | OpenOCD | 配置名称 |
configFiles | —— | OpenOCD 配置文件 |
gdbPath | arm-none-eabi-gdb.exe | gdb 的完整路径 |
编译下载配置
.vscode\tasks.json
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "make"
},
{
"label": "download",
"type": "shell",
"dependsOn": "build",
"command": "openocd",
"args": [
"-f",
"jlink_swd.cfg",
"-f",
"stm32f4x.cfg",
"-c",
"program build/cubxmx_f407ig.bin 0x08000000 verify reset exit"
]
}
]
}
填写说明
属性 | 功能 |
---|---|
label | 操作名称 |
type | 操作类型,一般都填shell |
command | 操作命令 |
args | 操作命令参数 |
dependsON | 操作依赖,填写操作名称 |
OpenOCD 配置
${msys_root}/opt/openocd/share/openocd/scripts/interface/jlink.cfg
${msys_root}/opt/openocd/share/openocd/scripts/target/stm32f4x.cfg
将上面两个文件复制到项目根目录下,并修改 jlink.cfg
#
# SEGGER J-Link
#
# http://www.segger.com/jlink.html
#
adapter driver jlink
#######使用的是 swd 引脚,所以添加如下命令###########
transport select swd
##################################################
# The serial number can be used to select a specific device in case more than
# one is connected to the host.
#
# Example: Select J-Link with serial number 123456789
#
# jlink serial 123456789
将修改完的 jlink.cfg 重命名为 jlink_swd.cfg,可以复制到 ${msys_root}/opt/openocd/share/openocd/scripts/interface/
一份,下次可以直接使用
调试程序
打断点,按 F5
,进行调试
编写测试程序
main.c
int main(void)
{
char *bytes = malloc(128);
char string[] = "test string abcdefghijklmnopqrstuvwxyz";
int size = strlen(string);
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (1)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
while (1)
{
int idx;
char head = string[0];
for (idx = 1; idx < size; idx++)
{
bytes[idx] = string[idx];
string[idx - 1] = bytes[idx];
}
string[idx - 1] = head;
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_3);
HAL_Delay(500);
}
}
}
转换驱动
OpenOCD 无法直接识别 JLink 的驱动,需要使用 zadig 将 JLink 驱动转换为 WinUSB,但这将导致 keil5 无法使用,不过无需担心,这一过程可以使用 UsbDriverTool 逆转,再将 JLink 驱动恢复过来。
发布程序
发布程序时,需要删除程序中的调试信息,此时需要修改 Makefile
######################################
# building variables
######################################
# debug build? 1 表示true,0表示false
DEBUG = 0
# optimization,g表示调试,不优化,3 表示进行 3 级优化
OPT = -O3
修改完之后,重新编译,即可发布
此时再进行调试发现断点无效,因为程序中已经没有调试信息了
标签:bin,OpenOCD,openocd,VSCode,cfg,程序调试,jlink,GPIO,MCU From: https://www.cnblogs.com/lonelyraft/p/VSCodeWithMCU.html