跳到正文

Wiki

插件使用教程

約 31 分鐘閱讀

本文由簡體中文內容確定性轉換,並受版本化術語表保護。

1.CubeMX安裝FW

點擊Help

選Manage embedded software packages,把STM32F1,F4,H7的第一個最新的固件勾上。

點install

可以不用登錄賬號選do not ask me again

然後等下載和安裝完

下載好就行了。

2.VScode安裝插件

然後打開VScode,在終端輸入下面的命令

code

然後可以配置一個環境單獨給CubeIDE插件使用,避免和默認環境衝突。

alt text

進行一些設置,自己按習慣來,不懂的暫時按我的來也行

alt text

選中STM32

alt text

然後安裝一些插件

找到下面這個STM32CubeIDE for Visual Studio Code插件安裝

alt text

右邊彈這個提示要選擇安裝(要有良好的科學網絡)

alt text

緊接着會進行一些環境的安裝

alt text

也可以再安裝一些其他的插件,比如Codex等插件 這些看你自己啦

alt text

3.OpenOCD使用事項

3.1.選擇debugger和mcu型號

OpenOCD 一般通過 .cfg 配置文件確定:使用什麼調試器 + 連接什麼 MCU

openocd -f interface/调试器.cfg -f target/芯片系列.cfg

第一個參數:看你用什麼調試器

調試器 OpenOCD 配置 説明
ST-Link V2 / V2-1 / V3 "interface/stlink.cfg" STM32 最常見
DAPLink "interface/cmsis-dap.cfg" DAPLink 實現 CMSIS-DAP
CMSIS-DAP "interface/cmsis-dap.cfg" 很多第三方調試器使用
J-Link "interface/jlink.cfg" SEGGER J-Link
FTDI 類 JTAG/SWD "interface/ftdi/xxx.cfg" 根據具體硬件選擇

第二個參數:看 STM32 哪個系列

STM32 系列 常見型號示例 OpenOCD Target
STM32C0 C011、C031、C071 "target/stm32c0x.cfg"
STM32F0 F030、F072 "target/stm32f0x.cfg"
STM32F1 F103C8、F103RC "target/stm32f1x.cfg"
STM32F2 F205、F207 "target/stm32f2x.cfg"
STM32F3 F303、F334 "target/stm32f3x.cfg"
STM32F4 F405、F407、F429、F446 "target/stm32f4x.cfg"
STM32F7 F746、F767 "target/stm32f7x.cfg"
STM32G0 G030、G070、G0B1 "target/stm32g0x.cfg"
STM32G4 G431、G474 "target/stm32g4x.cfg"
STM32H5 H503、H563、H573 "target/stm32h5x.cfg"
STM32H7 H743、H750、H745、H747 "target/stm32h7x.cfg"
STM32H7RS H7R3、H7S3 "target/stm32h7rsx.cfg"
STM32L0 L031、L073 "target/stm32l0.cfg"
STM32L1 L151、L152 "target/stm32l1.cfg"
STM32L4 / L4+ L432、L476、L496、L4R5 "target/stm32l4x.cfg"
STM32L5 L552、L562 "target/stm32l5x.cfg"
STM32N6 N657 等 "target/stm32n6x.cfg"
STM32U0 U031、U073 "target/stm32u0x.cfg"
STM32U3 U385 等 "target/stm32u3x.cfg"
STM32U5 U575、U585、U5A5 "target/stm32u5x.cfg"
STM32WB WB55 等 "target/stm32wbx.cfg"
STM32WBA2 WBA2xx "target/stm32wba2x.cfg"
STM32WBA5 WBA5xx "target/stm32wba5x.cfg"
STM32WBA6 WBA6xx "target/stm32wba6x.cfg"
STM32WL WL55、WLE5 "target/stm32wlx.cfg"
STM32C5 C53、C54、C55、C56、C59、C5A 見下方説明

STM32C5 要特別注意:

