前言:Keil开发者の困境
虽然keil的功能很嵌入式,但是想必用keil搞开发的老哥们苦keil久矣:
– 上古的软件界面
– 奇慢无比的包管理器
– 莫名其妙的bug(退出调试卡死、寄存器列表变空、寄存器值不更新、随机失效的断点…)

– 没有跳转功能(Browse Infomation你提都别提,对于大型项目,等他编译出来,人都走了有一会儿了)
– 神秘的错误代码
– 智能提示时好时坏
– 没有代码重构功能
– 生态封闭,不支持跨平台
– 没有代码管理
– 闭源且授权费用高(大家应该没几个人不是学习版吧)
不过该说不说,Keil的集成度,对新手的友好程度还是比较好的,所以本教程主要面向有一定开发经验,不想再受苦且愿意脱离keil的程序猿们,当然,这种开发方法其实实操起来并不复杂,且最重要的是兼容原来的Keil老工程,可以说还是相当简单的。
一.准备工作
1.软件条件
– VS Code
– STM32CubeMX(非必须,我个人喜欢用这个直接生成代码)
2.硬件条件
– 一块已经验证过硬件的板子(请使用keil工程编译烧录,以确定这块板子的硬件以及调试器都是好使的)
3.安装VS Code插件
下面我贴出我安装的插件列表,请各位直接抄答案:
– C/C++:该插件提供了C/C++语言支持和跳转以及一些Debug特性

– Chinese简体中文:这没啥说的吧….

– Cortex-Debug:提供对ARM-CM内核的调试功能

– EIDE:主要就是依靠这个插件提供对STM32的开发环境,其实不仅仅是32,他支持的芯片很多,比如:8051/AVR/STM8/Cortex-M/MIPS/RISC-V

好的,我们所有的准备工作就完毕了,接下来我将从工程生成、导入、编译、烧录到最后的调试,逐步讲解开发方法。
二.CubeMX工程生成
首先打开STM32CubeMX生成工程(本教程针对的重点不在这,请不熟悉CubeMX生成工程的同学,参考这个链接:《【STM32】HAL库 STM32CubeMX系列学习教程》,老鸟和有Keil工程的直接跳过这步就可以《【STM32】HAL库 STM32CubeMX系列学习教程》,其中的步骤和生成Keil工程没有区别):
1.选择芯片(所有的配置请根据自己的硬件条件选择,不要生拌樱桃)


2.MPU设置(不是H7的同学直接跳过这步)

3.GPIO设置:因为本工程只是一个演示工程,所以只初始化了一个LED灯

4.RCC设置:

5.HAL时基设置:

6.串口配置:

7.时钟树配置:两个红框选择完之后,在绿框位置输入480然后按下回车自动设置时钟树

8.工程设置:

9.代码生成设置:

10.生成工程:生成之后直接关闭就行了

三.生成EIDE工程
EIDE有官方的入门教程,本教程也是基于官方教程编写,如果哪里有疏漏或者不明白的地方请参考:
– 官方教程
– 官方论坛
1.安装完上述插件之后重新打开VS Code:
– 点击EIDE的图标,然后选择导入项目:

– 选择MDK类型工程

– 选择ARM类型产品

– 选择Keil的工程文件

– 在右下角弹出的选择框中选择否,然后给EIDE新建一个文件夹


– 点击继续切换工作区


– 打开工作区文件,在此处添加代码:

"folders": [
{
"path": "."
},
{
"name": "Code",
"path": ".."
}
]
– 这段代码在folders中添加了一项,目的是让智能提示和跳转功能(C/C++插件的IntelliSense功能)能够识别到咱们的项目工程文件,其中的内容和咱们刚才为EIDE创建的文件夹的位置有关,我刚才把EIDE文件夹创建到项目根文件夹下面,那么其中path的内容就应该是“..”,这代表将根文件夹(EIDE文件夹的上级目录)添加到工作区,然后给根文件夹起一个名字,我这里就叫做“Code”,大家想叫啥都可以
添加完的效果如下图,可以看到和文件管理器中的结构是相同的:


