目录
1.1-综述
2-vscode实现一键下载stm32
2.1-jlink的下载与擦除的makefile修改
2.2-stlink的下载与擦除的makefile修改
2.3-提升一点效率:使用tasks.json配置用户任务(下拉菜单)
1-tasks.json干啥用的
2-如何创建tasks.json?
3-tasks.json的文件编辑
4-tasks的使用方法
2.4-再提升一点效率:使用keybindings.json配置快捷键
1-keybindings.json可以配置自定义快捷键
2-打开keybindings.json
3-keybindings.json文件的编译
3-实现vscode里在线调试stm32
3.1-调试原理及分层结构
3.2-配置settings.json用于在线调试
1-配置vscode的settings.json
2-Cortex-Debug介绍
3-launch.json用于配置vscode的调试设置
4-测试运行
4.1-结论
这里介绍如何在vscode下实现jlink/stlink下载及在线调试;使用前面博客里的工程(参见0503,0504两个博文)里的名为may12的project,硬件也还是NUCLEO-F429ZI。在开发中,除了使用vscode进行酷炫的代码编辑,工程组织外,还有本文的重点:使用vscode对目标板进行下载(擦除、下载、复位)及调试(单步,查看寄存器),以及配置快捷键方便一键执行,毕竟调试个bug烧写800遍也不是啥丢人的事。
note: 我并不打算写一个step-by-step的说明,我尽量扩展一些原理性的东西,增加理解,如果需要可以直接参考附录的链接去DIY作为辅助,视频信息量并不中心支撑对系统的理解,因为如果不懂原理任意一个bug都要花费数小时。当然建议视频与博文都看一下。
下载的前置准备工作已经在 0503和0504两个博文里准备完毕,命令行都测试OK,接下来就是要把命令行放到makefile里,这样就可以在vscode的命令行里通过make指令调用这一大串命令行,等于一条vscode指令执行一串其他软件的功能;这是基础,是后面使用用户快捷键的基础。本章节的重点是编辑makefile文件+编辑tasks.json文件。
note: 先在vscode命令行中进行测试,确认运行正常后,放到makefile里。
#1- First create a file with all commands
$(BUILD_DIR)/jlink_flash_file: $(BUILD_DIR)/$(TARGET).bin
@touch $@
@echo device $(DEVICE) >> $@
@echo -e si 1 '\n' speed 10000 >> $@
@echo loadbin $< 0x08000000 >> $@
@echo -e r'\n'g'\n'qc'\n' >> $@
#2- Flash with J-Link
jflash: $(BUILD_DIR)/jlink_flash_file
JLink -commanderscript $<
通过make jflash指令就可以测试下载,指令执行时会先检查/build/jlink_flash_file文件是否存在,不存在的话就调用第一条rule来创建它,
打开build/jlink_flash_file,文件里是这样的,如下图
同理,有的时候我们还需要全片擦除操作,脚本文件类似,只是第三行用erase指令,默认不给参数的话表示全片擦除
$(BUILD_DIR)/jlink_erase:
@touch $@
@echo device $(DEVICE) >> $@
@echo -e si 1 '\n' speed 10000 >> $@
@echo erase >> $@
@echo -e r'\n'g'\n'qc'\n' >> $@
jerase: $(BUILD_DIR)/jlink_erase
JLink -commanderscript $<
st的下载指令要简单很多,一行搞定,在makefile里任意位置添加如下内容,这里是两条rule,第一条sterase,表示要擦除全片,因为是直接调用指令执行,所以没有任何依赖;第二条rule是stflash,依赖.bin文件存在,调用st-flash命令执行将bin文件下载到0x08000000的位置。
# st-util erase and flash
sterase:
st-flash --freq=4000 erase
stflash: $(BUILD_DIR)/$(TARGET).bin
st-flash --reset write $< 0x08000000
测试一下,在vscode的任意命令行里,打入make sterase 即可执行擦除,用时约半分钟,同理打入make stflash测试下载指令,下载完成后会自动复位运行,使用st进行下载的速度要远慢于使用jlink的速度。
在这里( Tasks in Visual Studio Code)了解关于tasks.json的作用,简单来说,就是vscode设计的专门配置如何调用外部功能的接口,因为这些外部的功能如make, lint等是开发环节中的重要部分,而且大部分是命令行式的。这一段所描述的所有内容都可以在这个链接里找到,建议认真阅读原文,要查看具体字段如"group"使用说明可以直接在网页里搜索。再简单来说,有了tasks.json就可以配置用户自己的下接菜单。
有两个方法,一、手动自己创建.vscode/tasks.json, 因为文件内容比较简单所以完全可以自己创建,省得记忆下面提到创建方法路径, 二、菜单的Terminal->configure tasks... 或者用CTRL+P 弹出输入框,输入‘>Task’列表显示一堆,选择“Tasks:Config Task”继续选择Creat tasks.json file from template 。 这里差别不大,因为我们只是要一个文件,然后里面内容删掉重写。
针对stm32开发的用到的功能只是tasks.json中很简单的一块,这里一共定义了6个task,分别说明如下,
调用make指令执行编译,实际执行的命令行是‘make all -j4’调用4核全力执行
调用make指令执行清理工程,实际执行‘make clean’,删除build目录及内容
jlink的下载,实际执行的是‘make -j4 jflash’
jlink的擦除,实际执行的是‘make jerase’
stlink的下载,实际执行的是 ‘make -j4 stflash’
stlink的擦除,实际执行的是‘st-flash --freq=4000 erase’
这里注意,第6个task没有通过makefile执行,而是直接调用st-flash指令,当然也可以从makefile里执行,调用'make sterase'即可。这表明tasks.json可以让vscode调用任意外部功能,如make.exe和st-flash.exe。
{
"version": "2.0.0",
"tasks": [
// MAKE(BUILD + CLEAN)
{
"label": "task-build",
"group": "build",
"type": "shell",
"command": "make",
"args": [
"all",
"-j4"
]
},
{
"label": "task-clean",
"group": "build",
"type": "shell",
"command": "make",
"args": ["clean"]
},
// JLINK (FLASH + ERASE)
{
"label": "task-jflash",
"group": "build",
"type": "shell",
"command": "make",
"args": [
"-j4",
"jflash"
]
},
{
"label": "task-jerase",
"group": "build",
"type": "shell",
"command": "make",
"args": ["jerase"]
},
// STLINK (FLASH+ERASE)
{
"label": "task-stflash",
"group": "build",
"type": "shell",
"command": "make",
"args": ["-j4", "stflash"]
},
{
"label": "task-sterase",
"group": "build",
"type": "shell",
"command": "st-flash",
"args": ["--freq=4000","erase"]
},
]
}
CTRL+SHIFT+B 或 Terminal->Run Build Task... 即可调出‘下拉菜单’,通过方向键选择并按回车执行。‘下拉菜单’中各项名称就是tasks.json中对应的"label"参数配置的。‘下拉菜单’的执行效果等同于键入对应的命令行。
上面的tasks是方便了一些,但是还不够,因为比如之前用KEIL的,是可以直接按F7编译,按F8下载的,所以为了让开发更简单一点,这里研究一下如何配置vscode的快捷键,注意和所有工程相关的配置不一样,快捷键的配置是工程无关的。
更多信息可以在 链接( Tasks in Visual Studio Code)里找到,搜索关键字“Binding keyboard shortcuts to tasks”,关于vscode的全局的快捷键的使用在这个链接( Visual Studio Code Key Bindings)里查询,这里建议初学者尤其是对系统原理不清楚的,尽量少用快捷键。
下面截图说明用户的keybindings.json文件的位置在哪里可以找到。
有两个方法打开keybindings.json 。可以用快捷键 (Ctrl+Shift+P) 选择Preferences: Open Keyboard Shortcuts (JSON)打开;或者File->Preferences->Keyboard shortcuts再点下图所示的图标打开。(此截图来自对应官网)
// Place your key bindings in this file to override the defaults
[
{
"key": "ctrl+f6",
"command": "workbench.action.tasks.runTask",
"args": "task-clean"
} ,
{
"key": "f6",
"command": "workbench.action.tasks.runTask",
"args": "task-build"
},
//for jlink
{
"key": "ctrl+f7",
"command": "workbench.action.tasks.runTask",
"args": "task-jerase"
},
{
"key": "f7",
"command": "workbench.action.tasks.runTask",
"args": "task-jflash"
},
//for st-util
{
"key": "ctrl+f8",
"command": "workbench.action.tasks.runTask",
"args": "task-sterase"
},
{
"key": "f8",
"command": "workbench.action.tasks.runTask",
"args": "task-stflash"
}
]
参照上面的示例文件,这里是把前面的tasks.json里面的任务给予对应的快捷键定义,简单的分类就是用f功能键表示创建操作,ctrl+f功能键表示对应的销毁操作。有了这个文件之后,就实现和keil一样的,F7一键编译
f6 = 编译工程
ctrl+f6 = 清除工程
f7 = jlink下载
ctrl+f7 = jlink擦除
f8 = stlink下载
ctrl+f8 = stlink擦除
读者最好了解在线调试的原理,否则可能对这里用到的各个文件或依赖感到很困惑。vscode是通过配置launch.json和settings.json,实现对其debug功能的配置。主要配置的对象是cortex-debug插件和下载器。
调试的原理简要说明一下。debug原理早在最早的GNU时代就确立了,现在仍然在使用GNU框架(其实好像就没有听说过GNU之外的)。简要的知识如下4点。
GDB: GDB是GNU中的调试框架设计,定义了调试的功能组件,如单步,断点,寄存器查看等功能,这也是为啥GDB框架下的调试界面基本相同(这就是‘标准’的力量)。
vscode是一个文件编辑器,也是一个容器,执行各种插件或调用外部应用如make等
Cortex-Debug是你在vscode下调试cortex核芯片的GDB,
GDB之下是接口,如JTAG协议接口,这通过jlink gdb server实现,其实就是给IDE的通用GDB调用接口;再之下就是对应的协议接口及硬件,如jlink及stlink,通过它们连接到对应的目标板。大概的访问路径是 vscode->cortex debug->jlink gdb server->jlink|swd |usb-> target chip。分层分得是很好很合理,就是层数有点多了,初学者很容易见此放弃。
参考: Home · Marus/cortex-debug Wiki (github.com) 和 Cortex Debug Under the hood · Marus/cortex-debug Wiki (github.com)
按上面的原理,如果你使用stlink,需要告诉vscode一些信息,如gdb在哪里,stlink的gdb server在哪里,其他的信息如stlink的接口等因为都在stlink里集成了,所以不需要额外告知。下面截图中指示3个执行文件的路径,随便放在哪里都可以,但是要确认路径正确,不然肯定会报错的。第一行是gdb地址,第二三行是jlink和stlink对应的gdb server的地址,本章节例子中可以使用jlink或stlink进行调试。
trouble shooting: 注意如果使用jlink,注意对应的gdb server是以‘CL’结尾的,表示是给命令行(即vscode shell)调用的程序。否则的话会报如下截图的错,一直显示“cortex-gdb无法连接到jlink的gdb server”。
在插件的主页可以看一下了它的功能与参数设置 ,这些settings的参数定义在Extensions边栏(按CTRL+SHIFT+X)找到,在Cortex-Debug这里虽然有46个参数,但是简单浏览下都是几大调试器的(jlink, openocd, pyocd, stlink, etc.)支持设计,重复的很多,而且主要是路径设置。参考如下
>>参数使用说明 cortex-debug/debug_attributes.md at master · Marus/cortex-debug · GitHub
更多信息可参考:
1- 介绍 Configure launch.json for C/C++ debugging in Visual Studio Code
2- 详细配置说明 Debugging in Visual Studio Code
launch.json是用于配置vscode中的debugger的,debugger功能是vscode重要功能模块。如果没有launch.json的话,首次需要创建,因为它是工程相关的,所以在.vscode目录下。创建可以手动创建,也可以点下图中所示的链接创建。简单对launch.json分析如下。
// Configure debug launch settings
// Feel free to copy these and modify them for your debugger and MCU
{
"version": "0.2.0",
"projectName": "MAY12",
"configurations": [
{
"name": "JLink launch",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}/build/may12.elf",
"request": "launch",
"type": "cortex-debug",
"servertype": "jlink",
"device": "STM32F429ZI",
"interface": "swd",
"runToMain": true, // else it starts at reset handler - not interested
"preLaunchTask": "task-build", // configured in tasks.json
"svdFile": "", // Include svd to watch device peripherals
"swoConfig":
{
"enabled": true,
"cpuFrequency": 168000000,
"swoFrequency": 10000000,
"source": "probe",
"decoders":
[
{
"label": "ITM port 0 output",
"type": "console",
"port": 0,
"showOnStartup": true,
"encoding": "ascii"
}
]
}
},
{
"name": "JLink attach",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}/build/may12.elf",
"request": "attach",
"type": "cortex-debug",
"servertype": "jlink",
"device": "STM32F429ZI",
"interface": "swd",
"runToEntryPoint": "main", // else it starts at reset handler - not interested
"preLaunchTask": "task-build", // configured in tasks.json
"svdFile": "", // Include svd to watch device peripherals
"swoConfig":
{
"enabled": true,
"cpuFrequency": 160000000,
"swoFrequency": 4000000,
"source": "probe",
"decoders":
[
{
"label": "ITM port 0 output",
"type": "console",
"port": 0,
"showOnStartup": true,
"encoding": "ascii"
}
]
}
},
{
"name": "STlink launch",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}/build/may12.elf",
"request": "launch",
"type": "cortex-debug",
"servertype": "stutil",
"device": "STM32F429ZI",
"interface": "swd",
"runToMain": true, // else it starts at reset handler - not interested
"preLaunchTask": "task-build", // configured in tasks.json
"svdFile": "", // Include svd to watch device peripherals
"swoConfig": {} // currently (v1.7.0) not supported
},
{
"name": "STlink attach",
"cwd": "${workspaceRoot}",
"executable": "${workspaceRoot}/build/may12.elf",
"request": "attach",
"type": "cortex-debug",
"servertype": "stutil",
"device": "STM32F429ZI",
"interface": "swd",
"runToEntryPoint": "main", // else it starts at reset handler - not interested
"preLaunchTask": "task-build", // configured in tasks.json
"svdFile": "", // Include svd to watch device peripherals
"swoConfig": {} // currently (v1.7.0) not supported
},
]
}
和stm32调试有关的内容有很多,但是迅速跑起来的话,东西并不多,我们以及使用stlink为例说明一下,stlink的比较短。下面12个配置项中,有的是关于vscode的,有的是关于cortex-debug的。
name = 就是显示在启动调试里的配置方案的名称,因为我们这里提供了4个方案,分别是jlink两个,stlink两个
cwd = 当前目录,搜索其他文件的起点位置
excuteable = .elf文件,有变量名称表和完整程序信息,内容包含.map, .bin , .ld文件。
request = 调试启动方式,是launch 还是 attach。attatch:强行进入调试,不下载,你自己确认vscode里界面的代码和目标板里的代码一样,不影响程序运行;launch: 重新下载,全新开始调试,确保.elf文件与目标板里是相同的,目标芯片被复位。
type = 表示是为哪个gdb配置的,这里肯定是用cortex-debug,我们用的是这个插件
servertype = gdb服务器名称,这里是用的stutil
device = 芯片详细名称,
interface = 所用的接口
runtoEntryPoing = 是否是从main开始,还是从复位开始,一般是从main开始,除非调试中断与操作系统
preLaunchTask = 启动vscode的调试前调用的命令,这里执行了build命令确保.elf文件是和代码完全一致的
svdFile = 芯片外设寄存器配置文件,如果要显示对应的如串口或CAN口寄存器,需要提供文件目录
swoConfig = jlink才有,配置swo的时钟频率的,stlink暂时没有
上面的配置准备完毕后就可以运行,建议先测试stlink,虽然慢,但是不复杂不容易出错,jlink可能会麻烦一些。
自动的会在绿三角启动按钮旁边显示已经配置好的debugger方案,点绿色按钮启动。最终调试界面如本章节开始的所示。vscode提供的调试按钮如下图所示,这是标准的gdb的调试‘配方’,甚至对应的快捷键在各个软件如KEIL中都是完全一样的。
到此通过配置launch.json和settings.json,实现对vscode的配置,最终调试界面如下,截图中使用的是'JLink launch'的配置
note:(在jlink下,可以在调试的同时看到swo的输出,而stlink并不支持,这算是jlink的一个优势,当然也可以麻烦一点搞一个串口跳过对swo的依赖)
总结一下,使用vscode进行stm32的完全开发,是一个系统工程。在前面博文的基础上,在vscode上实现了stm32的自定义菜单下载和一键下载,第二个重点是实现stm32的在线调试,支持jlink和stlink两种方式。主要的配置文件是launch.json, settings.json, tasks.json三个项目相关文件,还有keybindings.json文件。至此,已经实现vscode对keil/iar等IDE的替换,从原理上,GNU框架(或叫‘配方’更好)确实是一个非常好的设计,回看keil/iar等IDE,它们也是很忠实遵循GNU配方的。
note: 后续博文继续讨论关于OpenOCD和platformIO的使用。
note2: 一直没讨论c_cpp_properties.json,是因为如果可以完全保证工程完整的话,可以不需要c/c++插件的辅助,而且它与编译、下载、调试无关。在后续博文中讨论这个json文件。
参考:
1-Debugging STM32 in VSCODE with stlink and jlink | VIDEO 45
2-jlink swo用法及示例代码 J-Link SWO Viewer (segger.com)