現在不要把 C5 寫死成target/stm32c5x.cfg, 原因是 STM32C5 的 OpenOCD 支持非常新。2026 年 7 月才有 stm32c5x.cfg 支持補丁提交到 OpenOCD Gerrit;補丁里的文件名確實就是target/stm32c5x.cfg。 但是現在還沒完全發行到OpenOCD,需要等一段時間。

3.2.測試設備連接

我們用的stm32f103c8和st-link:

所以用

openocd -f interface/stlink.cfg -f target/stm32f1x.cfg

可以插上之後測試一波:

照上圖所示,已經連接成功了。

幾個關鍵日誌分別説明:

Info : STLINK V2J48S7 ...
→ OpenOCD 正常识别 ST-Link。

Info : Target voltage: 3.150483
→ 目标板供电正常,约 3.15 V。

Info : SWD DPIDR 0x1ba01477
→ SWD 通信已经建立。

Info : [stm32f1x.cpu] Cortex-M3 r1p1 processor detected
→ 已经真正识别并连接 MCU 核心。

Info : target has 6 breakpoints, 4 watchpoints
→ Cortex-M3 的硬件断点/数据观察点正常。

Info : Examination succeed
→ Target 初始化成功。

最后:
Info : [stm32f1x.cpu] starting gdb server on 3333
Info : Listening on port 3333 for gdb connections
→ OpenOCD 的 GDB Server 已经正式启动,可以给 VS Code / STM32Cube 调试器连接了。

4.工程創建與測試

4.1.使用CubeMX創建工程

點擊進入單片機挑選的按鈕

搜索對應芯片,並雙擊對應芯片選項。

進行一些配置,以下都是很基礎的東西,你在看這個視頻前肯定都會了

隨便開一個IO用來測試,比如LED的GPIO

FreeRTOS也要配置一下。

本例在用户目錄中實現 StartDefaultTask() 來替換默認任務函數,需要CubeMX生成的同名函數為弱定義。 可以在FreeRTOS的 Tasks and Queues 中,將 defaultTask 的 Code Generation Option 設為 As weak,重新生成後確認該函數帶有 __weak,避免兩個普通定義產生衝突。參考ST社區説明。

這些文件夾也要配置好,最後Toolchain選擇CMake,編譯器選擇GCC(6.14.1及之前沒有選擇編譯器這個選項很正常)

4.2.對工程進行配置與編譯

在工程文件夾打開終端(或者直接在此處打開VScode也行)

alt text

code .

打開VScode後記得切到`STM32·的配置

alt text

選擇這裏的Yes進行配置CMake預設

alt text

一般選Debug即可

alt text

可能談一個很長的對話框,是這個STM32Cube Core提示的,你直接點yes開始下載(這是自動部署各種環境的)

反正右下角是STM32Cube Core提示讓你安裝的,你安就完了,每個版本提示可能不一樣,總之安裝就完了。

等上面的環境部署完畢後,

找個C語言的代碼文件打開,然後右下角會提示安裝一個C/C++插件,這個可以安裝也可以不安裝,他也帶代碼提示,但是他的代碼提示對比自帶的clangd簡直是弱爆了,如果你是新手,你不會設置代碼提示,建議按我下面的操作來,直接別裝這個C/C++插件。

默認用的是clangd代碼提示

你可以測試一下代碼提示,是不是很強。

alt text

編譯的話,圖中的這倆build都可以

alt text

4.3.移植作者tungchiahui的標準C/C++工程模板

用git clone命令克隆倉庫:https://github.com/tungchiahui/STM32HAL_CMake_CPP_Template

git clone https://github.com/tungchiahui/STM32HAL_CMake_CPP_Template.git

把倉庫裏的除了.git以外的東西都複製到我們的STM32工程根目錄。

alt text

模板中的用户代碼按功能模塊組織,每個模塊的 .cpp、.hpp(或 .c、.h)放在同一個文件夾裏。複製後的目錄結構如下:

STM32工程根目录/
├── applications/
│   └── main/
│       ├── cpp_interface.cpp
│       └── cpp_interface.h
├── bsp/
│   └── boards/
│       ├── common/
│       │   └── struct_typedef.h
│       └── delay/
│           ├── bsp_delay.cpp
│           └── bsp_delay.hpp
└── cmake/
    ├── stm32cubemx/            # CubeMX生成的配置
    └── user/
        └── CMakeLists.txt     # 用户代码的配置

cmake/user/CMakeLists.txt 已經把 applications 和 bsp/boards 加入頭文件搜索路徑,所以引用用户頭文件時統一使用“模塊目錄/頭文件名”的寫法:

#include "main/cpp_interface.h"
#include "delay/bsp_delay.hpp"
#include "common/struct_typedef.h"

在這兩個目錄下新增模塊時,沿用這個寫法即可,不需要為每個模塊單獨添加頭文件搜索路徑。

打開CubeMX生成的 Core/Src/main.c,在 USER CODE BEGIN Includes 和 USER CODE END Includes 之間加上:

#include "main/cpp_interface.h"

然後在 main() 的 USER CODE BEGIN 2 和 USER CODE END 2 之間調用 cpp_main(),此時系統時鐘和外設已經初始化完成:

cpp_main();

注意 applications/main/cpp_interface.h 中的 isRTOS 設置:

  • 裸機使用默認值 0,業務代碼可以寫在 cpp_main() 的無限循環中;
  • 使用FreeRTOS時要改成 1,使 cpp_main() 執行完初始化後返回,程序才能繼續創建任務並啓動調度器。
  • 下面沿用前面配置了FreeRTOS的工程,因此先將 isRTOS 改為 1。

然後打開工程根目錄的 CMakeLists.txt,在CubeMX原有的 add_subdirectory(cmake/stm32cubemx) 後面添加 add_subdirectory(cmake/user),引用用户代碼的配置:

# Add STM32CubeMX generated sources
add_subdirectory(cmake/stm32cubemx)

# Add USER generated sources
add_subdirectory(cmake/user)

在同一個頂層 CMakeLists.txt 中,保留原有的C語言標準設置,並在 project() 之前增加C++標準設置(模板的 README-zh_CN.md 中也有説明):

# Setup compiler settings
set(CMAKE_C_STANDARD 11 CACHE STRING "C language standard")
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)

set(CMAKE_CXX_STANDARD 20 CACHE STRING "C++ language standard")
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)

然後在 applications 下新建 led_task 文件夾,把 led_task.cpp 和 led_task.h 都放進去:

applications/
├── main/
│   ├── cpp_interface.cpp
│   └── cpp_interface.h
└── led_task/
    ├── led_task.cpp
    └── led_task.h

applications/led_task/led_task.cpp:

#include "led_task/led_task.h"
#include "cmsis_os.h"
#include "main.h"

int32_t t;

extern "C"
void StartDefaultTask(void *argument)
{
  for(;;)
  {
    HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);
    ++t;
    osDelay(500);
  }
}

applications/led_task/led_task.h:

#ifndef LED_TASK_H
#define LED_TASK_H

#include "main/cpp_interface.h"

#endif

然後打開 cmake/user/CMakeLists.txt,把剛才新建的源文件添加到 Applications_Src 列表中:

set(Applications_Src
    ${CMAKE_CURRENT_SOURCE_DIR}/../../applications/main/cpp_interface.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/../../applications/led_task/led_task.cpp
)

只需要登記新增的 .c、.cpp 文件,.h、.hpp 不需要列為編譯源文件。因為 applications 已經是頭文件搜索根目錄,led_task 模塊也不需要額外添加搜索路徑。

詳細介紹(可以不看):cmake/stm32cubemx/CMakeLists.txt 由CubeMX管理,重新生成代碼時可能更新,因此用户代碼的源文件列表和頭文件搜索路徑統一維護在 cmake/user/CMakeLists.txt 中,頂層 CMakeLists.txt 通過 add_subdirectory(cmake/user) 加載它。這個用户配置文件已經包含在模板裏,前面複製時就已經帶過來了。

大功告成,編譯一次試試。可以看到下圖,那些新加的文件都編譯上了。

alt text

4.4.下載程序到板子

下載之前首先要先配置:

如果你不是stlink和jlink,接着往下看

按下圖的來點擊,你看看你是什麼debugger,你就選哪個。

如果這裏看不到對應設備,遇到權限問題,請查看Linux 下 USB 權限問題。

可以更新下STlink的驅動:

先安裝jlink-gdbserver的bundle,如下圖所示:

alt text

4.4.2.使用openocd服務驅動原生gdb調試器

當你要使用除了ST-Link和J-Link以外的調試器時:

先點調試,讓他生成launch.json:

openOCD接管選STM32Cube: STM32 Launch GDB:

然後選openocd:

過一會兒,肯定會調試失敗,然後提示你open launch.json

然後再點STM32Cube: STM32 Launch GDB:

launch.json內容如下:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "stgdbtarget",
            "request": "launch",
            "name": "STM32Cube: Launch Generic GDB Server",
            "origin": "snippet",
            "cwd": "${workspaceFolder}",
            "preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "program": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
            "gdb": "${command:st-stm32-ide-debug-launch.get-gdb-executable}",
            "deviceName": "${command:st-stm32-ide-debug-launch.get-device-name}",
            "deviceCore": "${command:st-stm32-ide-debug-launch.get-core-name}",
            "deviceTrustzone": "${command:st-stm32-ide-debug-launch.get-trustzone-status}",
            "serverExe": "",
            "serverParameters": [],
            "serverHost": "localhost",
            "serverPort": "",
            "serverCwd": "",
            "runEntry": "main",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "imageOffset": "",
                    "symbolFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "symbolOffset": ""
                }
            ]
        },
        {
            "type": "stgdbtarget",
            "request": "attach",
            "name": "STM32Cube: Launch GDB Client",
            "origin": "snippet",
            "cwd": "${workspaceFolder}",
            "preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "program": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
            "gdb": "${command:st-stm32-ide-debug-launch.get-gdb-executable}",
            "serverHost": "localhost",
            "serverPort": "${command:st-stm32-ide-debug-launch.get-server-port}",
            "runEntry": "main",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "imageOffset": "",
                    "symbolFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "symbolOffset": ""
                }
            ]
        }
    ]
}

我們需要改哪裏呢?

主要是:

  • serverExe : 就填二進制程序名 openocd或者openocd.exe
  • serverParameters :填那兩個openOCD參數,參考 openocd的兩個-f參數
  • serverHost :OpenOCD GDB Server 默認監聽 localhost,一般不用改
  • serverPort :OpenOCD 默認 GDB 端口 為 3333
  • serverCwd : 填serverExe這個二進制程序在哪個目錄底下
  • 添加liveWatch參數(重要)
  1. serverExe:

Linux填openocd Windows填openocd.exe

  1. serverParameters按下面這個格式來:

那倆-f的參數由openocd的兩個-f參數可知:

  • interface/stlink.cfg
  • target/stm32f1x.cfg

但是除了這倆,還需要一些參數:

            "serverParameters": [                
                "-f",
                "interface/stlink.cfg",

                "-c",
                "transport select swd",

                "-f",
                "target/stm32f1x.cfg",

                "-c",
                "$_TARGETNAME configure -gdb-max-connections 2"],

這裏建議按上面這個順序排布參數:先探針 → 再通信協議 → 再 MCU → 最後修改這個 MCU target 的參數

這裏的-c transport select xxx是選協議:

實際調試方式 配置
STM32 常用 SWD transport select swd
JTAG transport select jtag

咱們一般都是swd,所以選transport select swd。

而這個-c $_TARGETNAME configure -gdb-max-connections 2是允許這個 OpenOCD target 同時接受最多 2 個 GDB 客户端連接。

正常調試已經佔了一個:

OpenOCD :3333
    ↑
    └── GDB #1
         普通 Debug

咱們還需要用到Live Watch,所以把參數設置為2之後:

                  ┌─ GDB #1:普通 Debug
STM32 ← OpenOCD ──┤
                  └─ GDB #2:Live Watch
  1. serverCwd:

用終端命令直接查找下:

# Linux
which openocd

# Windows
where.exe openocd

Linux如上圖是/usr/bin/openocd,所以serverCwd填/usr/bin。

Windows如上圖是C:\xpack-openocd-0.12.0-7\bin\openocd.exe,所以serverCwd填C:\xpack-openocd-0.12.0-7\bin。 但是不能直接填C:\xpack-openocd-0.12.0-7\bin,因為在json中\是轉義字符,所以傻逼Windows應該填C:/xpack-openocd-0.12.0-7/bin或者雙反斜槓C:\\xpack-openocd-0.12.0-7\\bin。

  1. 添加liveWatch參數

在serverCwd後面,runEntry前面加上:

            "liveWatch": {
                "enabled": true,
                "samplesPerSecond": "4"
            },

最後:

Linux:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "stgdbtarget",
            "request": "launch",
            "name": "STM32Cube: Launch Generic GDB Server",
            "origin": "snippet",
            "cwd": "${workspaceFolder}",
            "preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "program": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
            "gdb": "${command:st-stm32-ide-debug-launch.get-gdb-executable}",
            "deviceName": "${command:st-stm32-ide-debug-launch.get-device-name}",
            "deviceCore": "${command:st-stm32-ide-debug-launch.get-core-name}",
            "deviceTrustzone": "${command:st-stm32-ide-debug-launch.get-trustzone-status}",
            "serverExe": "openocd",
            "serverParameters": [                
                "-f",
                "interface/stlink.cfg",

                "-c",
                "transport select swd",

                "-f",
                "target/stm32f1x.cfg",

                "-c",
                "$_TARGETNAME configure -gdb-max-connections 2"],
            "serverHost": "localhost",
            "serverPort": "3333",
            "serverCwd": "/usr/bin",
            "liveWatch": {
                "enabled": true,
                "samplesPerSecond": "4"
            },
            "runEntry": "main",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "imageOffset": "",
                    "symbolFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "symbolOffset": ""
                }
            ]
        },
        {
            "type": "stgdbtarget",
            "request": "attach",
            "name": "STM32Cube: Launch GDB Client",
            "origin": "snippet",
            "cwd": "${workspaceFolder}",
            "preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "program": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
            "gdb": "${command:st-stm32-ide-debug-launch.get-gdb-executable}",
            "serverHost": "localhost",
            "serverPort": "${command:st-stm32-ide-debug-launch.get-server-port}",
            "runEntry": "main",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "imageOffset": "",
                    "symbolFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "symbolOffset": ""
                }
            ]
        }
    ]
}

Windows:

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "stgdbtarget",
            "request": "launch",
            "name": "STM32Cube: Launch Generic GDB Server",
            "origin": "snippet",
            "cwd": "${workspaceFolder}",
            "preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "program": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
            "gdb": "${command:st-stm32-ide-debug-launch.get-gdb-executable}",
            "deviceName": "${command:st-stm32-ide-debug-launch.get-device-name}",
            "deviceCore": "${command:st-stm32-ide-debug-launch.get-core-name}",
            "deviceTrustzone": "${command:st-stm32-ide-debug-launch.get-trustzone-status}",
            "serverExe": "openocd.exe",
            "serverParameters": [                
                "-f",
                "interface/stlink.cfg",

                "-c",
                "transport select swd",

                "-f",
                "target/stm32f1x.cfg",

                "-c",
                "$_TARGETNAME configure -gdb-max-connections 2"],
            "serverHost": "localhost",
            "serverPort": "3333",
            "serverCwd": "C:/xpack-openocd-0.12.0-7/bin",
            "liveWatch": {
                "enabled": true,
                "samplesPerSecond": "4"
            },
            "runEntry": "main",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "imageOffset": "",
                    "symbolFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "symbolOffset": ""
                }
            ]
        },
        {
            "type": "stgdbtarget",
            "request": "attach",
            "name": "STM32Cube: Launch GDB Client",
            "origin": "snippet",
            "cwd": "${workspaceFolder}",
            "preBuild": "${command:st-stm32-ide-debug-launch.build}",
            "program": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
            "gdb": "${command:st-stm32-ide-debug-launch.get-gdb-executable}",
            "serverHost": "localhost",
            "serverPort": "${command:st-stm32-ide-debug-launch.get-server-port}",
            "runEntry": "main",
            "imagesAndSymbols": [
                {
                    "imageFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "imageOffset": "",
                    "symbolFileName": "${command:st-stm32-ide-debug-launch.get-projects-binary-from-context1}",
                    "symbolOffset": ""
                }
            ]
        }
    ]
}

4.4.3.如何進入調試

4.4.3.1.顯示1

如果你是下圖這樣,請按下面這樣做:

如果不是,請往下滑看下面的顯示2。

alt text

點完Run and Debug後,如下圖:

  • ST-Link選STM32cube: STM32 Launch STLink GDB Server
  • J-Link選STM32Cube: STM32 LaunchJLink GDB Server
  • openOCD接管選STM32Cube: Launch Generic GDB Server

alt text

4.4.3.2.顯示2

如果你是下圖這樣,請按下面這樣做:

alt text

你顯示上面這樣,可能是因為你已經有生成的launch.json了。(這樣直接點擊就行)

alt text

4.4.4.進入調試

然後會出現這個條,他會下載程序到板子(僅J-link) alt text

然後就成功下載了程序並進入了Debug

alt text

按照下圖所示,把你要監視的變量輸入到最頂上的框裏,就可以加入到實時監視框裏了。

結構體也可以:

4.4.5.更換調試器軟件為cortex debug(可選,很沒啥必要):

4.4.5.1.安裝cortex debug插件

在VScode裏搜索cortex debug並安裝

4.4.5.2.進行launch.json的配置

新建.vscode/launch.json:

{
    "version": "0.2.0",

    "configurations": [
        {
            // 调试配置名称
            "name": "STM32 - OpenOCD - Cortex Debug",

            // Cortex-Debug 固定写法
            "type": "cortex-debug",

            // 下载程序并开始调试
            "request": "launch",

            // 工程工作目录
            "cwd": "${workspaceFolder}",

            // ★ 必改:编译生成的 ELF
            "executable": "${workspaceFolder}/build/Debug/TEST.elf",

            // 使用 OpenOCD
            "servertype": "openocd",

            // ★ OpenOCD 可执行文件
            // Linux 下用 which openocd 查询
            "serverpath": "/usr/bin/openocd",

            // ★ 根据调试器和 MCU 修改
            //
            // ST-Link:
            // interface/stlink.cfg
            //
            // STM32F1:
            // target/stm32f1x.cfg
            //
            // STM32F4 则是:
            // target/stm32f4x.cfg
            "configFiles": [
                "interface/stlink.cfg",
                "target/stm32f1x.cfg"
            ],

            // ★ ARM GNU Toolchain 的 bin 目录
            // 建议不要直接写 "~"
            // 用 ${env:HOME} 更稳
            "armToolchainPath": "${env:HOME}/.local/share/stm32cube/bundles/gnu-tools-for-stm32/14.3.1+st.2/bin",

            // 启动后运行到 main()
            "runToEntryPoint": "main",

            // ★ Cortex Live Watch
            // OpenOCD 下可用
            // samplesPerSecond 最大 20
            // 先用 4Hz 足够
            "liveWatch": {
                "enabled": true,
                "samplesPerSecond": 4
            }


            // ============================================================
            // 以下为可选配置
            // ============================================================


            // 如果 Cortex-Debug 找不到 OpenOCD,
            // Linux:
            // which openocd
            //
            // 一般 Fedora 是:
            // /usr/bin/openocd
            //
            // "serverpath": "/usr/bin/openocd",


            // 如果 OpenOCD 找不到 interface/*.cfg 或 target/*.cfg,
            // Fedora 一般脚本目录在:
            // /usr/share/openocd/scripts
            //
            // 可以显式增加:
            //
            // "searchDir": [
            //     "/usr/share/openocd/scripts"
            // ],


            // 调试 Cortex-Debug / OpenOCD 问题:
            //
            // "showDevDebugOutput": "raw"
        }
    ]
}

目前我們要知道三件事,configFiles,executable,armToolchainPath和serverpath:

  1. configFiles:

參考 openocd的兩個-f參數

我們用的stm32f103c8和st-link: 所以"configFiles": ["interface/stlink.cfg","target/stm32f1x.cfg"]。

  1. executable:

用vscode的終端命令直接查找下,或者直接在VScode的文件管理器裏找:

# Linux
find build -name "*.elf"
# Windows
gci build -Recurse -File -Filter "*.elf"

注意,Windows要用powershell,不可以用cmd。

如上圖所示,在build/Debug/TEST.elf。

所以executable = ${workspaceFolder}/build/Debug/TEST.elf。

  1. armToolchainPath:

用vscode的終端命令直接查找下:

cube bundle show --project

這個輸出説明,我在用gnu-tools-for-stm32@14.3.1+st.2

用命令找他在哪:

# Linux
find ~/.local/share/stm32cube/bundles/gnu-tools-for-stm32 \
  -type f -name "arm-none-eabi-gdb"
# Windows
gci "$env:LOCALAPPDATA\stm32cube\bundles\gnu-tools-for-stm32" `
  -Recurse -File -Filter "arm-none-eabi-gdb.exe"

