Remote STM32 Development and Debugging with VSCode + OpenOCD

Code & Dev
Embedded
由AI生成的摘要 OwO

This article explains how to perform remote debugging and flashing of STM32 microcontrollers in VSCode using OpenOCD, with a Raspberry Pi 5 acting as a debugging bridge connecting a DAPLink debugger to the target board. It details configuring OpenOCD on the Raspberry Pi to listen on all network interfaces, and using GDB from the ARM GNU Toolchain together with the Cortex-Debug plugin on the PC to connect via TCP/IP to the remote OpenOCD service—enabling operations such as breakpoint debugging and code flashing. Configuration examples for `launch.json` and `tasks.json` are also provided for seamless integration into the VSCode workflow.

[PC] --Wi-Fi--> [Raspberry Pi 5] --USB--> [DAPLink] --SWD--> [STM32 Target Board]

GDB and OpenOCD

GDB  <-- TCP/IP -->  OpenOCD  <-- JTAG/SWD -->  MCU

Raspberry Pi Configuration

Test DAPLink USB connection status:

lsusb

Required Packages

  • openocd
  • gdb-multiarch
  • git
  • make
sudo apt install openocd gdb-multiarch git make

OpenOCD Setup

openocd -f interface/cmsis-dap.cfg -f target/stm32f1x.cfg

By default, the GDB server started by OpenOCD (port 3333) listens only on the local loopback address (127.0.0.1). We need OpenOCD to listen on all network interfaces (0.0.0.0).

Create a custom configuration file:

nano ~/remote_daplink.cfg

Content of ~/remote_daplink.cfg:

# Specify CMSIS-DAP interface
adapter driver cmsis-dap

# Use SWD protocol (supported by STM32F1)
transport select swd

# Optional: set adapter speed; reduce if connection is unstable (unit: kHz)
adapter speed 1000

# Load STM32F1x target configuration
source [find target/stm32f1x.cfg]

# Bind to all network interfaces
bindto 0.0.0.0
gdb_port 3333
telnet_port 4444
tcl_port 6666

# Optional: run OpenOCD as a background daemon
# daemon_startup attach

Launch OpenOCD with the custom config:

sudo openocd -f ~/remote_daplink.cfg

Tip: Use -d to output debug information.

To run in the background:

nohup sudo openocd -f ~/remote_daplink.cfg > /tmp/openocd.log 2>&1 &

PC Configuration

Install ARM GNU Toolchain

Primarily needed for the arm-none-eabi-gdb debugger.

>> ARM GNU Toolchain

The arm-none-eabi-gdb debugger relies on the OpenOCD server. Commands issued in GDB are sent over the network to OpenOCD, which translates them into low-level JTAG/SWD commands executed by the debug probe on the target MCU.

Keil Output

Options for Target -> Output
File TypePurpose
.axfExecutable file containing full debug symbols. Used for debugging and flashing via OpenOCD + GDB.
.hexIntel Hex format file, commonly used for production flashing.
.binRaw binary image file, typically used for OTA updates, etc.

VSCode Setup

First, install the Cortex-Debug extension in VSCode.

For remote debugging, configure ./.vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Remote Debug (STM32F1)",
      "cwd": "${workspaceFolder}",
      "executable": "./MDK-ARM/RaspVisionCar/RaspVisionCar.axf",
      "request": "launch",
      "type": "cortex-debug",
      "servertype": "external",
      "gdbTarget": "192.168.156.107:3333",
      "gdbPath": "arm-none-eabi-gdb",
      "device": "STM32F103C8",
      "runToEntryPoint": "main"
    }
    //......
  ]
}

Manual GDB flashing via command line:

arm-none-eabi-gdb "D:/Projects/STM32/RaspVisionCar/MDK-ARM/RaspVisionCar/RaspVisionCar.axf"
target extended-remote 192.168.156.107:3333
monitor reset halt
load

For automated remote flashing, configure ./.vscode/tasks.json:

{
    "label": "Flash via Remote GDB (OpenOCD)",
    "type": "shell",
    "command": "arm-none-eabi-gdb", // Ensure it's in PATH (GNU Arm Embedded Toolchain)
    "args": [
        "build/RaspVisionCar.elf",
        "-q",
        "-ex", "target extended-remote ${input:remoteGdbHost}:3333",
        "-ex", "monitor reset halt",
        "-ex", "load",
        "-ex", "monitor reset",
        "-ex", "detach",
        "-ex", "quit"
    ],
    "group": "build",
    "presentation": {
        "echo": true,
        "reveal": "silent",
        "focus": false,
        "panel": "shared",
        "clear": true
    },
    "dependsOn": "Build Project (Release)" // Build before remote flashing
}