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.
flash
, erase
, reset
launch.json
for debugginggit submodule
CMakeLists.txt
from the CMakeLists-example.txt
arm-none-eabi-gcc
is in the PATHSet 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
mkdir -p .vscode && echo '[{ "name": "arm-gcc from CMake Toolchain", "toolchainFile": "${workspaceRoot}/cubemx.cmake/arm-gcc.cmake" }]' > .vscode/cmake-kits.json
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
and Drivers
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 against libncurses5
, which may not be installed on a recent Linux distribution. (On Ubuntu, install it with sudo apt install libncurses5
)