How to Develop STM32 on macOS with VS Code: A Complete Guide to CubeMX, OpenOCD, and DAPLink

This article explains how to build an STM32 development environment on macOS with VS Code, STM32CubeMX, and OpenOCD. It addresses common pain points such as the lack of a Keil alternative on Mac, disconnected flashing and debugging workflows, and the complexity of DAPLink setup. Keywords: STM32, VS Code, OpenOCD.

Technical Specifications at a Glance

Parameter Description
Operating System macOS
Target Platform STM32 microcontrollers
Core Languages C / CMake / JSON
Debug Protocols ST-Link, CMSIS-DAP
Build Method CMake-GCC project generated by STM32CubeMX
Core Tools VS Code, STM32CubeMX, OpenOCD, ARM GNU Toolchain
GitHub Stars Not provided in the original article, N/A
Core Dependencies cmake, openocd, arm-none-eabi-gcc, cortex-debug

This workflow gives macOS first-class STM32 development capabilities

Traditional STM32 development often depends on Keil, while macOS has long been at a disadvantage in terms of official IDE support, drivers, and debugging workflows. The core value of this setup is that it unifies code editing, project generation, compilation, flashing, and debugging inside VS Code.

Compared with older DIY combinations such as CLion + CubeMX + OpenOCD, the STM32CubeIDE for Visual Studio Code extension significantly lowers the integration barrier. For embedded developers using a MacBook, that means lower migration cost and a more consistent workflow.

A dedicated VS Code Profile is worth setting up

If you work across embedded systems, AI, Java, or computer vision, create separate Profiles for each area. This isolates extensions, themes, debuggers, and code intelligence rules, and prevents one development environment from contaminating another.

image-20260430211551951 AI Visual Insight: The image shows the VS Code settings interface or workspace view, with emphasis on using separate Profiles to isolate extension sets, themes, and language service configurations. This isolation is especially important for mixed embedded and AI development because it reduces indexing conflicts, debug configuration interference, and extension startup overhead.

Environment setup must cover the compiler, build system, and debugger

To develop STM32 applications on macOS, you need at least five categories of tools: an editor, a code generator, a build system, a cross compiler, and an on-chip debugger. OpenOCD, the ARM GNU Toolchain, and CMake can all be installed directly through Homebrew.

Tool Recommended Version Purpose Installation Method
VS Code Latest Editing, debugging, task integration Download from the official website
STM32CubeMX ≥ 6.10 Graphical peripheral configuration and project generation Download from the official website
CMake Latest Cross-platform build management brew install --formula cmake
ARM GNU Toolchain Latest Compile bare-metal ARM programs brew install --cask gcc-arm-embedded
OpenOCD Latest Flashing, GDB bridge, hardware debugging brew install openocd

Use version commands to validate the toolchain quickly

arm-none-eabi-gcc --version   # Check whether the ARM compiler is available
cmake --version               # Check whether CMake is installed successfully
openocd --version             # Check whether OpenOCD is available

These commands verify that the compile, build, and debug paths are all in place.

The VS Code extension stack defines the upper limit of the developer experience

The most important extension is not a set of individually installed pieces, but STM32CubeIDE for Visual Studio Code. It acts as the entry point for ST’s official VS Code workflow, automatically pulling in related components and, in many cases, installing ST-Link support services as well.

image-20260430211840587 AI Visual Insight: The image shows STM32Cube-related extensions in the VS Code Marketplace. The key takeaway is to choose the official bundled extension instead of installing components one by one. This design reduces the risk of missing dependencies and ensures that generation, build, and debugging capabilities come from the same official workflow.

image-20260430210623753 AI Visual Insight: This image likely shows the backend service deployment result after the extension is installed, highlighting that ST-Link-related services are provisioned automatically. That means the local environment evolves from a simple editor extension into a hardware-capable development terminal, reducing extra driver and tool configuration work.

It is also a good idea to install C/C++, CMake Tools, and Cortex-Debug. The first two handle semantic analysis and build management, while Cortex-Debug connects OpenOCD and GDB to the VS Code debug panel.

STM32CubeMX is the recommended way to generate a CMake project

Although the extension can create an empty project, the safer approach is still to create the project in STM32CubeMX. The reason is simple: CubeMX provides the most complete modeling capabilities for chip selection, clock trees, GPIO, middleware, and HAL initialization code.

When you create a new project, select the target chip, open Project Manager, and set the toolchain to CMake-GCC. The generated project will then integrate naturally with VS Code and CMake Tools.

image-20260430215003649 AI Visual Insight: The image shows the main interface of the official STM32 VS Code extension, including system binding packages, project entry points, or toolchain status. This indicates that the extension does more than improve the editor experience. It also handles SDK discovery, environment binding, and project lifecycle management.

image-20260430215207754 AI Visual Insight: This image appears to show the new project entry point in STM32CubeMX, emphasizing that you should start from chip selection rather than from a template. That choice determines the correctness of later HAL code, startup files, and peripheral initialization logic.

image-20260430220136353 AI Visual Insight: The image likely shows the Project Manager or code generation settings page. The key step is switching the generator to CMake-GCC. This option directly determines whether the output project can integrate seamlessly with the VS Code build and debug workflow.

image-20260430220611104 AI Visual Insight: This image is most likely the final configuration page before code generation, showing the project name, path, and toolchain information. It represents the stage just before CubeMX converts graphical hardware modeling into a compilable source project.

After code generation, you can build directly in VS Code

cmake -S . -B build/Release      # Generate the build directory
cmake --build build/Release      # Build the ELF file

These two commands correspond to the configuration and compilation stages of the STM32 project, and you can run them either in the terminal or through VS Code tasks.

