0 预备环境
1.正常使用gcc的环境编译可以运行
2.STM32CubeMX可以生成 SW4STM32
注意:一定要是SW4STM32 ,不然后期在Clion中无法进行编译
SW4STM32 在新版本中已经取消,这里提供一个老的版本
链接:https://pan.baidu.com/s/1NPl9mFzq8jIvHnfeq4cPZg?pwd=vpck
提取码:vpck
3.这里使用的是stlink烧录的
4.参考视频:https://www.bilibili.com/video/BV1z44y1t7Lg/?share_source=copy_web&vd_source=08ffec12a130bb99e9aac8670b5b9c2f
5.上面视频的资料:https://share.weiyun.com/KdkTFRnp
1 配置ARMCLANG环境
Keil_v5的安装路径,进入ARM文件夹
打开ARMCLANG文件夹
打开里面的bin目录,并复制其地址
在系统环境变量中配置
打开【此电脑】→右键【属性】→【高级系统设置】→【环境变量】
在path中添加刚才的地址
2 使用CubeMX新建工程
此处省略-----
只需要在最后的Toolchain / IDE中选择SW4STM32即可
3 使用Clion打开,修改CMakeLists.txt
这里会让你选择board,选择下图所示的这个(如果后面烧录出错的话,里面可能需要更改)【如果是F4则选择f4对应的】
打开CMakeLists.txt文件
这一部分是CMakeLists.txt默认生成的,这里需要和你自己的保持一致,所以复制粘贴替换的时候,要从这一部分之下开始,把这一部分之下的内容全部替换成下面的程序
3.1 STM32F1系列替换文件
#*************************************************************
# 1. 设定项目名称
# 需要给定 PROJECT_NAME 的值,必须与项目名称一致,否则 MDK 生成 *.sct 时路径不对
set(PROJECT_NAME demo)
# 2. 设定芯片类型
# 设定芯片类型,必须正确以 -mcpu 的参数规则命名,后边的编译参数会调用这个值
set(CMAKE_SYSTEM_PROCESSOR Cortex-M3)
############################################################
# 1. 指定编译器和链接器,避免使用默认的 gcc
############################################################
# 设置编译器 C 的编译器
set(CMAKE_C_COMPILER armclang.exe)
set(CMAKE_C_COMPILER_WORKS TRUE)
# 即便用不到C++ 的编译器,还是要显示说明的,否则报错
set(CMAKE_CXX_COMPILER armclang.exe)
set(CMAKE_CXX_COMPILER_WORKS TRUE)
#设置 ASM 的编译器(不设置配合 -masm=auto 使用)
set(CMAKE_ASM_COMPILER armclang.exe)
#set(CMAKE_ASM_COMPILER armasm.exe) # 指明 ASM 编译器,配合 第二种 CMAKE_ASM_FLAGS_INIT 方式使用
set(CMAKE_ASM_COMPILER_WORKS TRUE)
#设置链接器
set(CMAKE_C_LINK_EXECUTABLE armlink.exe)
set(CMAKE_ASM_LINK_EXECUTABLE armlink.exe)
set(CMAKE_CXX_LINK_EXECUTABLE armlink.exe)
#*******************************************************************************************#
# 2. 获取芯片地址描述信息
# 获取当前 MCU 的 section 描述,及存储空间和起始地址的描述(注意:需要先用 keil 打开编译一下当前项目才能生成)
# 设置Sections脚本路径,CubeMX生成 MDK 后先编译一下,就会在MDK-ARM 目录下生成工程名命名的文件夹
# 在那个目录里会生成以项目名命名的sct文件。 由于在本地调用,不需要加 global 全局变量标记,更简洁
set(SECTIONS_SCRIPT_PATH ${CMAKE_HOME_DIRECTORY}/MDK-ARM/${PROJECT_NAME}/${PROJECT_NAME}.sct)
#********************************************************************************************#
# 3. 设置与芯片对应的 --target 编译选项
# 设置编译时默认参数片段,这些参数参见 MDK 中的配置,注意:Target 分页中要选 6.12 的 ARM 编译器,并抄各分页的 --target 配置
set(C_TARGET_FLAG --target=arm-arm-none-eabi) # MDK 的 link 分页中的配置
set(ASM_TARGET_FLAG --target=arm-arm-none-eabi) # MDK 的 link 分页中的配置(不支持显示指定 ASM 编译器的方式)
set(LINKER_TARGET_FLAG --cpu=${CMAKE_SYSTEM_PROCESSOR}) # MDK 的 link 分页中的配置
#********************************************************************************************#
# 4. 设置编译规则,这些规则变量要被外部的 CMakelistes.txt 调用,所以需要用 CACHE STRING "global" 声明为全局变量
# 编译参数,这些编译参数是从 MDK 中来的,具体的含义看 《 armclang Reference Guide 》 第一章节有详细介绍
# 需要注意的是不是 MDK 中的每个参数都要哪进来的,有些参数已经在 include 和 source 中被配置了
set(COMPILE_RULE_FLAG "-mcpu=${CMAKE_SYSTEM_PROCESSOR}")
# 设置 C 编译器选项(这里就把MDK中的 C/C++ 分页里最下边一栏的属性贴进来)
# 参数 -w 表示忽略所有警告,不然要配具体忽略哪些警告,尽管贴过来也行,但是太乱
# 优化选项 -O 有 1~3 -Os 是平衡 -Oz 是最小体积
set(CMAKE_C_FLAGS_INIT "${C_TARGET_FLAG} ${COMPILE_RULE_FLAG} \
-xc -std=c99 -fno-rtti -funsigned-char -fshort-enums -fshort-wchar \
-gdwarf-3 -Oz -ffunction-sections -w")
# 设置 C++ 编译器选项(没有用到 c++ 所以不用配置)
#set(CMAKE_CXX_FLAGS_INIT ${CMAKE_C_FLAGS_INIT})
# 设置ASM编译器选项
# 注意: -masm=auto 选项是 MDK 的 link 分页里没有的参数,需要加上 -g 是debug 用的加不加都行
set(CMAKE_ASM_FLAGS_INIT "${ASM_TARGET_FLAG} ${COMPILE_RULE_FLAG} \
-masm=auto -c -gdwarf-3 ")
# 第二种方式 配套显示执行 armasm.exe 为 ASM 编译器的方法,看上起更清晰一些
#set(CMAKE_ASM_FLAGS_INIT "${ASM_TARGET_FLAG} --cpu=Cortex-M3")
# 设置链接器选项
# 这些参数再 ARMCC 文档里么有,但 MDK 的 link 分页有,
# 使用忽略所有警告的配置时没有 --map 及其之后的内容, 这里根据需要保留了一些信息,在 demo.map 中可以看到
set(CMAKE_EXE_LINKER_FLAGS_INIT " \
${LINKER_TARGET_FLAG} \
--strict \
--scatter ${SECTIONS_SCRIPT_PATH} \
--info sizes --info totals --info unused --info veneers \
--summary_stderr \
--info summarysizes"
)
# project settings
project(demo C CXX ASM)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD 99)
#Uncomment for hardware floating point
#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)
#Uncomment for software floating point
#add_compile_options(-mfloat-abi=soft)
include_directories(App Core/Inc RT-Thread Drivers/STM32F1xx_HAL_Driver/Inc/Legacy Drivers/STM32F1xx_HAL_Driver/Inc Drivers/CMSIS/Device/ST/STM32F1xx/Include Drivers/CMSIS/Include Middlewares/Third_Party/RealThread_RTOS/include/ Middlewares/Third_Party/RealThread_RTOS/bsp/_template/cubemx_config)
add_definitions(-DUSE_HAL_DRIVER -DSTM32F103xB)
file(GLOB_RECURSE SOURCES "startup/*.*" "RT-Thread/*.*" "Middlewares/*.*" "Drivers/*.*" "Core/*.*" App)
# 对于混合兼容的环境,需要屏蔽各种编译环境引起的文件“干扰”,通过 list(REMOVE_ITEM) 命令移除不同编译环境下的干扰文件
# 在原来 CubeMX 自动生成的 gcc 编译环境目录上,附加 ARMCC 编译需要的文件
file(GLOB_RECURSE SOURCES ${SOURCES} "MDK-ARM/startup_stm32f103xb.s")
# 将由 CubeMX 生成的 GCC 编译环境中的会干扰ARMCC环境的文件,放在 EXCLUDE_SRCS 自定义列表中
file(GLOB_RECURSE EXCLUDE_SRCS
"Middlewares/Third_Party/RealThread_RTOS/libcpu/arm/cortex-m3/context_gcc.S"
"startup/*.*"
"Core/Src/syscalls.c"
"STM32F103C8Tx_FLASH.ld"
)
# 从源文件列表(SOURCES)中剔除干扰文件(EXCLUDE_SRCS)
list(REMOVE_ITEM SOURCES ${EXCLUDE_SRCS})
add_executable(${PROJECT_NAME} ${SOURCES} ${LINKER_SCRIPT})
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
set(ELF_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf)
# 使用 armclang 自带的 fromelf 工具,实现 elf 转 hex
set(ARMCC_fromelf fromelf.exe)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
# 相当于fromelf.exe" --i32combined --output="xxx/demo.hex" "xxx/demo.elf"
COMMAND ${ARMCC_fromelf} --i32combined --output="${HEX_FILE}" "${ELF_FILE}"
COMMENT "Building ${HEX_FILE}"
)
## 使用了 gcc 的 arm-none-eabi-objcopy 工具实现 elf 转 hex 和 bin, 跟 armclang 不是一脉
#set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
#add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
# COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}> ${HEX_FILE}
# COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}> ${BIN_FILE}
# COMMENT "Building ${HEX_FILE} Building ${BIN_FILE}")
3.2 STM332F4系列替换文件
#THIS FILE IS AUTO GENERATED FROM THE TEMPLATE! DO NOT CHANGE!
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
cmake_minimum_required(VERSION 3.24)
#*************************************************************
# 1. 设定项目名称
# 需要给定 PROJECT_NAME 的值,必须与项目名称一致,否则 MDK 生成 *.sct 时路径不对
set(PROJECT_NAME testF4)
# 2. 设定芯片类型
# 设定芯片类型,必须正确以 -mcpu 的参数规则命名,后边的编译参数会调用这个值
set(CMAKE_SYSTEM_PROCESSOR Cortex-M4)
############################################################
# 1. 指定编译器和链接器,避免使用默认的 gcc
############################################################
# 设置编译器 C 的编译器
set(CMAKE_C_COMPILER armclang.exe)
set(CMAKE_C_COMPILER_WORKS TRUE)
# 即便用不到C++ 的编译器,还是要显示说明的,否则报错
set(CMAKE_CXX_COMPILER armclang.exe)
set(CMAKE_CXX_COMPILER_WORKS TRUE)
#设置 ASM 的编译器(不设置配合 -masm=auto 使用)
set(CMAKE_ASM_COMPILER armclang.exe)
#set(CMAKE_ASM_COMPILER armasm.exe) # 指明 ASM 编译器,配合 第二种 CMAKE_ASM_FLAGS_INIT 方式使用
set(CMAKE_ASM_COMPILER_WORKS TRUE)
#设置链接器
set(CMAKE_C_LINK_EXECUTABLE armlink.exe)
set(CMAKE_ASM_LINK_EXECUTABLE armlink.exe)
set(CMAKE_CXX_LINK_EXECUTABLE armlink.exe)
#*******************************************************************************************#
# 2. 获取芯片地址描述信息
# 获取当前 MCU 的 section 描述,及存储空间和起始地址的描述(注意:需要先用 keil 打开编译一下当前项目才能生成)
# 设置Sections脚本路径,CubeMX生成 MDK 后先编译一下,就会在MDK-ARM 目录下生成工程名命名的文件夹
# 在那个目录里会生成以项目名命名的sct文件。 由于在本地调用,不需要加 global 全局变量标记,更简洁
set(SECTIONS_SCRIPT_PATH ${CMAKE_HOME_DIRECTORY}/MDK-ARM/${PROJECT_NAME}/${PROJECT_NAME}.sct)
#********************************************************************************************#
# 3. 设置与芯片对应的 --target 编译选项
# 设置编译时默认参数片段,这些参数参见 MDK 中的配置,注意:Target 分页中要选 6.12 的 ARM 编译器,并抄各分页的 --target 配置
set(C_TARGET_FLAG --target=arm-arm-none-eabi) # MDK 的 link 分页中的配置
set(ASM_TARGET_FLAG --target=arm-arm-none-eabi) # MDK 的 link 分页中的配置(不支持显示指定 ASM 编译器的方式)
set(LINKER_TARGET_FLAG --cpu=${CMAKE_SYSTEM_PROCESSOR}) # MDK 的 link 分页中的配置
#********************************************************************************************#
# 4. 设置编译规则,这些规则变量要被外部的 CMakelistes.txt 调用,所以需要用 CACHE STRING "global" 声明为全局变量
# 编译参数,这些编译参数是从 MDK 中来的,具体的含义看 《 armclang Reference Guide 》 第一章节有详细介绍
# 需要注意的是不是 MDK 中的每个参数都要哪进来的,有些参数已经在 include 和 source 中被配置了
set(COMPILE_RULE_FLAG "-mcpu=${CMAKE_SYSTEM_PROCESSOR} -mfpu=fpv4-sp-d16 -mfloat-abi=hard -c ")
# 设置 C 编译器选项(这里就把MDK中的 C/C++ 分页里最下边一栏的属性贴进来)
# 参数 -w 表示忽略所有警告,不然要配具体忽略哪些警告,尽管贴过来也行,但是太乱
# 优化选项 -O 有 1~3 -Os 是平衡 -Oz 是最小体积
set(CMAKE_C_FLAGS_INIT "${C_TARGET_FLAG} ${COMPILE_RULE_FLAG} \
-xc -std=c99 -fno-rtti -funsigned-char -fshort-enums -fshort-wchar \
-gdwarf-4 -O1 -ffunction-sections -w")
# 设置 C++ 编译器选项(没有用到 c++ 所以不用配置)
#set(CMAKE_CXX_FLAGS_INIT ${CMAKE_C_FLAGS_INIT})
# 设置ASM编译器选项
# 注意: -masm=auto 选项是 MDK 的 link 分页里没有的参数,需要加上 -g 是debug 用的加不加都行
set(CMAKE_ASM_FLAGS_INIT "${ASM_TARGET_FLAG} ${COMPILE_RULE_FLAG} \
-masm=auto -c -gdwarf-4 ")
# 第二种方式 配套显示执行 armasm.exe 为 ASM 编译器的方法,看上起更清晰一些
#set(CMAKE_ASM_FLAGS_INIT "${ASM_TARGET_FLAG} --cpu=Cortex-M3")
# 设置链接器选项
# 这些参数再 ARMCC 文档里么有,但 MDK 的 link 分页有,
# 使用忽略所有警告的配置时没有 --map 及其之后的内容, 这里根据需要保留了一些信息,在 testF4.map 中可以看到
set(CMAKE_EXE_LINKER_FLAGS_INIT " \
${LINKER_TARGET_FLAG} \
--strict \
--scatter ${SECTIONS_SCRIPT_PATH} \
--info sizes --info totals --info unused --info veneers \
--summary_stderr \
--info summarysizes"
)
# project settings
project(testF4 C CXX ASM)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_STANDARD 99)
#Uncomment for hardware floating point
#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)
#Uncomment for software floating point
#add_compile_options(-mfloat-abi=soft)
include_directories(Core/Inc Drivers/STM32F4xx_HAL_Driver/Inc Drivers/STM32F4xx_HAL_Driver/Inc/Legacy Drivers/CMSIS/Device/ST/STM32F4xx/Include Drivers/CMSIS/Include)
add_definitions(-DUSE_HAL_DRIVER -DSTM32F407xx)
file(GLOB_RECURSE SOURCES "startup/*.*" "Drivers/*.*" "Core/*.*")
# 对于混合兼容的环境,需要屏蔽各种编译环境引起的文件“干扰”,通过 list(REMOVE_ITEM) 命令移除不同编译环境下的干扰文件
# 在原来 CubeMX 自动生成的 gcc 编译环境目录上,附加 ARMCC 编译需要的文件
file(GLOB_RECURSE SOURCES ${SOURCES} "MDK-ARM/startup_stm32f407xx.s")
# 将由 CubeMX 生成的 GCC 编译环境中的会干扰ARMCC环境的文件,放在 EXCLUDE_SRCS 自定义列表中
file(GLOB_RECURSE EXCLUDE_SRCS
"Middlewares/Third_Party/RealThread_RTOS/libcpu/arm/cortex-m3/context_gcc.S"
"startup/*.*"
"Core/Src/syscalls.c"
"STM32F103C8Tx_FLASH.ld"
)
# 从源文件列表(SOURCES)中剔除干扰文件(EXCLUDE_SRCS)
list(REMOVE_ITEM SOURCES ${EXCLUDE_SRCS})
add_executable(${PROJECT_NAME} ${SOURCES} ${LINKER_SCRIPT})
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
set(ELF_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf)
# 使用 armclang 自带的 fromelf 工具,实现 elf 转 hex
set(ARMCC_fromelf fromelf.exe)
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
# 相当于fromelf.exe" --i32combined --output="xxx/testF4.hex" "xxx/testF4.elf"
COMMAND ${ARMCC_fromelf} --i32combined --output="${HEX_FILE}" "${ELF_FILE}"
COMMENT "Building ${HEX_FILE}"
)
## 使用了 gcc 的 arm-none-eabi-objcopy 工具实现 elf 转 hex 和 bin, 跟 armclang 不是一脉
#set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
#add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
# COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}> ${HEX_FILE}
# COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}> ${BIN_FILE}
# COMMENT "Building ${HEX_FILE} Building ${BIN_FILE}")
3.3 替换文件需要注意的事项
根据自己项目的不同需要更改的地方
4 使用CubeMX生成MDK文件
打开CubeMX,如果你之前的关了,那么从下面这里进入
将SW4STM32换成MDK,然后生成
Keil打开生成的工程,并进行编译(这里编译环境要看一下,是不是6.**以上的,如果使用AC5是不行的)
编译运行一下,然后就可以关掉Keil了
5 Clion编译运行测试
重新加载一下CMakeLists
如果这里没有出现锤子,那么就进去更换一下文件
打开后,点一下,它会自动让你选择正确的,默认的是带.elf的,这里就是选一个不带.elf的
点击锤子开编译
点击三角,进行烧录运行
如果出现错误,需要去找一下st_nucleo_f103rb.cfg的位置,并打开
再次烧录就可以了