前期准备

  1. 一个Keil工程

  2. 根据主机平台和目标平台选择并安装交叉编译工具链,目标平台为ARM的直接官网下载:Arm GNU 工具链下载 – Arm Developer。如本文选择

  3. 安装CMake、Ninja(非必须,因为MinGW支持Unix make)、CLion(或VSCode等其他支持CMake工程的IDE)

创建CMake工程

可以直接将原工程复制一份,或者新建一份并将源文件按照Keil分组(其实爱咋分咋分),在工程根目录新建CMakeLists.txt文件,内容如下所示:

# 设置工程依赖的最低CMake版本
cmake_minimum_required(VERSION 3.20)
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(GD32F30xTest C CXX ASM)
# 设置C标准为C11
set(CMAKE_C_STANDARD 11)
# 设置C++标准为C++11
set(CMAKE_CXX_STANDARD 11)

# 不要链接标准C/C++库
add_compile_options(-nostdlib)
add_link_options(-nostdlib)

# 添加硬浮点选项 (如果目标平台有FPU)
add_compile_definitions(ARM_MATH_CM4;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)

# 添加软浮点选项 (如果目标平台没有FPU)
#add_compile_options(-mfloat-abi=soft)

# 指定CPU内核架构、指令集和其他编译选项
add_compile_options(-mcpu=cortex-m4 -mthumb -mthumb-interwork)
add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0)

#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
# uncomment to mitigate c++17 absolute addresses warnings
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")

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)
endif ()

add_definitions(
        -D_RTE_
        -DGD32F30X_CL
        -DUSE_STDPERIPH_DRIVER
        -DUSE_USBFS
        -DUSE_FATFS
        -D__FPU_PRESENT=1
        -D__FPU_USED=1
        -DARM_MATH_CM4
        # 添加其他宏定义
)

include_directories(
        "Firmware/CMSIS"
        "Firmware/CMSIS/GD/GD32F30x/Include"
        "Firmware/GD32F30x_standard_peripheral/Include"
        # 添加其他include路径
)

file(GLOB_RECURSE SOURCES
        "Firmware/CMSIS/*.h"
        "Firmware/CMSIS/GD/GD32F30x/Include/*.h"
        "Firmware/CMSIS/GD/GD32F30x/Source/system_gd32f30x.c"
        "Firmware/CMSIS/GD/GD32F30x/Source/GCC/startup_gd32f30x_cl.s"
        "Firmware/GD32F30x_standard_peripheral/Include/*.h"
        "Firmware/GD32F30x_standard_peripheral/Source/*.c"
        "main.c"
        # 添加其他源文件路径
)

# 设置链接脚本文件
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/gd32f30x_flash.ld)

# 设置链接器选项
add_link_options(-Wl,-gc-sections,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map)
add_link_options(-mcpu=cortex-m4 -mthumb -mthumb-interwork)
add_link_options(-T ${LINKER_SCRIPT})

add_link_options(-specs=nano.specs -specs=nosys.specs -u _printf_float)

add_executable(${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT})

# 链接静态库
target_link_libraries(${PROJECT_NAME}.elf ${CMAKE_SOURCE_DIR}/EMWIN/STemWin/Lib/STemWin_CM4_wc16_ot.a)

set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)

# 生成hex文件和bin文件
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
        COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
        COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
        COMMENT "Building ${HEX_FILE}
Building ${BIN_FILE}")

根据工程实际情况及需要修改上述内容,各种编译选项和宏定义可以参考Keil中的Options for Target -> C/C++ -> Compiler control string,就能愉快地使用CMake管理和构建工程了,配合使用CLion或VSCode,体验吊打Keil这上古神器。值得一提的是,CLion(本文使用2024.3)现在直接支持设置SEGGER J-Link调试了,不再需要像之前一样使用OpenOCD了,当然,如果使用其他调试器的话,大概还是要配置OpenOCD的,不过我这里刚好都是用的J-Link。

后话

鉴于某些MCU厂商不提供适用于GCC的链接脚本和启动文件,如果不想手动从ARMCC或IAR移植过来的话,也可以直接使用ARMCC或IAR的工具链,这样还有一个好处是不会破坏原有的工程(也就是说既可以使用CMake来管理和构建,也可以使用Keil),并且不会出现因为使用不同的工具链而出现与其他人不同的问题,坏处就是ARMCC实在是太落后了。。。ARMCLANG要好点,编译速度也快点,但是一些老工程往往使用ARMCC,如果直接设置成ARMCLANG的话大概率编译不过。

CMake配置使用ARMCC或其他自定义编译器,参见:https://github.com/JetBrains/clion-custom-defined-compiler-examples

文章作者: Liccsu
本文链接:
版权声明: 本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Liccsu's blog
喜欢就支持一下吧
打赏
微信 微信