Skip to content

Instantly share code, notes, and snippets.

@qiayuanl
Last active June 19, 2023 14:35
Show Gist options
  • Save qiayuanl/9cea0e3e588d5d12735202fc1c1cdd6d to your computer and use it in GitHub Desktop.
Save qiayuanl/9cea0e3e588d5d12735202fc1c1cdd6d to your computer and use it in GitHub Desktop.
cmake_minimum_required(VERSION 3.24)
project(lalala C CXX ASM)
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)
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_options(-Og -g)
add_definitions(-DESC_DEBUG) # ESC Debug
endif ()
# Enable hardware FPU
add_compile_definitions(ARM_MATH_MATRIX_CHECK;ARM_MATH_ROUNDING)
add_compile_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
add_link_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
include(Stm32)
include(boards/CMakeLists.txt)
#Tree of boards:
#├── CMakeLists.txt
#├── foc
#│   ├── Core
#│   ├── Drivers
#│   ├── foc.ioc
#│   └── STM32F401RCTX_FLASH.ld
#└── imu
#│  ├── Core
#│   ├── Drivers
#│   ├── imu.ioc
#│   └── STM32F401RCTX_FLASH.ld
# in boards/CMakeList.txt:
add_subdirectory(foc)
stm32_create_cube_lib(imu cortex-m4)
######################################
#Tree of applications/imu:
#├── CMakeLists.txt
#├── ecat_app.c
#├── ecat_app.h
#├── main.c
#├── pid.c
#└── pid.h
# applications/imu/CMakeList.txt:
include_directories(./)
file(GLOB_RECURSE SOURCES_APP "./*.*")
add_executable(imu.elf ${SOURCES_APP} ${board_imu_SYS})
target_link_libraries(imu.elf board_imu)
stm32_create_hex(imu)
MACRO(stm32_create_cube_lib BOARD_NAME CPU_TYPE)
SET(BOARD_TARGET_NAME "board_${BOARD_NAME}")
SET(BOARD_TARGET_DIR "${CMAKE_CURRENT_LIST_DIR}/${BOARD_NAME}")
message(STATUS "Create board target: board_${BOARD_NAME}")
# Detect linker scripts. Priorities: *_USER.ld, if not found *_FLASH.ld, if not found first *.ld
file(GLOB LINKER_SCRIPTS "${BOARD_TARGET_DIR}/*_USER.ld")
if (NOT LINKER_SCRIPTS)
file(GLOB LINKER_SCRIPTS "${BOARD_TARGET_DIR}/*_FLASH.ld")
if (NOT LINKER_SCRIPTS)
file(GLOB LINKER_SCRIPTS "${BOARD_TARGET_DIR}/*.ld")
endif ()
endif ()
list(GET LINKER_SCRIPTS 0 LINKER_SCRIPT_${BOARD_TARGET_NAME})
message(STATUS "Detected Linker Script for ${BOARD_TARGET_NAME}: ${LINKER_SCRIPT_${BOARD_TARGET_NAME}}")
file(GLOB_RECURSE ${BOARD_TARGET_NAME}_SOURCES "${BOARD_TARGET_DIR}/Core/*.*" "${BOARD_TARGET_DIR}/Drivers/*.*")
add_library(${BOARD_TARGET_NAME} STATIC ${${BOARD_TARGET_NAME}_SOURCES})
file(GLOB_RECURSE ${BOARD_TARGET_NAME}_SYS "${BOARD_TARGET_DIR}/Core/Src/syscalls.c" "${BOARD_TARGET_DIR}/Core/Src/sysmem.c")
# Kernel-specific build settings
target_compile_options(${BOARD_TARGET_NAME} PUBLIC -mcpu=${CPU_TYPE})
target_link_options(${BOARD_TARGET_NAME} PUBLIC
-Wl,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map -mcpu=${CPU_TYPE} -T ${LINKER_SCRIPT_${BOARD_TARGET_NAME}})
# Read kernel-specific header paths, defines, and sources from ".mxproject"
file(STRINGS ${BOARD_TARGET_DIR}/.mxproject LINES)
foreach (LINE ${LINES})
if (LINE MATCHES "\\[(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(${BOARD_TARGET_NAME} PUBLIC ${CMAKE_MATCH_1})
elseif (LINE MATCHES "^\\s*HeaderPath=\\s*(.*)\\s*") #Detect header paths
string(REGEX MATCHALL "[^;]+" INCL_LIST "${CMAKE_MATCH_1}")
list(TRANSFORM INCL_LIST PREPEND ${BOARD_TARGET_DIR}/)
target_include_directories(${BOARD_TARGET_NAME} PUBLIC ${INCL_LIST})
elseif (LINE MATCHES "^\\s*LibFiles=\\s*(.*)\\s*") #Detect library sources
string(REGEX MATCHALL "[^;]+" SRC_LIST "${CMAKE_MATCH_1}")
list(TRANSFORM SRC_LIST PREPEND ${BOARD_TARGET_DIR}/)
foreach (SRC_FILE ${SRC_LIST})
if (EXISTS "${SRC_FILE}")
target_sources(${BOARD_TARGET_NAME} PRIVATE ${SRC_FILE})
endif ()
endforeach ()
endif ()
endif ()
endforeach ()
ENDMACRO()
function(stm32_create_hex NAME)
set(HEX_FILE ${PROJECT_BINARY_DIR}/${NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${NAME}.bin)
add_custom_command(TARGET ${NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${NAME}.elf> ${HEX_FILE}
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${NAME}.elf> ${BIN_FILE}
COMMENT " Building ${HEX_FILE} Building ${BIN_FILE}")
endfunction()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment