Project Anatomy
Every firmware project has the same shape, whether it lives in src/, src/tests/ or
starter-projects/. This page uses src/bmc as the example. For what each board actually
does, see Boards.
What You Should Edit
Almost everything in a project directory is generated and will be overwritten. The files that are genuinely yours:
Src/*.cpp: your firmware. Picked up by a glob, so new files need no CMake change.Inc/*.hpp: your headers, other than the generated<project>_config.hpp.USER CODE BEGIN/USER CODE ENDblocks inside CubeMX'smain.candmain.h.- The
.iocfile, edited through the CubeMX GUI.
Everything else regenerates.
File Breakdown
src/bmc/
CMakeLists.txt generated by update_cmake_cfg.py
CMakePresets.json generated by update_cmake_cfg.py
bmc.ioc CubeMX, edited through the GUI
startup_stm32g431xx.s CubeMX
STM32G431XX_FLASH.ld CubeMX, referenced by the toolchain file
cmake/
gcc-arm-none-eabi.cmake CubeMX, used by every preset
starm-clang.cmake CubeMX, unused
Inc/
main.h CubeMX, USER CODE blocks are yours
stm32g4xx_hal_conf.h CubeMX
stm32g4xx_it.h CubeMX
bmc_config.hpp generated by config_gen.py
motor.hpp yours
err.hpp yours
type.hpp yours
Src/
main.c CubeMX, USER CODE blocks are yours
stm32g4xx_hal_msp.c CubeMX
stm32g4xx_it.c CubeMX
syscalls.c CubeMX
sysmem.c CubeMX
system_stm32g4xx.c CubeMX
controller.cpp yours
The five CubeMX .c files plus the startup assembly are compiled by lib/stm32g4, not by the
project itself. The project's own target_sources globs Src/*.cpp only.
Two Directory Layouts
Most projects keep sources at Src/ and Inc/. Some CubeMX versions emit Core/Src and
Core/Inc instead, and src/tests/serial is the one project in this tree that does. The generator
probes for both, so either works, but do not mix them within a project.
The Interface with lib/
A project must set three variables before pulling in the library tree:
set(MX_SRC_DIR "${CMAKE_SOURCE_DIR}/Src")
set(MX_INC_DIR "${CMAKE_SOURCE_DIR}/Inc")
set(MX_STARTUP_S "${CMAKE_SOURCE_DIR}/startup_stm32g431xx.s")
add_subdirectory(../../lib fwlib)
lib/stm32g4 fails the configure step if any is missing, and lib/CMakeLists.txt uses their
presence to decide whether this is an MCU build at all. lib/stm32g4 then reaches back up and adds
sources to the project's own executable target by name, which is why the ordering matters.
Linked Libraries
The bottom of a generated CMakeLists.txt looks like this:
# Add linked libraries
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx
# Add user defined libraries
stm32
dbc
util
)
stm32cubemx is always present. The rest come from the --lib flags passed to scripts/new.sh:
Warning
update_cmake_cfg.py deletes and re-renders CMakeLists.txt, CMakePresets.json and
.clangd from scratch. It does not read your existing library list back out of the file.
Re-running it without re-passing the full set of --lib flags silently drops the libraries
the project was linking, and the failure shows up as a confusing link error later.
Library names are not validated. A typo becomes a missing-target error at build time.
Regenerating a Project
There is no shell wrapper for this. Run the tool directly: