Setting Up GD32 Development Environment on Windows Using VSCode and CMake

Setting Up GD32 Development Environment on Windows Using VSCode and CMake

I previously set up the GD32 development environment in a Linux environment, but since I often use Windows, I made some improvements based on the original setup to enable compiling, downloading, and debugging microcontroller programs on Windows. See the following tweets for details:

Building GD32F470 Project Based on CMake

Debugging GD32F470 Based on PyOCD

Implementation Approach

  • Code Build: CMake, using the original CMakeLists file
  • Code Compilation: Invoking CMake
  • Program Download: Invoking OpenOCD
  • Program Debugging: Using Cortex-Debug
  • Program Printing: Using RTT via PyOCD

Among these, building, compiling, downloading, and printing are all written as VSCode tasks and visualized with Task Buttons.

Results

Results of building, compiling, downloading, and printing:

Debugging results

Preparation Work

  • Microcontroller: GD32F450
  • Debugger: DAPLink
  • PC: Windows 10
  • Editor: VSCode
  • Cross Compilation Toolchain: gcc-arm-none-eabi-10.3-2021.10
  • Build Tools: CMake, MinGW64 (mainly provides make tools)
  • Code Flashing and Debugging Tool: OpenOCD (Windows version)
  • Debug Plugin: Cortex-Debug (plugin used in VSCode)
  • VSCode Task Visualization Button Plugin: Task Buttons
  • RTT Printing Tool: PyOCD (PyOCD can also perform code flashing and debugging, but when using DAPLink + Cortex-Debug, live watch is not available)

Code Build

Code build refers to automatically generating a Makefile using CMake to prepare for the next step of compilation (if you directly use the Makefile, building is not necessary).

Implementing this by writing a task to invoke the CMake command:

Add to the <span>.vscode/tasks.json</span> tasks field (create this file if it does not exist):

        {
            // Task name
            "label": "CMake Configure",
            // Terminal execution
            "type": "shell",
            // Command to execute
            "command": "cmake",
            // Arguments passed to the command
            "args": [
                "-S", "${workspaceFolder}",                                                  // Source directory
                "-B", "${workspaceFolder}/build",                                           // Build directory
                "-DTOOLCHAIN_PREFIX=C:/Users/haijun/Desktop/123/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-",  // Specify cross-compilation prefix
                "-G", "MinGW Makefiles",                                                      // Specify generator  
                "-DCMAKE_MAKE_PROGRAM=C:/Users/haijun/Desktop/123/mingw64/bin/mingw32-make.exe"// Specify make program
            ],
            // Specify the directory for task execution and add temporary environment variables
            "options": {
                "cwd": "${workspaceFolder}", 
                "env": {
                    "PATH": "C:/Users/haijun/Desktop/123/mingw64/bin;${env:PATH}"
                }
            },
            // Task belongs to the build group.
            "group": {
                "kind": "build",
                "isDefault": false
            },
            // Parse error messages
            "problemMatcher": [],
            "detail": "Configure CMake project"
        },
  1. Since I did not add the CMake tool to the environment variable, I temporarily added CMake to the environment variable using <span>env</span>.
  2. Both the cross-compilation toolchain and make program are not added to the environment variable, so absolute paths are used directly.
  3. The actual CMake command executed:
cmake -S source_path \
  -B  build_directory \
  -DTOOLCHAIN_PREFIX=C:/Users/haijun/Desktop/123/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi- \
  -G MinGW Makefiles \
  -DCMAKE_MAKE_PROGRAM=C:/Users/haijun/Desktop/123/mingw64/bin/mingw32-make.exe

Open the command palette <span>ctrl+shift+p</span>, search for <span>tasks:run Task</span>, you can see the task and click to execute it.

Code Compilation

Add to the <span>.vscode/tasks.json</span> tasks field:

