CMake + CubeMX/CubeCLT Toolchain
Installing
- Install CubeMX. This is the
.iocfile editor. - Install CubeCLT. This is the command-line toolset that contains all the software necessary to build and deploy the codebase.
- Install CubeMCUFinder.
- Install the corresponding extension for your editor. In each case, the extension will need to be provided the location to CubeMX and CubeCLT.
Creating a New CubeMX Project
- Open CubeMX and navigate to
File→New Project. - A window should pop up. In this window, select your desired MCU or development board. To search, use the "Commercial Part Number" search bar.
- When you have selected your MCU/board, click
Start Projectin the top right. - Navigate to the
Project Managertab. - Give your project a name and set the
Project Locationto the desired directory. - Set the
Toolchain / IDEdropdown toCMake. - Now, still in the
Project Managertab, navigate to theCode Generatorsettings on the left menu. - Select
Copy only the necessary library files. This will reduce bloat on your computer by only bringing in the necessary HAL files for your specific project instead of all 900+. - Save the project by navigating to
File→Save Projector by pressingCtrl + S. - Click
Generate Codein the top right. CubeMX will generate the project files in the specified directory. For example, if the project name ismyprojectand the location is/home/user/mrover-esw/src/, the generated files will be in/home/user/mrover-esw/src/myproject/.
Adding CMake Dependencies to Projects
Removing Dependency on Generated HAL Drivers
By default, CubeMX generates HAL drivers and includes them in the project. The top level CMakeLists.txt then includes these generated HAL drivers in the build with the following line:
add_subdirectory(cmake/stm32cubemx)
If you take a look inside the CMakeLists.txt inside the cmake/stm32cubemx/ directory,
you will see that it includes all of the generated HAL drivers for the selected MCU. This
CMakeLists.txt is automatically generated by CubeMX to include the necessary HAL drivers
your project requires. For example:
set(STM32_Drivers_Src
${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/system_stm32g4xx.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ramfunc.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_gpio.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_exti.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr.c
${CMAKE_CURRENT_SOURCE_DIR}/../../Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_cortex.c
)
These generated HAL drivers total over 900 files, which is unnecessary and would bloat
the repository if committed. In order to prevent this, we remove the dependency on the
generated HAL drivers for each project and instead use a shared HAL driver library which
is hosted as a git submodule in lib/extern/STM32CubeG4.
To do this, we create our own CMakeLists.txt file in a new directory cmake/stm32cubemx_extern/.
This CMakeLists.txt file will replace the generated one and instead link to the shared
HAL driver library. For example, the above generated CMakeLists.txt would be replaced with the following:
set(STM32_Drivers_Src
${CMAKE_CURRENT_SOURCE_DIR}/../../Core/Src/system_stm32g4xx.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_rcc_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_flash_ramfunc.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_gpio.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_exti.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_dma_ex.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_pwr.c
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_cortex.c
)
You can see that instead of navigating to the Drivers/STM32G4xx_HAL_Driver/ directory
that is autogenerated for every project, we instead navigate to the shared HAL driver library
in lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/.
To use this new CMakeLists.txt file instead of the autogenerated one, simply replace the following line in the top-level CMakeLists.txt:
add_subdirectory(cmake/stm32cubemx)
with
add_subdirectory(cmake/stm32cubemx_extern)
Keep in mind that whenever you generate code from CubeMX which requires a new HAL driver file,
you will need to manually add that file to the cmake/stm32cubemx_extern/CMakeLists.txt file.
For example, if you enable the I2C peripheral in CubeMX and regenerate code, CubeMX will
generate the file stm32g4xx_hal_i2c.c. You will then need to add the following line to the
cmake/stm32cubemx_extern/CMakeLists.txt file where the other HAL driver files are listed:
${CMAKE_CURRENT_SOURCE_DIR}/../../../../lib/extern/STM32CubeG4/Drivers/STM32G4xx_HAL_Driver/Src/stm32g4xx_hal_i2c.c
TODO
We should create a script to automate this process of creating and updating the cmake/stm32cubemx_extern/CMakeLists.txt file.
Adding lib/ Dependencies
To add lib/ dependencies to a CubeMX project, add the following to CMakeLists.txt.
# Add fwlib dependency
add_subdirectory(../../lib fwlib)
# Add linked libraries
target_link_libraries(${CMAKE_PROJECT_NAME}
stm32cubemx
# Add user defined libraries
stm32
units
util
)
Building and Flashing
./scripts/build.sh --src <PROJECT>will build the project./scripts/flash.sh --src <PROJECT>will flash the project to the MCU connected to the STLINK
For example, if the project is named myproject and is located in /home/user/mrover-esw/src/,
the command to build would be:
./scripts/build.sh --src myproject
Note
In order to use the scripts to build and flash, ensure all */bin directories from CubeCLT are included in $PATH