VSCode ARM CortexM 开发: http://coffeelatte.vip.cpolar.top/post/software/applications/vscode/vscode_arm_cortexm_开发/
文章目录
- VSCode ARM CortexM 开发: <http://coffeelatte.vip.cpolar.top/post/software/applications/vscode/vscode_arm_cortexm_%E5%BC%80%E5%8F%91/>
- 1. Embedded IDE
- 1.1. 安装工具链
- 1.2. 项目配置
- 1.3. 编译和下载
- 2. 调试
- 3. 国产芯片及 CMSIS-DAP 调试器的支持
- 3.1. PyOCD 的安装
- 3.2. 关于 PyOCD 的扩展说明
- 3.3 PyOCD 常用命令
- 4. 常见问题解决
- 4.1. GCC 链接错误 引用未定义函数 _read _write _sbrk
VSCode 的嵌入式开发插件具备了相当多的功能,这里主要使用 Embedded IDE,这是一个支持 MCU 开发的工具,但不具备调试功能,为了调试 ARM Cortex-M MCUs,可以配合安装 Cortex-Debug 插件。这两个插件直接在扩展商店进行搜索安装即可,下面主要介绍使用方法。
1. Embedded IDE
Embedded IDE 集成了 MCU 项目创建,固件和工具下载等功能。安装完毕后在 VSCode 图标面板中会出现 EIDE 图标,EIDE 即 Embedded IDE 的缩写。
点击 EIDE 图标,将出现“New Project”、“Open Project”、“Import Project”项目按钮,以及“Configure Toolchain”、“Setup Utility Tools”、“Open plug-in Settings”选项菜单。
“New Project” 可用于创建新 MCU 工程,“Import Project” 可以将 Keil、IAR 或 Eclipse 类 IDE(如 STM32Cube IDE) 工程导入到 EIDE 环境中。“New Project” 和 “Import Project” 都有很好的引导界面,使用起来很方便。
EIDE 会跟随 VSCode 的语言配置展示为英文或中文菜单,如果没有自动跟随,可以点击 “Open plug-in Settings” 后,在配置中切换 EIDE 界面语言。
这里我们假设已经创建或导入了一个 ARM Cortex M 工程,接下来看一下工程配置及开发工具链的安装。
1.1. 安装工具链
在 EIDE 的“Builder Configurations”和“Flasher Configurations”下可以看到默认使用了 GCC 编译器和 JLink 调试器。如果你的系统中已经直接或间接的安装了这两个工具,那可以到“Open plug-in Settings”下配置好相关工具的路径。
如果没有安装这两个工具,则可以点击“Setup Utility Tools”进行安装:
EDID 不支持工具卸载功能,实际上,这些工具默认下载并解压在 “ u s e r R o o t / . e i d e / t o o l s ”目录下(“ {userRoot}/.eide/tools” 目录下(“ userRoot/.eide/tools”目录下(“{userRoot}”即当前的用户目录)。如果需要卸载,则直接到该目录下删除对应工具即可。
EDID 也支持使用 AC5、AC6、IAR 等编译器,以及 STLink、pyOCD 等下载器,可以点击“Builder Configurations”和“Flasher Configurations”后面的切换按钮进行更换。
注:使用“Setup Utility Tools”安装的 GCC 包在使用时会造成 FreeRTOS 堆栈大很多(TCB 中的 struct _reent xNewLib_reent 结构有问题,runtime 的问题),解决办法是使用 STM32Cube IDE 中的 GCC 进行替换(点此下载)。
1.2. 项目配置
有了编译器和调试器工具,就可以编译并下载程序。但是,在此之前需要先进行项目配置,除了配置编译器和下载器以外,需要配置“Chip Support Package”、“Builder Configurations”、“Flasher Configurations”和“Project Attributes”。
如果某项目无法咱开,则点击项目后边的“+”号进行添加即可:
先添加一个“Chip Support Package”,“From Repo”会从网络上自动下载相关 pack 包,“From Disk”则可以选择硬盘上一个已经下载好的 pack 包。相关资源可能在 github 上,所以网络安装需要些特殊工具支持。如果失败,可以多尝试几次。
继续点击加号添完成“Chip Support Package”和“Builder Configurations”、“Flasher Configurations”的添加。配置好“Chip Support Package”后会自动完成 Svd 的配置,有了 Svd 才可以调试外设。
GCC 需要配置“Linker Script File Path”,这个是 LD 连接文件,该文件可以来自 STM32 Cube,或者示例参考工程。如果是 Keil 的 ACx 编译器,则可以使用默认连接脚本(将“USe Custom Linker Script File”置为 false)。IAR 编译器需要配置 icf 格式的连接文件。
“Flasher Configurations”以 OpenOCD 为例,需要配置“Chip Config”和“Interface Config”,所谓“Chip Config”即指芯片的配置,“Interface Config” 指使用哪种调试器,这里使用的是 DAP 调试器,如果是 stlink 或 jlink 只要按需修改即可。
如果是导入的项目,不添加“Chip Support Package”也可以正常编译和下载、调试,只是调试时不支持查看外设寄存器。
“Project Attributes” 中可以配置 Include Path、Library Path 和 全局宏等。
其他项目一般会自动配置,如有差异则按需变更即可。
1.3. 编译和下载
安装好依赖工具并做好项目配置后就可以编译并下载程序,点击项目右侧的按钮即可:
2. 调试
Embedded IDE 不具备调试功能,需要 Cortex-Debug 扩展插件。Cortex-Debug 可以与 EIDE 进行很好的配合,一般不需要进行额外的配置。当变更 EIDE 的“Flasher”后即会自动生成 VSCode 调试脚本。然后按 F5 进行调试即可。
Cortex-Debug 会自动安装 RTOS Views 以及其他一些依赖插件,如果提示自动安装,点击允许即可。
RTOS Views 支持 RTOS 调试功能,比如查看系统中的 Task 等。
3. 国产芯片及 CMSIS-DAP 调试器的支持
通常国产芯片会提供 Keil 的 pack 文件,以及 JTAG 扩展支持该芯片的方法。因此如果使用 Keil+DAP 或者使用 EIDE+JTAG 均可下载和调试。但使用 EIDE+DAP 就需要变通一下,因为 EIDE 所支持的调试器中并没有 Keil 中的 CMSIS-DAP 选项,只有 OpenOCD 和 PyOCD。而想让 OpenOCD 支持某款芯片就要编写该芯片的 Flash 算法,这个方法有些复杂。
而 PyOCD 则可以直接使用 Keil 的 pack 文件,通过这种方式使 EIDE 支持国产芯片更加普遍适用,并且易于实现。同时在 EIDE 的“Chip Support Package”中也可以通过文件加载 pack 文件来获取国产芯片的型号支持。
3.1. PyOCD 的安装
既然是 Py 开头的,那一定使需要用到 Python,Windows 下从官网下载好 Python3,或者 Linux 下使用命令进行安装后(需要安装 pip)后,通过 pip 命令安装 PyOCD 即可:
# 配置 pip 使用阿里云镜像.
pip config set global.index-url http://mirrors.aliyun.com/pypi/simple/
pip config set global.trusted-host mirrors.aliyun.com
pip config set global.timeout 120
# 安装 PyOCD.
pip install pyocd
需要注意的是,Windows 下不要使用 MSYS2 这类环境下的 python 和 pip,容易安装失败。
之后使用
pyocd --version
验证安装是否成功。
然后将 EIDE 中的“Flasher Configurationgs” 配置为 pyOCD。点击“Flasher Configurationgs->Other Options”,将打开“debug.pyocd.yaml”文件,向该文件添加:
pack:
- /Abs/Path/To/Company.Family_DFP.Version.pack
之后重启 Vscode,便可在 EIDE 的 “Flasher Configurationgs->Target Name”中选择 pack 文件中的芯片,并进行调试。
PyOCD 能够自动识别 CMSIS-DAP 等多种调试器,不需要再 EDID 中设置调试器种类。
3.2. 关于 PyOCD 的扩展说明
以上使用 pack 包的方法是基于 PyOCD 对 pack 包的手动管理。PyOCD 支持两种手动管理 pack 包的方式,官方原文说明如下:
Manual pack usage
If you prefer to manually manage packs, or if the managed pack system cannot access online packs from your network, you can download them yourself from the official CMSIS-Pack list. The downloaded pack files can be stored wherever you like. Typically you would group them in a single common directory. Another good option is to place the pack file used with a project in a project-relative location.
There are two ways to use a manually downloaded pack.
The simplest option is to pass the --pack option to the pyocd tool, specifying the path to the .pack file. PyOCD does not cache any information about packs used this way, so this argument must be passed for every invocation in addition to the other arguments. For instance, to run the GDB server, you might execute pyocd gdbserver --pack=Keil.STM32L4xx_DFP.2.2.0.pack. Note that you can pass multiple --pack arguments to pyOCD, which might be useful in a scripted execution of pyOCD.
For a more permanent solution, use a pyocd.yaml configuration file. In the config file, set the pack session option to either a single .pack file path or a list of paths. Now when you run the pyocd tool, it will automatically pick up the pack file(s) to use.
Here is an example config file that lists two packs.
pack:
- /Users/admin/CMSIS-Packs/Keil.STM32L0xx_DFP.2.0.0.pack
- /Users/admin/CMSIS-Packs/NXP.MKV58F24_DFP.11.0.0.pack
To see the targets provided by a .pack file, run pyocd list --targets and pass the approprate --pack option or use a config file, as described above.
Note: .pack files are simply zip archives with a different extension. To examine the contents of a pack, change the extension to .zip and extract.
Note: PyOCD can work with expanded packs just like zipped .pack files. Pass the path to the root directory of the pack using the --pack argument, as above. This is very useful for cases such as development or debugging of a pack, or for working with other CMSIS-Pack managers that store packs in decompressed form.
PyOCD 的 yam 配置文件说明如下:
Config file
pyOCD supports a YAML configuration file that lets you set session options that either apply to all probes or to a single probe, based on the probe’s unique ID.
The easiest way to use a config file is to place a pyocd.yaml file in the project directory. An alternate .yml extension and optional dot prefix on the config file name are allowed. Alternatively, you can use the --config command line option, for instance --config=myconfig.yaml. Finally, you can set the config_file option. If there is a need to prevent reading a config file, use the --no-config argument.
The top level of the YAML file is a dictionary. The keys in the top-level dictionary must be names of session options, or the key probes. Session options are set to the value corresponding to the dictionary entry. Unrecognized option names are ignored.
EIDE 中的 debug.pyocd.yaml 属于项目级的配置文件。
PyOCD 安装了 CMSIS Pack Manager,其位置在用户目录下
C:\Users\<User Name>\AppData\Local\cmsis-pack-manager\cmsis-pack-manager
3.3 PyOCD 常用命令
pyocd pack find <part keyword>
pyocd pack install <part number>
4. 常见问题解决
4.1. GCC 链接错误 引用未定义函数 _read _write _sbrk
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x10): undefined reference to `_write'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0xe): undefined reference to `_fstat'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x10): undefined reference to `_lseek'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x10): undefined reference to `_read'
在 Builder Configurations -> Builder Options 中进行修改。
选择 Global Options 或 Linker,添加或删除 “–specs=nosys.spece”(文章:ARM GCC 链接错误 引用未定义函数 _read _write _sbrk 解决和重定向 中说要添加该参数,但我实际项目中已经添加了该参数仍然报出了这个警告,删除后警告消失)。