– 然后按Ctrl+,打开VS Code设置,搜索elf:将下面框选的设置勾选,这是为了让编译器在编译结束后将axf文件转换成elf文件供咱们调试使用。

这样一个简单的EIDE工程就生成完了。
2.现在简单给大家介绍一下EIDE的工程项目文件(官方描述)(酌情跳过):
.eide: 此文件夹包含 eide 项目信息、构建器选项等配置
.eide/eide.json: 此文件用于描述你的项目
<workspase name>.code-workspace: 该文件是一个 vscode 工作空间文件VSCode 将把该工作区的设置保存至该文件
您可以在文件资源管理器中双击该文件以直接打开 eide 项目
上面的这些文件是EIDE工程项目必备的,所以除非你知道自己在干嘛,要不然就别动他,其实你完全可以无视这些文件,因为一般我们对工程的修改都不在这里进行。
注意:EIDE对Keil的工程有一些兼容性问题,只有符合下面要求的工程才能够导入(官方描述):
Keil 版本限制:
只支持 v5 !!!
RTE 组件:
因为在 UVPROJX 项目文件中 MDK 的 RTE 组件的描述更复杂,Eide 不支持引入这些 RTE 组件,如果您的项目有 RTE 组件,建议不要导入它们 (只有CMSIS组件的除外(笔者补充:就是下面图片中只有最上面的CMSIS且左面没有展开的加号的是可以的))
那些有 RTE 组件的有以下绿色图标:
强制导入
如果你强行导入一个带有 RTE 组件的 Keil 项目,你必须手动添加缺失的
源文件,包含目录到项目 !
我个人认为上面的限制其实大部分工程都能满足,Keil版本就不说了,开发STM32用的都是V5版本的。
另外关于RTE组件:这个RTE个人感觉用的人不多,我看网上除了硬汉哥比较喜欢使用,其他的资料比较少。如果是新工程的话,既然用CubeMX生成代码了,也不会用到RTE了。另外如果你是之前已经用Keil添加过RTE组件的老项目,也可以通过手动添加源代码的方式实现。
3.简单介绍一下EIDE插件的各个功能模块(酌情跳过):
我们导入完工程之后,点击EIDE的插件图标会发现有六个功能模块,分别是:项目资源、芯片支持包、构建配置、烧录配置、C/C++属性以及项目设置(由于篇幅,我在这里只能简单介绍,如果有疏漏请参考官方教程)

项目资源:
这其中包含了咱们项目源码、源文件夹和输出文件。
如果想要添加文件或者文件夹可以将鼠标悬停(或者右键)在项目资源这一栏,然后点击右面的图标进行添加:

如果想对已经在项目中的文件(夹)做添加或修改,可以在对应的目标上右键。另外值得说的是,将鼠标悬停在项目文件或者文件夹上可以发现右面有两个图标,一个是刷新,另一个是排除:



排除和移除不同,排除是在不改变项目文件结构和内容的情况下,让目标不参与编译,而移除是直接将该文件从项目中删除(但是保留本地磁盘文件)。
芯片支持包
这里的芯片支持包和大家在Keil包管理器中安装的那个DFP包是一个东西,他对咱们咱们工程有什么影响呢,EIDE官方是这样说的:
当您安装了 cmsis-pack 并为您的项目选择了 mcu 具体型号后,插件将得知你所使用的芯片型号和规格,以下功能将得到优化:
编译配置:插件将自动根据芯片类型选择CPU Type
烧录配置:对于 JLink 等烧录器,插件可以自动完成型号的选择,以及烧录算法文件的安装
调试配置:插件可以根据芯片型号自动生成更完整的调试配置(用于Cortex-debug)(包括:芯片型号,SVD 路径等)
RAM/ROM Layout:将根据已选择的芯片信息,自动填写 RAM/ROM 地址 和 大小
外设组件:允许安装 cmsis-pack 内附带的源码组件不是必需的
这个功能不是必需的,即使您没有安装任何芯片支持包,插件也能完全正常地工作
也就是说,如果不安装芯片支持包,程序也是可以正常烧录和下载的,只不过有很多东西需要咱们自己去设置,所以我建议大家都去安装这个,主打一个省事(我后面会教大家怎么去安装),而且最重要的一点,不像Keil的包下载经常会失败,他这个下载安装速度是非常快的。
构建配置
构建配置中有五个子项:其中CPU类型和硬件浮点选项只要安装了芯片支持包是自动给你配置的。

