The official STM32 VS Code extension from STMicroelectronics represents a significant shift in the embedded development workflow. Rather than forcing developers into the heavyweight STM32CubeIDE Eclipse-based environment, the extension brings STM32 development into a modern, lightweight editor. But understanding what the extension actually does under the hood is important before trusting it for production firmware work.
At its core, the extension wraps a container-based or VM-based toolchain. On first install, it downloads a preconfigured virtual machine image that contains the arm-none-eabi-gcc toolchain, OpenOCD, and STM32CubeMX. This VM runs transparently in the background, and the extension communicates with it via a JSON-RPC bridge. This design means your host machine doesn't need to have the ARM toolchain installed globally — but it also means the extension has a large disk footprint and requires virtualization support.
Build integration is handled through CMake. The extension generates a CMakeLists.txt based on the CubeMX project configuration, and subsequent builds invoke CMake + Ninja through the VM. For CI/CD pipelines, this is an important detail: you cannot simply run the extension's build command in a GitHub Actions runner without also spinning up the VM, which makes headless CI more complex than with a standard Makefile workflow.
Debugging is handled through a GDB server proxy. The extension spawns OpenOCD (inside the VM) and connects VS Code's native debug adapter to it via a tunneled port. This architecture works reliably for single-core MCUs, but multi-core debugging on devices like the STM32MP1 requires additional configuration of the multi-target launch.json settings. The extension's documentation on this is sparse, and we found that direct OpenOCD configuration files from the command line are often more predictable for complex debugging scenarios.
Despite its quirks, the STM32 VS Code extension is a meaningful improvement for teams already standardized on VS Code. The IntelliSense configuration it generates (via c_cpp_properties.json with the correct include paths and defines from CubeMX) alone justifies its use — this was historically one of the most painful parts of setting up a productive STM32 development environment.