This is a collection of lightweight CMake and Python scripts that can build STM32 CubeMX projects with CMake and set up VSCode for editing/building/debugging.
It is a more lightweight / modular replacement of ioc2cmake, taking advantage of VSCode CMake tools, avoiding the need to pass compiler flags / include paths etc directly to VSCode.
- Parses CubeMX .ioc project file
- Determines compile / link flags & linker script from project file
- Adds relevant CubeMX / CMSIS sources & include paths to CMake target
- Supports flash/debug tools: stlink, pyocd, openocd, blackmagic
- Creates make targets
flash
,erase
,reset
- Creates VSCode
launch.json
for debugging
- Create a project with CubeMX
- Generate source code. (Select "Project->Toolchain/IDE: Makefile" or "STM32CubeIDE" and "Code Generator->Copy only necessary library files")
- Copy this repository to the source tree or add it as
git submodule
- Create a
CMakeLists.txt
from theCMakeLists-example.txt
- Make sure
arm-none-eabi-gcc
is in the PATH
Set up your executable target with a regular add_executable(<target_name> <target_sources>)
and then call cubemx_target(<target_name> <options...>)
to add the relevant sources and compile/link flags to it.
cubemx_target()
supports following options (TARGET
and IOC
are mandatory, the rest is optional):
Name | Default value | Description |
---|---|---|
TARGET |
- | CMake target name for the executable. The TARGET keyword can also be omitted. |
IOC |
- | CubeMX .ioc project file. |
CUBEMX_SOURCE_DIR |
$CMAKE_CURRENT_SOURCE_DIR |
Directory of the CubeMX generated code. It's possible to build the same application for different targets, by pointing to a different CUBEMX_SOURCE_DIR per target. |
CUBEMX_CORE_DIR |
$CUBEMX_SOURCE_DIR |
Directory of the custom code generated by CubeMX for the particular target (Core folder). |
CUBEMX_LIB_DIR |
$CUBEMX_SOURCE_DIR |
Directory of the generic platform code used by CubeMX (Drivers and Middlewares ). It's possible to keep it separate from the source tree, instead of letting CubeMX copy it to the project. See e.g. STM32CubeL4 |
STARTUP |
startup_stmXYZ.s |
By default the startup file provided by CubeMX is used, but it can be overridden if a custom one is needed (e.g. for a bootloader). |
LDSCRIPT |
STMXYZ_FLASH.ld |
By default the linker script provided by CubeMX is used, but it can be overridden if a custom one is needed (e.g. for a bootloader and/or custom memory layouts). |
FLASH_TARGET_NAME |
flash |
CMake target name for the "flash to target" operation. By default, make flash will program the target. To avoid name collision, it is necessary to assign different names, if multiple cubemx_target s are created. |
IMG_ADDR |
0x08000000 |
Start address of flash image. It can be overridden e.g. when a bootloader is used. |
ELF2BIN_OPT |
- | Additional options to be passed to objcopy , e.g. for padding of the .bin file. |
ELF2LST_OPT |
- | Additional options to be passed to objdump , e.g. for prefixing of intermixed source in the .lst file. |
mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=../cubemx.cmake/arm-gcc.cmake .. && make
- Make sure the "CMake Tools" extension is installed.
- Point VSCode to the CMake toolchain file in the project directory:
mkdir -p .vscode && echo '[{ "name": "arm-gcc from CMake Toolchain", "toolchainFile": "${workspaceRoot}/cubemx.cmake/arm-gcc.cmake" }]' > .vscode/cmake-kits.json
- Start VSCode and select the kit "arm-gcc from CMake Toolchain"
-
Depending on the project setup and generated sources, one of the symbols
USE_FULL_LL_DRIVER
,USE_HAL_DRIVER
have to be defined. Most of the time, they can both be used (like in the example CMakeLists.txt) but if there are compiler errors due to missing driver include files, one of them might need to be removed. -
For some STM32 models, such as the STM32F103 used on the famous "blue pill" board, the MCU type definition and name of the startup file used by CubeMX is different from the
Mcu.UserName
provided in the.ioc
file. In that case, you need to specify that information explicitly. Example for the "blue pill" board:
target_compile_definitions(bluepill_project PRIVATE STM32F103xB)
cubemx_target(
TARGET bluepill_project
IOC ...
STARTUP "${CMAKE_CURRENT_LIST_DIR}/startup_stm32f103xb.s"
)
-
The list of CubeMX source files is determined by globbing at CMake configuration stage. If it changes (by re-generating the sources with added peripherals, for example) then the CubeMX configuration has to be invoked again (in VSCode: Ctrl-Shift-P & "CMake: Configure" or "Developer: Reload Window")
-
Only the sources in
Core
andDrivers
are added automatically. If there are additional generated sources (e.g. Middlewares), they have to be added manually, for instance:
target_include_directories(example_target PRIVATE
"USB_HOST/App"
"USB_HOST/Target"
"Middlewares/ST/STM32_USB_Host_Library/Core/Inc"
"Middlewares/ST/STM32_USB_Host_Library/Class/CDC/Inc"
)
file(GLOB_RECURSE MIDDLEWARE_SRC
"USB_HOST/*.c"
"Middlewares/*.c"
)
target_sources(example_target PRIVATE ${MIDDLEWARE_SRC})
-
Other user-specific source files (e.g. a dedicated application folder separate from the CubeMX sources) can be added the same way as above
-
For most STM32 chips,
pyocd
must be updated with a device pack to recognize the chip, e.g.
pyocd pack -i stm32f407vgtx
- The current
arm-none-eabi-gdb
from developer.arm.com is still linked againstlibncurses5
, which may not be installed on a recent Linux distribution. (On Ubuntu, install it withsudo apt install libncurses5
)
- STM32F407VGT (STM32F407G-DISC1)
- STM32L496ZGT (NUCLEO-L496ZG)
- STM32L433RCT (NUCLEO-L433RC-P)
- STM32F767ZIT (NUCLEO-F767ZI)
- STM32H743ZIT (NUCLEO-H743ZI)