-
-
Save elmot/c48f756c5443c4a003978db94392e00d to your computer and use it in GitHub Desktop.
# CMakeLists.txt for dual-core STM32H7xx MCUs and CLion IDE | |
# | |
# DISCLAIMER: Experimental version, based on undocumented assumptions how STM32CubeMX works | |
# DISCLAIMER: THIS FILE IS PROVIDED UNDER "The Unlicense" LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND | |
# | |
# Requirements: | |
# Toolchain binaries have to be in system path | |
# STM32CubeMX field "Project Manager | Code Generator | Target IDE" must be set to "STM32CubeIDE" | |
# | |
# Tested under environment: | |
# Windows 10 | |
# GCC toolchain for ARM Cortex-M V2019q4 | |
# STM32CubeMX V6.2.1 | |
# STM32CubeH7 Firmware Package V1.9.0 | |
# CLion 2021.2 EAP | |
# NUCLEO-H745ZI-Q MCU board | |
# STM32CubeProgrammer 2.7.0 | |
# | |
# How To Use: | |
# 1. Set up CLion according to https://www.jetbrains.com/help/clion/2020.3/embedded-overview.html#build-system | |
# 2. Create a project using STM32CubeMX for dual-core STM32H7xx MCU, set "Target IDE" as STM32CubeIDE, and click GENERATE CODE | |
# 3. Place this file into the project root folder | |
# 4. Set relevant project name as 'project' clause 1st argument | |
# 5. Open the project root folder as CLion project "File | Open..." | |
# 6. Set the real path of STM32_Programmer_CLI.exe to STM32_PROGRAMMER_PATH variable | |
# 7. Configure run configurations for both cores | |
# | |
# This file contains two additional custom targets: | |
# a. ${PROJECT_NAME}_ALL - builds two .elf files for both cores | |
# b. ${PROJECT_NAME}_FLASH - flashes both .elf files into MCU flash memory | |
# | |
# Written by ilia.motornyi[%]jetbrains.com | |
# | |
cmake_minimum_required(VERSION 3.20) | |
# Cross compilers and tools | |
set(CMAKE_SYSTEM_NAME Generic) | |
set(CMAKE_SYSTEM_VERSION 1) | |
set(CMAKE_C_COMPILER arm-none-eabi-gcc) | |
set(CMAKE_CXX_COMPILER arm-none-eabi-g++) | |
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc) | |
set(CMAKE_AR arm-none-eabi-ar) | |
set(CMAKE_OBJCOPY arm-none-eabi-objcopy) | |
set(CMAKE_OBJDUMP arm-none-eabi-objdump) | |
set(SIZE arm-none-eabi-size) | |
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) | |
# Project settings. | |
project(h7-single-cmake #[[TODO set reasonable project name]] C CXX ASM) | |
# Common compile settings | |
# Language standard | |
set(CMAKE_CXX_STANDARD 17) | |
set(CMAKE_C_STANDARD 11) | |
# Generic compiler settings | |
add_compile_options(-mthumb -mthumb-interwork) | |
add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0) | |
add_link_options(-mthumb -mthumb-interwork) | |
add_link_options(-Wl,-gc-sections,--print-memory-usage) | |
# Build types | |
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") | |
message(STATUS "Maximum optimization for speed") | |
add_compile_options(-Ofast) | |
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo") | |
message(STATUS "Maximum optimization for speed, debug info included") | |
add_compile_options(-Ofast -g) | |
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel") | |
message(STATUS "Maximum optimization for size") | |
add_compile_options(-Os) | |
else () | |
message(STATUS "Minimal optimization, debug info included") | |
add_compile_definitions(DEBUG) | |
add_compile_options(-Og -g3) | |
endif () | |
# Enable hardware FPU | |
add_compile_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16) | |
add_link_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16) | |
add_compile_definitions(ARM_MATH_CM4;ARM_MATH_MATRIX_CHECK;ARM_MATH_ROUNDING) | |
# Uncomment to mitigate c++17 register variable warnings | |
#add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Wno-register>) | |
# End of common part | |
# Detect linker scripts. Priorities: *_USER.ld, if not found *_FLASH.ld, if not found first *.ld | |
foreach (KRNL CM4 CM7) | |
file(GLOB LINKER_SCRIPTS "${KRNL}/*_USER.ld") | |
if (NOT LINKER_SCRIPTS) | |
file(GLOB LINKER_SCRIPTS "${KRNL}/*_FLASH.ld") | |
if (NOT LINKER_SCRIPTS) | |
file(GLOB LINKER_SCRIPTS "${KRNL}/*.ld") | |
endif () | |
endif () | |
list(GET LINKER_SCRIPTS 0 LINKER_SCRIPT_${KRNL}) | |
message(STATUS "Detected Linker Script for ${KRNL}: ${LINKER_SCRIPT_${KRNL}}") | |
endforeach () | |
# Kernel-specific sources | |
# Cortex-M4 | |
file(GLOB_RECURSE CM4_SRC "CM4/*.*" "Common/*.*") | |
add_executable(${PROJECT_NAME}_CM4.elf ${LINKER_SCRIPT_CM4} ${CM4_SRC}) | |
# Cortex-M7 | |
file(GLOB_RECURSE CM7_SRC "CM7/*.*" "Common/*.*") | |
add_executable(${PROJECT_NAME}_CM7.elf ${LINKER_SCRIPT_CM7} ${CM7_SRC}) | |
# Kernel-specific build settings | |
target_compile_options(${PROJECT_NAME}_CM4.elf PRIVATE -mcpu=cortex-m4) | |
target_compile_options(${PROJECT_NAME}_CM7.elf PRIVATE -mcpu=cortex-m7) | |
target_link_options(${PROJECT_NAME}_CM4.elf PRIVATE -Wl,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}_CM4.map -mcpu=cortex-m4 -T ${LINKER_SCRIPT_CM4}) | |
target_link_options(${PROJECT_NAME}_CM7.elf PRIVATE -Wl,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}_CM7.map -mcpu=cortex-m7 -T ${LINKER_SCRIPT_CM7}) | |
# Custom commands to build .hex files | |
foreach (KRNL CM4 CM7) | |
set(HEX_NAME ${PROJECT_NAME}_${KRNL}.hex) | |
set(HEX_FILE ${PROJECT_BINARY_DIR}/${HEX_NAME}) | |
add_custom_command(TARGET ${PROJECT_NAME}_${KRNL}.elf POST_BUILD | |
COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}_${KRNL}.elf> ${HEX_FILE} | |
BYPRODUCTS ${HEX_FILE} | |
COMMENT "Building ${HEX_NAME}") | |
endforeach () | |
# Read kernel-specific header paths, defines, and sources from ".mxproject" | |
file(STRINGS .mxproject LINES) | |
foreach (LINE ${LINES}) | |
if (LINE MATCHES "\\[Cortex(M4|M7):(PreviousUsedCubeIDEFiles|PreviousLibFiles)\\]") #Detect relevant group | |
set(CUBE_PRJ_GROUP "C${CMAKE_MATCH_1}") | |
elseif (LINE MATCHES "^\\[.*\\]$") #Detect non-relevant groups | |
unset(CUBE_PRJ_GROUP) | |
elseif (CUBE_PRJ_GROUP) | |
if (LINE MATCHES "^\\s*CDefines=\\s*(.*)") #Detect defines | |
target_compile_definitions(${PROJECT_NAME}_${CUBE_PRJ_GROUP}.elf PRIVATE ${CMAKE_MATCH_1}) | |
elseif (LINE MATCHES "^\\s*HeaderPath=\\s*(.*)\\s*") #Detect header paths | |
string(REGEX MATCHALL "[^;]+" INCL_LIST "${CMAKE_MATCH_1}") | |
target_include_directories(${PROJECT_NAME}_${CUBE_PRJ_GROUP}.elf PRIVATE ${INCL_LIST}) | |
elseif (LINE MATCHES "^\\s*LibFiles=\\s*(.*)\\s*") #Detect library sources | |
string(REGEX MATCHALL "[^;]+" SRC_LIST "${CMAKE_MATCH_1}") | |
foreach (SRC_FILE ${SRC_LIST}) | |
if (EXISTS "${CMAKE_SOURCE_DIR}/${SRC_FILE}") | |
target_sources(${PROJECT_NAME}_${CUBE_PRJ_GROUP}.elf PRIVATE ${SRC_FILE}) | |
endif () | |
endforeach () | |
endif () | |
endif () | |
endforeach () | |
add_custom_target(${PROJECT_NAME}_ALL | |
DEPENDS ${PROJECT_NAME}_CM4.elf ${PROJECT_NAME}_CM7.elf | |
COMMENT "Build both M4 and M7 parts" | |
) | |
#TODO set actual STM32_Programmer_CLI path | |
find_program(STM32_PROGRAMMER_PATH "C:/Program Files/STM32CubeIDE_1.6.1/STM32CubeIDE/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.win32_1.6.0.202101291314/tools/bin/STM32_Programmer_CLI.exe") | |
add_custom_target(${PROJECT_NAME}_FLASH | |
${STM32_PROGRAMMER_PATH} -c port=swd shared -d $<TARGET_FILE:${PROJECT_NAME}_CM7.elf> -d $<TARGET_FILE:${PROJECT_NAME}_CM4.elf> -rst | |
COMMENT "Flash both M4 and M7 parts" | |
DEPENDS ${PROJECT_NAME}_ALL | |
) |
Thanks , helped me so much cross-compiling MIPS
@Vladimir-pa
It looks like this template is a bit overcomplicated and tied to STM32CubeMX
Probably this one is more suitable https://gist.github.com/elmot/3b4f0e9f8b23864fdf8bb509c329d051
Hi,
Thanks for your sharing, but I got a problem when reload the Cmake project on Ubuntu
"CMake Error at CMakeLists.txt:88 (list): list GET given empty list"
so how to solve this problem
@Qylann, please make sure if STM32CubeMX field Project Manager | Code Generator | Target IDE is set to "STM32CubeIDE"
Hi @elmot, sorry for contacting you this way but could you please look at https://youtrack.jetbrains.com/issue/CPP-25472
It's a nasty bug which causes the development to be a pain in CLion (given we have many different SOC we'll have files with the same names)
I'm not asking even for a full solution but at least a context window which will allow us to choose from the declaration (it's already implemented in go to source/header).
@Vladimir-pa, yeah, nasty bug, I know... Why don't you vote it up?
It’s been around for a while
Its a duplicate of https://youtrack.jetbrains.com/issue/CPP-8264
Which is upvoted an commented but still nothing was done since it was posted 6 years ago :(
We are a relatively small team of 8 developers in Intel. I’ve worked hard to migrate the team to clion and now we’ve found this frustrating bug :(
Could you please check it out or forward it to some one who can ?
Thanks!
@elmot Thanks a lot!!! Really nice work! it helps me massively with my master's thesis.
If you did build the project in STM32IDE before, and do not want to clean its build files, change your CMakeLists around the add_exectuable lines like this:
# Kernel-specific sources
# Cortex-M4
file(GLOB_RECURSE CM4_SRC "CM4/*.*" "Common/*.*")
list(FILTER CM4_SRC EXCLUDE REGEX "CM4/Debug/.*$")
list(FILTER CM4_SRC EXCLUDE REGEX "CM4/Release/.*$")
add_executable(${PROJECT_NAME}_CM4.elf ${LINKER_SCRIPT_CM4} ${CM4_SRC})
# Cortex-M7
file(GLOB_RECURSE CM7_SRC "CM7/*.*" "Common/*.*")
list(FILTER CM7_SRC EXCLUDE REGEX "CM7/Debug/.*$")
list(FILTER CM7_SRC EXCLUDE REGEX "CM7/Release/.*$")
add_executable(${PROJECT_NAME}_CM7.elf ${LINKER_SCRIPT_CM7} ${CM7_SRC})
Without this change, I got a lot of errors about duplicate definitions etc.
I noticed that your compile option is -mfpu=fpv4-sp-d16, which does work for the M4 core, but the M7 core has fpv5-sp-d16.
Thanks for sharing! It helped me a lot!