注意,Windows要用powershell,不可以用cmd。

複製輸出結果:

/home/tungchiahui/.local/share/stm32cube/bundles/gnu-tools-for-stm32/14.3.1+st.2/bin/arm-none-eabi-gdb

但是去掉最後的執行程序arm-none-eabi-gdb,只需要到bin即可:

/home/tungchiahui/.local/share/stm32cube/bundles/gnu-tools-for-stm32/14.3.1+st.2/bin

所以armToolchainPath = /home/tungchiahui/.local/share/stm32cube/bundles/gnu-tools-for-stm32/14.3.1+st.2/bin。

  1. serverpath:

用終端命令直接查找下:

# Linux
which openocd

而Windows,你自己裝哪的你應該知道吧。。。

最終的launch.json:

{
    "version": "0.2.0",

    "configurations": [
        {
            // 调试配置名称
            "name": "STM32 - OpenOCD - Cortex Debug",

            // Cortex-Debug 固定写法
            "type": "cortex-debug",

            // 下载程序并开始调试
            "request": "launch",

            // 工程工作目录
            "cwd": "${workspaceFolder}",

            // ★ 必改:编译生成的 ELF
            "executable": "${workspaceFolder}/build/Debug/TEST.elf",

            // 使用 OpenOCD
            "servertype": "openocd",

            // ★ OpenOCD 可执行文件
            // Linux 下用 which openocd 查询
            "serverpath": "/usr/bin/openocd",

            // ★ 根据调试器和 MCU 修改
            //
            // ST-Link:
            // interface/stlink.cfg
            //
            // STM32F1:
            // target/stm32f1x.cfg
            //
            // STM32F4 则是:
            // target/stm32f4x.cfg
            "configFiles": [
                "interface/stlink.cfg",
                "target/stm32f1x.cfg"
            ],

            // ★ ARM GNU Toolchain 的 bin 目录
            // 建议不要直接写 "~"
            // 用 ${env:HOME} 更稳
            "armToolchainPath": "/home/tungchiahui/.local/share/stm32cube/bundles/gnu-tools-for-stm32/14.3.1+st.2/bin",

            // 启动后运行到 main()
            "runToEntryPoint": "main",

            // ★ Cortex Live Watch
            // OpenOCD 下可用
            // samplesPerSecond 最大 20
            // 先用 4Hz 足够
            "liveWatch": {
                "enabled": true,
                "samplesPerSecond": 4
            }
        }
    ]
}
4.4.5.3.Debug與LiveWatch

