The STM32CubeIDE software serves as an excellent starting point for STM32 development. However, when it comes to developer experience, the IDE provided by ST can feel sluggish and resource-intensive.
In this article, we’ll explore how to seamlessly transition from STM32CubeIDE to Visual Studio Code for your embedded software development needs. Under the hood, we’ll set up a robust CMake build system, utilize clangd for indexing, formatting and tidy checks, and configure VS Code to efficiently manage the CMake project, clangd, and debugging.
Let’s dive into the details!
Creating a project with STM32CubeIDE
In this chapter, we’ll walk through the process of setting up a C++ project using STM32CubeIDE. If you’ve already configured a project, feel free to skip ahead to the next section.
New STM32 project
Let's create a new project in STM32CubeIDE by clicking on File -> New -> STM32 Project
Micro-controller choice
In the micro-controller search we are gonna enter the name of the micro-controller that we are using. In my case it's the NUCLEO board with the micro-controller STM32L4A6ZGTX.
Project name
Let's now enter the name of the project and it's location.
HAL Configuration
After clicking finish, the configuration view will open up. Here you will be able to configure your micro-controller hardware. For the purpose of this demo, let's configure a led as GPIO Output and give the pin a name that we can later reference in our source files.
Code generation settings
As a last step before letting STM32CubeIDE generate the code, select Project Manager -> Project -> Do not generate the main()
And Project Manager -> Project -> Generate peripheral initialization as a pair of '.c/.h' files for peripheral
Generating the HAL code
We are now ready to generate the code. Click save or the generate code symbol.
Application folder
We selected to not generate the main so that we can write a cpp main ourselves. Start by creating a source folder in the root directory by right clicking on the project then clicking on New -> Source Folder
Creating the main
And create a main.cpp
file inside the Application
folder:
The code for the main.cpp
used in this demo is the following:
#include "main.h"
#include "gpio.h"
extern "C"
{
extern void SystemClock_Config();
}
int main()
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
while (true)
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
HAL_Delay(1000);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
HAL_Delay(1000);
}
}
Compile and debug
We are now ready to compile and debug our project with STM32CubeIDE.
Setting up the CMake project
Let's now close the STM32CubeIDE window and start integrating our STM project in VS code. The first thing to do is to set up the CMake project.
Start by checking if you have CMake and Ninja already installed on your system by typing in the terminal:
cmake --version
ninja --version
If CMake or Ninja are missing, you can install them from your package manager in linux or from the official websites in Windows:
In Windows you will have to add the path of your Ninja executable to the system environment variables. For example, if your executable is located in C:\Ninja\ninja.exe
, you can add the path C:\Ninja\
to your system environment variables.
Afterward clone the github folder associated to this article and copy the following files to your project folder:
CMakeLists.txt
CMakePresets.json
gcc-arm-none-eabi.cmake
CMakeLists.txt
Open the CMakeLists.txt
file and if needed adapt the name of the micro-controller from STM32L4A6ZGT to the one that you are using. In the CMakeLists.txt
file check that your sources are defined in the PROJECT_SOURCES
variable and that the correct symbols are defined in the PROJECT_DEFINES
variable.
CMake toolchain file
The toolchain file gcc-arm-none-eabi.cmake
defines the location of the compiler toolchain that CMake uses.
The TOOLCHAIN_PREFIX
variable should point to the location of the compiler included by STM32CubeIDE. In linux it's usually inside /opt/st/
while in Windows it's usually inside C:\ST\
.
At this point you should be ready to let CMake configure and build your project. Open a terminal in the root of your project folder and type the following commands:
cmake --preset Application # configure project
cmake --build --preset Application # build project
The output of the last command when the compilation finishes should be something like:
[25/25] Linking CXX executable STM32-CMake-base.elf
Congratulation you compiled your embedded project with CMake and Ninja !
Setting up VS Code
From the github repo associated with this article, copy the .vscode
folder to your project folder.
In the .vscode/settings.json
file you can adapt define the location of gdb and gdb server to allow debugging. Additionally the location of the gcc compiler for clangd can also be adapted.
{
"cortex-debug.gdbPath": "/opt/st/stm32cubeide_1.15.0/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.12.3.rel1.linux64_1.0.100.202403111256/tools/bin/arm-none-eabi-gdb",
"cortex-debug.JLinkGDBServerPath": "/opt/st/stm32cubeide_1.15.0/plugins/com.st.stm32cube.ide.mcu.externaltools.jlink.linux64_2.2.200.202402092224/tools/bin/JLinkGDBServer",
"clangd.arguments": ["--query-driver=/opt/st/stm32cubeide_1.15.0/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.12.3.rel1.linux64_1.0.100.202403111256/tools/bin/arm-none-eabi-gcc"]
}
The file .vscode/extensions.json
specifies the recommended extensions to use. If you open the extension menu in VS Code, you will be able to see and install the extension listed in .vscode/extensions.json
.
After installing the recommended extensions, the VS Code CMake and clangd integration will start working. By opening a source file, clangd will index it and you will be able to start using the advanced functionality that the clangd language server provides.
Here an example of the sometimes very helpful checking that clangd performs by default:
You can now compile the project in VS Code by pressing CTRL + SHIFT + B
.
Debugging
The file .vscode/launch.json
that was copied in the previous chapter from the github repo configures the debugging settings. If you open it, you will see two configurations, one for the SEGGER J-Link debugger and the other for the ST-Link debugger.
In the left bar in VS Code, select the Debug symbol, then select the debug configuration compatible with your debugger and finally press the play button to flash the firmware on your micro-controller and start debugging.
Formatting and tidy checks
To enable formatting of the sources and clang-tidy checks, copy the following files from the cloned github folder to your application folder:
-
Application/.clang-format
: This file defines the formatting rules for your C/C++ code. -
Application/.clang-tidy
: Here, you’ll find configuration settings for clang-tidy. This tool analyzes your code for potential issues, such as code smells, bugs, and performance bottlenecks.
Note that clang-format and clang-tidy will be active only at the level of the configuration files. In this scenario, their effects will extend to all files residing inside the Application folder. In this way clangd will not format or perform checks on files generated by STM32CubeIDE.
Now you’re all set to streamline your STM32 development workflow using VS Code, CMake, and clangd. Happy coding!
Feel free to ask me any question in the comments.
Top comments (2)
really appreciate all the work that has gone into this great post
This is really neat. I'm not a huge fan of the STM32CubeIDE since I'm used to vscode for all of my coding work -- so thanks, I'll give that a try!