第三项:是否使用自定义的sct文件(链接文件,Keil叫分散加载文件),这个完全就看自己的需求了,如果从没接触过的同学就保持默认。
第四项:RAM/Flash布局:这个就是和Keil中的设置是一样的

第五项:构建器选项:这个就是Keil魔术棒设置中的部分内容,相信有Keil开发经验的同学看一眼就知道咋回事了

烧录配置
这部分就是用来配置烧录器的一般来说保持默认就可以,如果需要修改的话,每个子项目表达的意思也很清楚,这里就不赘述了,如果有不明白的地方或者特殊操作请参考官方教程。
C/C++属性
这部分包含三个子项:分别是:包含目录、库搜索目录以及预处理宏定义

·包含目录 就是头文件的包含目录,也就是Keil中的那个头文件路径。
·库搜索目录 只适用于GCC编译器(Keil用的是ARMCC),所以这一项不用对咱们来说没用,如果说你想添加库文件,那么直接添加 .lib, .obj 文件到项目就可以了。
·预处理宏定义 这个配置就是Keil中的全局预处理器宏定义,不过需要注意的是:
这个配置仅为 C/C++ 源文件 指定宏定义,如果你要为 asm 文件指定宏定义,请前往构建器配置->汇编器中添加
项目设置

· 项目名称:
在构建器中
它用于在生成输出文件时确定文件名 (比如:
.elf,.hex,.bin…).它是变量
${ProjectName}的值
·输出目录名:
这个目录用于存放在编译过程中产生的中间文件,也包括咱们烧录和调试需要的.elf、 .hex、 .bin 等文件
这个文件夹不在项目资源中,他在这(磁盘中是在给EIDE新建的那个文件夹中):

·环境变量:
这个环境变量指的是EIDE项目使用的环境变量,一般来说用不上,以下是官方的介绍:
我们支持在项目中添加一些环境变量
这些变量可用于:
源文件路径
编译器参数
构建流程(进程的环境变量)
烧录器命令
特殊的 EIDE 变量
COMPILER_CMD_PREFIX: 值类型string此变量用于向编译器传递一些固定参数
因为有一些编译器需要
许可证参数和激活码参数
MCU_RAM_SIZE: 值类型number, hex number此变量用于打印内存使用情况,计算百分比
必须和
MCU_ROM_SIZE同时使用
MCU_ROM_SIZE: 值类型number, hex number此变量用于打印内存使用情况,计算百分比
必须和
MCU_RAM_SIZE同时使用
EIDE_BUILD_ORDER: 值类型number中用于在 多项目工作区 中确定项目构建优先级
四.安装实用工具
想要EIDE真的为我们所用,需要给他提供一些厨具,点击操作界面中的安装实用工具(本教程是基于stlink进行,使用其他调试器的同学可以参考,大体方法都是一样的,只不过需要按照你们使用的调试器安装不同的工具并且设置对应的配置):

然后安装我下面截图中框住的工具(你可以都安完了再重启EIDE):

Cppcheck(可以不安):一个静态的C/C++代码检查工具,它可以检测编译器通常无法检测到的错误类型。
GNU Arm Embedded Toolchain:这是GCC嵌入式工具链,我们主要是用他的GDB工具来进行调试,并不参与编译
OpenOCD:一个开源的片上调试器,旨在提供针对嵌入式设备的调试、系统编程和边界扫描功能。我们主要是用它搭配上面的GDB来进行调试。(对于GDB OpenOCD Stlink之间关系有疑惑的同学请参考《嵌入式软件的调试工具》)
STM32 Cube Programmer CLI:这个是STM32 Cube Programmer的命令行程序,用于烧录程序(如果使用Jlink不用下)
Arm C Compiler V5.06u7:这个就是ARMCC编译器,也就是Keil使用的编译器,这里直接提供的是学习版(妈妈再也不用担心我的版权问题)
以上的工具都安装完毕之后点击右下角的OK重启EIDE(或者手动重启VS Code)(这些工具的安装位置在:C:Users你的用户名.eide ools):