先編譯

點擊進入debug:

成功進入:

複製一個你程序裏的某個全局變量,我這裏是cmd_vel2:

填到cortex live watch,注意不是stm32cube live watch:

然後點運行看一下變量cmd_vel2

是不斷在變化的:

5.常見問題

5.1.Linux下USB權限問題

如果你都正常識別出設備了,則沒必要做這一步了

如果你遇到的話,你解決不了就讓AI來解決,AI幾秒鐘就給你把事辦了

如果調試器插上後能在 lsusb 中看到,但 VS Code 找不到設備,或者調試輸出中出現下面的報錯,通常是當前用户沒有訪問 USB 設備節點的權限:

libusb couldn't open USB device /dev/bus/usb/001/008, errno=13
libusb requires write access to USB device nodes
ST-Link enumeration failed

先在終端運行 lsusb,確認調試器已被系統識別。報錯中的 /dev/bus/usb/001/008 只是示例,實際路徑以你自己的輸出為準。可以用 ls -l 查看該節點的權限:

lsusb
ls -l /dev/bus/usb/001/008

**使用 ST-Link:**先按上文點擊插件中的 install ST-Link udev rules。如果仍然報權限錯誤,檢查規則是否裝到了系統中:

find /etc/udev/rules.d /usr/lib/udev/rules.d -maxdepth 1 -iname '*stlink*.rules' -print 2>/dev/null