image-20260430225929065 AI Visual Insight: The image shows the main VS Code interface after opening the STM32 project, typically including the source tree, build entry point, debug sidebar, and status bar. It confirms that the generated CMake project has been recognized correctly by the editor and now supports a standardized development workflow.

image-20260501122345353 AI Visual Insight: This image likely shows the build button or a successful build screen, indicating that VS Code has taken over the underlying CMake build process. For STM32 development, this step confirms that the HAL, startup files, and linker script now form a complete build artifact pipeline.

DAPLink flashing requires explicit OpenOCD integration

If you use ST-Link, VS Code can often detect the programmer directly in the debug view. DAPLink, however, uses the CMSIS-DAP protocol path, so you usually need to specify the interface and target scripts manually through OpenOCD.

Connect DAPLink first, then run the following test command. If you see a target connection log, the path is working.

openocd -f interface/cmsis-dap.cfg -f target/stm32f4x.cfg   # Connect to STM32F4 through CMSIS-DAP

This command verifies that OpenOCD can correctly recognize both DAPLink and the STM32 target board.

image-20260501124042821 AI Visual Insight: The image shows the VS Code debug or device selection area, indicating that the default workflow is optimized for ST-Link. For DAPLink users, this reveals exactly why an additional custom OpenOCD configuration is necessary.

image-20260501124509673 AI Visual Insight: This image likely shows OpenOCD terminal output with successful CMSIS-DAP detection, target core attachment, or flash information. It serves as critical evidence that DAPLink is ready for both flashing and GDB debugging.

Use tasks.json to formalize the build and flash workflow

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Build STM32",
      "type": "shell",
      "command": "cmake",
      "args": [
        "--build",
        "${workspaceFolder}/build/Release"
      ]
    },
    {
      "label": "DAPLink Flash",
      "type": "shell",
      "dependsOn": "Build STM32", 
      "command": "openocd",
      "args": [
        "-f", "interface/cmsis-dap.cfg",      
        "-f", "target/stm32f4x.cfg",          
        "-c", "program ${workspaceFolder}/build/Release/RM_Motor.elf verify reset exit" 
      ]
    }
  ]
}

This configuration turns the sequence of “build first, then flash” into a reusable task, which is ideal for rapid day-to-day firmware deployment.

image-20260501125310098 AI Visual Insight: The image is likely the VS Code task output window after flashing, showing steps such as build, program, verify, and reset. It demonstrates that tasks.json has successfully wrapped the command-line flashing flow into the editor.

Breakpoint debugging depends on Cortex-Debug and a visible GDB path

To debug with breakpoints in VS Code, install Cortex-Debug and create .vscode/launch.json. The key fields include the ELF executable path, the OpenOCD path, the target scripts, and the pre-launch build task.

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug STM32F407 with DAPLink",
      "type": "cortex-debug",
      "request": "launch",
      "cwd": "${workspaceFolder}",
      "executable": "${workspaceFolder}/build/Release/RM_Motor.elf", 
      "servertype": "openocd",
      "serverpath": "/opt/homebrew/bin/openocd", 
      "gdbPath": "/Applications/STM32CubeCLT/GNU-tools-for-STM32/bin/arm-none-eabi-gdb", 
      "configFiles": [
        "interface/cmsis-dap.cfg",
        "target/stm32f4x.cfg"
      ],
      "searchDir": [
        "/opt/homebrew/share/openocd/scripts"
      ],
      "runToEntryPoint": "main", 
      "preLaunchTask": "Build STM32"
    }
  ]
}

This configuration connects OpenOCD, GDB, and the target firmware to VS Code’s native debugging workflow.

image-20260501125622208 AI Visual Insight: The image shows the Cortex-Debug error screen reporting that it cannot find arm-none-eabi-gdb. The underlying issue is that the debugger frontend starts correctly, but the backend GDB executable is either not in PATH or not declared explicitly. The fix is to set gdbPath.

One stable best practice is to configure paths explicitly

On macOS, Homebrew, STM32CubeCLT, and manually installed packages may all live in different directories. Do not assume that VS Code will always inherit your shell PATH, especially when you launch it from the graphical interface. Explicitly setting serverpath, gdbPath, and searchDir is usually more reliable than depending on environment variables.

This workflow fits both beginners and medium-sized projects

In summary, this is not just a single-tool tutorial. It is a complete STM32 development pipeline: CubeMX handles hardware modeling, CMake handles builds, OpenOCD bridges flashing and debugging, and VS Code provides the unified user interface. For Mac users, this is currently one of the most practical solutions that balances official support, maintainability, and extensibility.

FAQ

Q1: Why use VS Code instead of STM32CubeIDE directly?

A: VS Code is lightweight, highly extensible, and integrates well with AI coding tools. It is also a good fit if you want to unify embedded, algorithm, and general software development inside one editor.

Q2: What is the configuration difference between DAPLink and ST-Link?

A: ST-Link can often be detected directly by the official extension, while DAPLink usually requires you to specify OpenOCD’s interface/cmsis-dap.cfg and the target chip script manually.

Q3: How do I fix the Cortex-Debug error that says GDB cannot be found?

A: First confirm in the terminal that arm-none-eabi-gdb exists. Then write the absolute path into the gdbPath field in launch.json to avoid mismatches between the VS Code startup environment and your shell PATH.

Core takeaway

This article reconstructs a minimum viable STM32 development workflow on macOS with VS Code. It covers environment setup, CubeMX project generation, VS Code extension configuration, DAPLink flashing, and Cortex-Debug breakpoint debugging, and it includes practical tasks.json and launch.json templates.