{
            "label": "CMake Build",
            "type": "shell",
            "command": "cmake",
            "args": [
                "--build", "build",   // Path to build
                "--target", "all",   // Compile all
                "-j 8"      // Multi-threading to speed up compilation
            ],
             "options": {
                 "cwd": "${workspaceFolder}", 
                 "env": {
                     "PATH": "C:/Users/haijun/Desktop/123/openocd-v0.12.0-i686-w64-mingw32/bin;${env:PATH}"
                 },
            "group": {
                "kind": "build",
                "isDefault": true
            },
      // Automatically parse compiler output
            "problemMatcher": {
                "owner": "cpp",           // Parse C/C++ output
                "fileLocation": ["relative", "${workspaceFolder}"],  // Use relative paths
                // Match compiler output using regular expressions
                "pattern": {
                    "regexp": "^(.*):(\d+):(\d*):\s*(warning|error):\s*(.*)$",
                    "file": 1,
                    "line": 2,
                    "column": 3,
                    "severity": 4,
                    "message": 5
                }
            },
  1. The actual command executed:
cmake --build build  --target all  -j 8
  1. Configure the <span>problemMatcher</span> field to match C errors and warnings and allow jumping to them.

Open the command palette <span>ctrl+shift+p</span>, search for <span>tasks:run Task</span>, you can see the task and click to execute it.

Code Download

Code download uses OpenOCD.

Add to the <span>.vscode/tasks.json</span> tasks field:

 {
            "label": "flash-openocd",
            "type": "shell",
            "command": "openocd",
            "args": [
                "-f", "./pyocd/openocd.cfg",
                "-c", "program build/gd32f470BaseProject.elf verify reset exit"
            ],
            "group": {
                "kind": "build",
                "isDefault": false
            },
            "options": {
                "cwd": "${workspaceFolder}", 
                "env": {
                    "PATH": "C:/Users/haijun/Desktop/123/openocd-v0.12.0-i686-w64-mingw32/bin;${env:PATH}"
                },
            },
            // There are dependencies, dependent tasks are executed in order
            "dependsOn": ["CMake Build"],
            "dependsOrder": "sequence",
            "problemMatcher": [],
            "detail": "Flashing using OpenOCD"
        },

The actual command executed:

openocd  -f ./pyocd/openocd.cfg  -c program build/gd32f470BaseProject.elf verify reset exit

Among them:

  1. <span>openocd.cfg</span> is the configuration file for OpenOCD.
# Downloader: cmsis-dap
adapter driver cmsis-dap
# Download method swd
transport select swd
# Target chip configuration file (since there is no gd32f4, use stm32f4x instead)
source [find target/stm32f4x.cfg]
  1. <span>-c indicates the command to execute</span>
    1. <span>program</span> is the program to be downloaded
    2. <span>verify</span> verifies after downloading
    3. <span>reset</span> resets the MCU
    4. <span>exit</span> exits OpenOCD

Open the command palette <span>ctrl+shift+p</span>, search for <span>tasks:run Task</span>, you can see the task and click to execute it.

  1. This task depends on <span>CMake Build</span> and executes in order.

Program Debugging

Debugging uses Cortex-Debug, so you need to configure the <span>launch.json</span> file.

Two methods for invoking <span>openocd</span> and <span>pyocd</span> are provided.

{
    // Use IntelliSense to learn about related properties. 
    // Hover to view descriptions of existing properties.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [

        {
            "name": "Debug with OpenOCD",
            "serverpath": "C:/Users/haijun/Desktop/123/openocd-v0.12.0-i686-w64-mingw32/bin/openocd.exe",
            "armToolchainPath":  "C:/Users/haijun/Desktop/123/gcc-arm-none-eabi-10.3-2021.10/bin/",
            "cwd": "${workspaceRoot}",
            "executable": "./build/gd32f470BaseProject.elf",
            "request": "launch",
            "type": "cortex-debug",
            "servertype": "openocd",
            "configFiles": [
                "./pyocd/openocd.cfg"],
            "searchDir": [],
            "runToEntryPoint": "main",
            "showDevDebugOutput": "none",
            "liveWatch": {
                "enabled": true,
                "samplesPerSecond": 1
            },
            "preLaunchTask": "CMake Build"
        },
        {
            "name": "GD32 Debug with PyOCD",
            "armToolchainPath":  "C:/Users/haijun/Desktop/123/gcc-arm-none-eabi-10.3-2021.10/bin/",
            "cwd": "${workspaceRoot}",
            "executable": "./build/gd32f470BaseProject.elf",
            "request": "launch",
            "type": "cortex-debug",
            "runToEntryPoint": "main",
            "servertype": "pyocd",
            "targetId":"gd32f470zg",
            "showDevDebugOutput": "none",
            "cmsisPack": "./pyocd/GigaDevice.GD32F4xx_DFP.3.2.0.pack",
            "liveWatch": {
                "enabled": true,
                "samplesPerSecond": 1
            }
        }
    ]
}

RTT Printing

Invoke the <span>pyocd rtt</span> command.

Add to the <span>.vscode/tasks.json</span> tasks field:

{
            "label": "RTT Print via pyOCD",
            "type": "shell",
            "command": "pyocd rtt",
            "args": [
                "--config", "pyocd.yaml"
            ],
            "presentation": {
                "reveal": "always",
                "panel": "shared",
                "echo": true,
                "focus": true,
                "showReuseMessage": true,
                "clear": false
            },
            "options": {
                "cwd": "${workspaceFolder}/pyocd", 
            },
            "problemMatcher": [],
            "isBackground": true,
            "detail": "View RTT print using pyOCD"
        }

The actual command executed:

pyocd rtt  --config pyocd.yaml

Task Visualization Buttons

Use the <span>Task Buttons</span> plugin to visualize tasks.

Add to the <span>settings.json</span>:

{
    // Whether to show tasks
    "VsCodeTaskButtons.showCounter": true,
    // Button list
    "VsCodeTaskButtons.tasks": [
        {
            // Button name
            "label": "๐Ÿ› ๏ธ",
            // Associated task
            "task": "CMake Configure",
            // Mouse hover tip
            "tooltip": "Start cmake Configure",
            // "color": "warning",
        },
        {
            "label": "๐Ÿš€ ",
            "task": "CMake Build",
            "tooltip": "Build the project",
        },
        {
            "label": "๐Ÿ“ฅ",
            "task": "flash-openocd",
            "tooltip": "Download bin file to flash",
        },
        {
            "label": "๐Ÿงน",
            "task": "CMake Clean",
            "tooltip": "Clean the project",
        },
        {
            "label": "๐Ÿ–จ๏ธ",
            "task": "RTT Print via pyOCD",
            "tooltip": "Print RTT info",
        }
    ]
}

Leave a Comment