五.编译项目
0.安装芯片支持包:
点击芯片支持包右侧的加号,EIDE提供了两种安装方式:


你可以选择从仓库下载安装或者从磁盘安装:
从仓库安装:
我们为 eide 缓存了一些 修剪过的 cmsis 包
如果您使用这种方式,eide 将从上面的存储库中提取所有可用的包,并提供一个列表供您选择
为什么修剪这些包
有些 cmsis 包的尺寸非常大,这会影响项目的大小
因此,我们可以修剪它们并删除不使用的内容,以减少磁盘使用量
从磁盘安装:(如果大家不想下载支持包且以前Keil下载过这些包,可以通过这种方向指向包所在的地址)
你需要从网站上下载这些包(
.pack),并在 eide 弹出的窗口中选择你要安装的包这里有些官方的下载站点:
MDK5 Software Packs: Arm Keil | Devices
Arm Official Site: Arm Keil | CMSIS Packs
这里为了方便,直接从仓库下载包:
点击从仓库安装之后输入你的芯片系列,按下回车等待下载完成即可。

然后你在芯片支持包这项就可以看到下载完的DFP包了,点击右侧加号添加我们的芯片型号:

现在可以看到,现在我们的芯片支持包已经安装完了:

没有通过CubeMX生成工程的同学可以通过在外设组件中勾选添加自己需要的外设驱动:

调整工作区设置:
因为我们既用CubeMX生成工程又加入了芯片支持包,这就会导致有些标准的函数会有两份(一份存在于工程源码中,另一份存在于芯片支持包带的源码中),这在使用VS Code的Ctrl点击函数名跳转的功能(IntelliSense)时出现两个结果,这时候我们需要把芯片支持包的源码从这个功能中屏蔽掉:

在我红框框选的地方加入代码,“C_Cpp.files.exclude” 方式配置了需要IntelliSense忽略的文件目录,我们把芯片支持包的目录添加进去然后你可以进入任何一个.c文件选择在右下角点击重新分析工作区,也可以重启VS Code:

另一种我上面图片注释中的方法也可以,这种方法是直接把.pack目录从VS Code的资源管理器中排除,排除之后,在左侧资源管理器就不再显示.pack的内容了
1.编译工程:
如果上面的步骤都成功通过了,接下来点击项目名称右侧的编译(或者按F7)就可以进行编译了:

可以看到,EIDE除了显示了编译之后的代码大小,还给出了内存和Flash的使用情况,甚至根据sct文件显示出了每个内存区的使用占比(就问苦苦查map文件的同学,这不比Keil香?)

六.烧录工程
0.在烧录配置右侧点击双向箭头图标切换使用的调试器:

这里大家按照自己的调试器选择:

然后按照自己的需求更改烧录配置(一般来说不需要修改,我这里是默认设置):

1.烧录工程:
点击点击项目名称右侧的烧录图标烧录工程:

如果中断中打印出类似以下内容则代表烧录成功:

如果烧录之后程序没有运行,除了排查代码错误(可以通过Keil烧录验证)还需要检查烧录配置中的烧录后启动程序是不是True。
七.调试工程
EIDE的调试需要通过CortexDebug插件来完成,不过EIDE可以帮助我们生成调试配置。
1.在项目名称右键,点击生成调试器配置模板,选择对应的调试器,我用的stlink所以选择OpenOCD:

2.在右侧弹出的创建窗口中选择对应的配置:

名称:自己随便起
调试模式:有两种一种是启动,另一种是附加。
启动(launch):停止MCU并复位,从头开始执行(与Keil调试相同)
附加(attach):不复位MCU,将暂停MCU然后介入调试
接口:按照你的调试器选择
目标:按照你的芯片型号选择
配置完毕之后点击新建,发现跳转到了launch.json文件(该文件在 EIDE文件夹.vscode)中,其中的配置EIDE已经帮咱们配置好了,下面给大家介绍一下每一个配置项(其他调试器的配置项也是大同小异,基本不需要做改动),如有遗漏,或需要高级操作,请参考CortexDebug的官方WiKi。

