0 预备环境

1.正常使用gcc的环境编译可以运行

2.STM32CubeMX可以生成 SW4STM32

image-20230416104153221

注意:一定要是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文件夹

image-20230416104706430

打开ARMCLANG文件夹

image-20230416104745716

打开里面的bin目录,并复制其地址

image-20230416104850085

在系统环境变量中配置

打开【此电脑】→右键【属性】→【高级系统设置】→【环境变量】

在path中添加刚才的地址

image-20230416105105904

2 使用CubeMX新建工程

此处省略-----

只需要在最后的Toolchain / IDE中选择SW4STM32即可

3 使用Clion打开,修改CMakeLists.txt

这里会让你选择board,选择下图所示的这个(如果后面烧录出错的话,里面可能需要更改)【如果是F4则选择f4对应的】

image-20230416105603944

打开CMakeLists.txt文件

image-20230416105823498

这一部分是CMakeLists.txt默认生成的,这里需要和你自己的保持一致,所以复制粘贴替换的时候,要从这一部分之下开始,把这一部分之下的内容全部替换成下面的程序

3.1 STM32F1系列替换文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#*************************************************************
# 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系列替换文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#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 替换文件需要注意的事项

根据自己项目的不同需要更改的地方

image-20230416110210966 image-20230416110246331 image-20230416112227865

4 使用CubeMX生成MDK文件

打开CubeMX,如果你之前的关了,那么从下面这里进入

image-20230416110437698

将SW4STM32换成MDK,然后生成

image-20230416110646289

Keil打开生成的工程,并进行编译(这里编译环境要看一下,是不是6.**以上的,如果使用AC5是不行的)

image-20230416110849413

编译运行一下,然后就可以关掉Keil了

5 Clion编译运行测试

重新加载一下CMakeLists

image-20230416111311932 image-20230416111354506

如果这里没有出现锤子,那么就进去更换一下文件

image-20230416111029278

image-20230416111103861

打开后,点一下,它会自动让你选择正确的,默认的是带.elf的,这里就是选一个不带.elf的

image-20230416111050867

点击锤子开编译

image-20230416111440107

点击三角,进行烧录运行

image-20230416111652135

如果出现错误,需要去找一下st_nucleo_f103rb.cfg的位置,并打开

image-20230416111850366

image-20230416111742908

再次烧录就可以了