如果沒有找到規則,可以從 ST 官方的 STSW-LINK007 下載頁獲取安裝包。解壓後進入 AllPlatforms/StlinkRulesFilesForLinux,按其中的 readme.txt 安裝與你的發行版對應的 udev 規則包。在這個目錄中,Fedora 使用 .rpm 包,Ubuntu/Debian 使用 .deb 包:

# Fedora:只运行这一行
sudo dnf install ./st-stlink-udev-rules-*.rpm

# Ubuntu/Debian:只运行这一行
sudo apt install ./st-stlink-udev-rules-*.deb

如果下載的包名不同,以實際文件名和隨包説明為準。ST 的發行説明也説明了 Linux 下需要安裝相應的 ST-Link USB 訪問規則。

**使用 J-Link:**上文安裝的 jlink-gdbserver bundle 用於啓動調試服務;USB 權限還需要 SEGGER 的 udev 規則。安裝 SEGGER J-Link Software and Documentation Pack 中對應發行版的 .rpm 或 .deb 包時,會一併安裝規則。如果使用解壓版,則按照包內 README.txt,將 99-jlink.rules 複製到 /etc/udev/rules.d/。具體方法見 SEGGER 的 Linux 排查説明。

安裝規則後,運行:

sudo udevadm control --reload-rules

然後拔下調試器再插回去,重新運行 lsusb,用新的總線號和設備號查看 /dev/bus/usb/... 節點。可以將實際路徑代入下方命令,檢查當前用户能否讀寫:

test -r /dev/bus/usb/001/008 && test -w /dev/bus/usb/001/008 && echo 'USB 设备节点可读写'

拔插後設備號可能變化,不要照抄示例中的 001/008。確認權限後,回到 VS Code 重新選擇調試器。如果 lsusb 根本看不到調試器,應先檢查 USB 線、接口和供電;這不是 udev 權限問題。

這裏檢查的是 /dev/bus/usb/...。如果另外還要打開板載虛擬串口 /dev/ttyACM*,那是串口設備的權限,需要分別排查。