cwd:运行命令的目录
type:调试器类型:咱们用的是cortex-debug
request:请求类型,就是我上面说的启动还是附加
name:这个就是调试配置的名字,也就是刚才按照模板创建调试配置时设置的名字
servertype:服务类型,因为我是stlink所以使用OpenOCD
executable:可执行文件的目录
runToEntryPoint:指定调试器进入的点,大多数情况就是main
configFiles:这个配置文件是OpenOCD的特有配置
·interface:指定OpenOCD使用的调试器接口,大家选择的时候可能会看到有stlink、stlink-v2等,但是只要是stklink就选择stlink.cfg配置文件即可,因为其他的配置文件已经被弃用了,最后指向的都是stlink.cfg文件
这些配置文件在以下路径中
C:Users
ame.eide oolsopenocd_7a1adfbec_mingw32shareopenocdscriptsinterface
·target:指向目标芯片的配置文件
svdFile:指向的是芯片DFP包的svd文件,这个文件帮助调试器显示外设寄存器的值,如果正确添加了芯片支持包并且选定了芯片型号,那么EIDE会帮你自动配置这项
3.启动调试
好的,现在我们就可以启动调试了,你可以按下F5直接启动调试,也可以在VS Code左侧进入运行和调试界面然后点击绿色的播放键启动调试:

如果你和下面截图一样,没有报错,左侧变量也显示了内容,那么恭喜你,你已经成功进入到了调试模式:

接下来我简单介绍一下调试界面以及简单的使用:

1.这个区域用于展示当前函数的一些变量、全局变量、和CPU的寄存器
2.这个区域用于显示监视的变量,你可以在变量上右键点击添加到监视,也可以点击监视这栏右面的加号手动输入表达式。另外有些时候可能需要看16进制的数据,那么你可以点击右侧的 0x 切换16进制和10进制的显示.

3.这个区域用于显示和管理所有的断点,点击对应的条目可以跳转到对应的断点处
4.这个区域用来动态监视变量,这个功能默认是关闭的,需要修改launch.json:

注意:这个 samplesPerSecond(每秒采样率)不要设置的太高,因为VS Code的限制,如果调的太高,会冻结显示对应的窗口,最好是保持默认设置(“samplesPerSecond”: 4)即250ms采样一次

在LiveWatch只能添加全局或静态变量,比如上图,a是一个main函数中的静态变量,加入其中没办法监视,但是b作为一个全局变量就可以,
另外如果你可以在变量后面加 ,h(H) / ,x(X) 来将该变量单独显示成十六进制形式,如第三个变量;还有一些其他用法: ,b(B) 显示成二进制形式、,d(D) 显示成十进制形式、
5.这个区域用来显示外设寄存器的值:你将鼠标悬停在对应的寄存器值上会显示出详细的信息,如下图:

6.这个区域就是用来控制程序的复位、顺序执行、步过、单步、跳出和退出调试。
7.这个区域就是内存查看器,你可以在这添加要查看的内存视图并且可以通过右面的设置按钮重命名,同时也支持一些复制和保存等操作:

同时,在设置中你也可以更改显示的格式,比如按多少个字节显示、是大端还是小端:

8.XRTOS
这个功能主要用于监控RTOS的线程,显示一些线程的基本信息,对于调试跑操作系统的程序还是挺有用处的(同样,其中展示的信息只有在程序暂停或断点的时候才会被刷新):

八.常见问题&使用小技巧
1.没有实时语法错误提示?
把工作区文件中的“settings”中的“C_Cpp.errorSquiggles”项设置成“enabled”

2.每次调试都需要编译-下载-然后F5?
是的,如果说改变源码了的话,是需要每次都编译下载然后启动调试,目前我没发现可以一键解决的方法(如果有大神解决了,欢迎贴出来,我会补充在这~)(在launch.json中添加”preLaunchTask”的方法不行,我试过了)
















暂无评论内容