CLion搭建STM32开发环境(基于野火开发板STM32F103C8T6)
硬件环境:
- STM32F103C8T6
- 野火DAP调试器
软件环境
- Windows 11(23H2)
- STM32CubeMX
- CLion2024.2.2
- MinGW(新版本CLion,捆绑了MinGW,可以省略)
- OpenOCD
- arm-none-eabi-gcc
链接
参考教程:
Clion搭建stm32开发环境(STM32F103C8T6),有这一篇就够(只愿意博君一笑!!!)_clion写单片机-CSDN博客
本次教程是针对,在开发环境中遇到的问题和解决方法,以及更细致完善的分析整个过程
一、工具安装
1.Clion(本次演示,未删除中文插件,所以安装界面为中文)
Step1:双击CLion-2024.2.2.exe 打开安装程序,点击下一步
Step2:选择安装目录,点击下一步
Step3:配置安装选项,这里建议全选,点击下一步
Step4:选择启动菜单文件夹创建快捷方式,点击安装
Step5:等待安装完成,选择稍后重启,点击完成
Step6:进入软件,使用账户激活软件(这里不提供破解方法,自行上网查找)
Step7:为软件安装中文插件,点击插件选项,安装中文插件,完成软件的安装设置
2.MinGw(踩坑过程)
之前一直都是通过MinGW-w64 - for 32 and 64 bit Windows - Browse Files at SourceForge.net下载安装的,在Files文件下载安装的免安装包,这次一看,居然没有了。于是就开始踩坑过程。
- 通过mingw-get-setup.exe,安装程序,下载安装。装完后下载组件,但是很漫长,下了一个多小时都没有安装完,速度很慢(因为要访问外网服务器,所以很慢)果断放弃了。
2.直接通过SourceForge网址下载最新的安装包,但是下载完解压后,发现文件结构和目录看不懂,也找不到bin文件夹
3.去官网Downloads - MinGW-w64下载,但是进去后发现又看不懂,找了一会儿,看到了SourceForge,点进去后看到了熟悉的页面。于是下载了一个mingw-w64-8.03.zip版本的,解压后发现依旧不对
4.继续在官网Downloads - MinGW-w64寻找答案,看到了MinGW-W64-builds下的GitHup的链接,点了进去。进去后发现好像对了(进入GitHup需要运气,当然也可以使用科学上网工具,这里不在说明,下载时可以使用多线程下载工具,速度较快,这里我使用的是IDM)
但是进去后发现不知道应该下载哪一个,这些名称都不怎么认识,于是又开始了一段查找。将其中的选择参数说明如下表:
参数分类 | 参数 | 说明 |
---|---|---|
CPU架构 | i686 | 32位系统架构 |
CPU架构 | x86_64 | 64位系统架构 |
操作系统接口协议 | win32 | 开发windows应用程序 |
操作系统接口协议 | posix | 开发Linux、Mac应用程序(可移植应用程序等) |
异常处理模型(32bit) | dwarf | 版本新,性能好,只支持32位系统,不支持64位系统 |
异常处理模型(64bit) | seh | 版本新,性能好,只支持64位系统,不支持32位系统 |
运行时库 | msvcrt | 传统上,MinGW-w64 编译器使用 MSVCRT 作为运行时库,它在所有版本的 Windows 上都可用(win10一下版本使用) |
运行时库 | ucrt | UCRT,全称Universal C Runtime(通用C运行时库),是微软为Windows平台引入的一项关键技术,旨在提供符合ISO C99、C11及POSIX标准的C语言运行时支持。自Windows 10起,UCRT作为操作系统的核心组件,为应用程序带来了更好的兼容性、稳定性和性能。(win10及其以上版本更好的选择) |
这里作为开发单片机,这里选择x68_64-14.2.0-release-posix-seh-ucrt-rt-v12-rev0.7z使用解压软件,解压到指定文件夹即可
3.arm-none-eabi-gcc
Step1:Arm官网下载arm-none-eabi-gcc编辑器,选择Zip的免安装版本
Step2:将压缩包,解压到指定文件夹,方便管理,即可
4.OpenOCD
Step1:点击网址链接,进入网站,下载最新的即可
Step2:将下载好的压缩包,解压到指定文件夹,即可。路径不要有空格和中文
5.STM32CubeMx
5.1 JAVA环境配置
Step1:打开JAVA官网,下载最新版,点击下载按钮
Step2:双击运行jre-8u421-windows-x64.exe进行安装,点击安装
Step3:勾选更改目标文件夹,点击安装,更改完成后,点击下一步
Step4:等待安装完成
5.2Cubemx下载
Step1:进入官网下载,点击下载STM32CubeMX按钮
Step2:选择Windows版本,点击下载按钮,稍后就能使用账户登录或访客模式下载软件
Step3:双击SetupSTM32CubeMX-6.12.0-Win.exe文件进行安装,点击Next
Step4:勾选相关同意事项,点击Next
Step5:更改安装路径,点击Nxet,等待安装完成,最后点击Done,完成安装
相关目录及安装路径如图
STM32Cub文件夹包含如下文件,gcc-arm、mingw64、OpenOCD
二、基础环境配置
1.添加系统环境变量
打开系统的环境变量(右击此电脑->属性->高级系统设置->环境变量),找到系统变量
中的PATH
变量,点击编辑,在当中新建
三个路径,分别是OpenOCD
、MinGW64
和arm-none-eabi-gcc
三个软件安装目录下的bin
文件夹的安装路径
重启电脑,使用CMD命令行,输入一下命令,出现版本号后,证明环境添加成果
gcc -v
arm-none-eabi-gcc -v
openocd -v
三、CLion配置、创建STM32项目
1.STM32F1库文件安装
Step1.官网下载指定芯片的库文件包,这里选择F1,鼠标单击F1位置
Step2.选择要安装的版本,这里选择安装最新版(登录后即可下载)
Step3.解压后完成下载
2.准备STM32所需要的固件库
说明:新建四个文件夹分别为Libraries、STARTUP、CMSIS、User。Libraries文件夹用于存放库函数,STARTUP文件夹用于存放启动文件,CMSIS文件夹用于存放标准接口文件,User文件夹用于存放中断函数、和主函数,以及用户自己写的显示和驱动函数。
2.1标准库文件准备
打开STM32F10x_StdPeriph_Lib_V3.6.0库文件夹,点击Libraries文件夹,在点击下面的STM32F10x_StdPeriph_Driver文件夹,找到inc、src文件两个文件复制到新建的Libraries文件夹中。
2.2coer_cm3文件准备
打开STM32F10x_StdPeriph_Lib_V3.6.0库文件夹,点击Libraries文件夹,在点击下面的CMSIS文件夹,继续点击下面的CM3文件夹,最后点击下面的CorSupport文件,将里面的core_cm3.c、core_cm3.h文件复制到,新建的CMSIS文件夹中。
2.3系统文件准备
打开STM32F10x_StdPeriph_Lib_V3.6.0库文件夹,点击Libraries文件夹,在点击下面的CMSIS文件夹,继续点击下面的CM3文件夹,接着点击下面的DevicSupport文件夹,然后点击下面的ST文件夹,最后点击下面的STM32F10x文件夹,将里面的stm32f10x.h、system_stm32f10x.c、system_stm32f10x.h文件复制到,新建的CMSIS文件夹中。
2.4启动文件准备
打开STM32F10x_StdPeriph_Lib_V3.6.0库文件夹,点击Libraries文件夹,在点击下面的CMSIS文件夹,继续点击下面的CM3文件夹,接着点击下面的DevicSupport文件夹,然后点击下面的ST文件夹,点击下面的STM32F10x文件夹,最后点击startup文件夹将里面startup_stm32f10x_md.s文件复制到,新建的STARTUP文件夹中。
名称 | 解释 |
---|---|
arm | 适用于arm编译器 |
gcc_ride7 | 适用于GCC编译器 |
iar | 适用于iar编译器 |
TrueSTDIO | 适用于TrueSTDIO编译器 |
具体选择cl还是md,需要查看数据手册,看自己芯片的存储容量,这里选择md,中等容量的启动文件。
2.5中断、stm32f10x_conf.h文件准备
打开STM32F10x_StdPeriph_Lib_V3.6.0库文件夹,点击Project文件夹,在点击下面的STM32F10x_StdPeriph_Template文件夹,将下面的stm32f10x_conf.h、stm32f10x_it.c、stm32f10x_it.h文件复制到,新建的User文件夹中。
其中stm32f10x_it.c、stm32f10x_it.h是中断的相关函数,stm32f10x_conf.h包含了所有外设的头文件,还有断言处理语句,至此完成了STM32所需要的全部固件库、和相关文件的准备工作。
3.CLion工具链配置
打开软件,打开->设置->构建、执行、部署->工具链,输入mingw的路径(新版本的CLion有绑定的mingw,可以跳过,这个步骤主要用于编辑纯c,可以跳过)
按照上一个步骤,新建一个工具链,名字叫做MinGW-STM32,其它使用捆绑默认,更改构建工具、C编译器、C++编译器,调试器的路径。其中C编译器和C++编译器使用gcc-arm-none-eabi文件夹的对应文件,将新建的MinGW-STM32工具链设置为默认。
打开构建、执行、部署->嵌入式开发,设置OpenOCD和STM32CubeMX执行文件的路径(否则使用STM32CubeMX创建项目时会报错)
设置Debug,这里工具链选择新建的MinGW-STM32,更改名称为Debug-STM32,生成器选择MinGW Makefiles,其它保持默认
4.CubeMX生成STM32项目
打开文件->新建->项目->嵌入式->STM32CubeMX,设置文件路径
项目创建完成后,点击通过STM32CubeMX打开
进去STM32CubeMX后,依次点击File->New Project,然后选择芯片型号,这里输入STM32F103C8T6,然后双击被框住的地方,进去芯片设置界面。
这里使用标准库开发,不需要进行任何设置(STM32CubeMX生成的相关代码均为HAL库的文件)点击Project Manager 设置工程名称,以及保存路径。IDE选择STM32CubeIDE(这里只针对新版本,老版本自行网上查找),设置完成后点右上角的GENERATE CODE,生成工程。
[!WARNING]
这里路径必须和CLion路径、名称必须完全一致,否则生成的工程不能覆盖原有工程,导致出错。
生成的项目如下图:
这里我们是标准库开发,需要删除Core、Drivers文件夹
删除Core、Drivers文件后,导入之前整理准备的固件库的四个文件夹
在User文件下,新建main.c和main.h文件,这个时候发现软件报错了,因为这个工程是基于CMakeLists,我们需要更改这个文件的相关设置。
打开CMakeLists.txt文件,进行如下设置,最后点击右边的从新加载按钮,这样错误就消除了,并添加标准库和芯片板子的宏定义
USE_STDPERIPH_DRIVER //标准库
STM32F10X_MD //板子芯片型号
add_definitions(-DDEBUG -DUSE_STDPERIPH_DRIVER -DSTM32F10X_MD) //CMakeLists.txt 宏定义部分,可以直接复制使用
点击编译,发现新的报错,内存地址 [r1]
处尝试进行字节存储,操作失败,这是因为core_cm3.c文件的相关代码,与CLion中要求不同,需要进行更改,我直接把更换代码的链接贴出来,直接更换即可。
更改完成后,又发现了新的问题,提示arm-none-eabi-gcc相关问题,期初认为是版本太高,或者没有设置环境变量,但是经过一番排除后发现都没有问题,于是点击报错链接,发现是STM32F103C8TX——FLASH.ld文件的某个位置报错。
[!IMPORTANT]
链接脚本文件:用于指导编译器如何组织生成的代码和数据,以及如何在微控制器的存储器中分配空间。它是在使用GNU工具链(如GCC编译器)进行STM32F103C8Tx微控制器的裸机编程时使用的一个重要文件。
于是各种开始在网上,查资料,试图解决问题,但是查询无果后,既然问题出在这个链接文件上,就仔细分析这个链接文件,然后代码注释的后面发现了这样一段注释。意思就是说“READONLY
” 关键字仅在 GCC11 及更高版本中受支持,如果使用 GCC10 或更早版本,请将其删除。
然后备份了一下工程,就试着删除了一下“READONLY
” 这个关键字,然后果然,编译就通过了,可以看到以及成功的生成了.bin和.hex文件,证明编译已经通过了。
[!CAUTION]
复盘原因时,发现了arm-none-eabi-gcc版本是10.3.1的,所以编译时链接脚本文件会报错,因为识别不了“
READONLY
” 这个关键字,版本不够高。但是之前配置时,也没有出现过这种情况。所以还得分析根本原因,于是我找到了之前配置成功的项目,对比了一下有了重大发现,贴图如下:
不难发现,两者有很大的不同,老版没有“
READONLY
” 关键字,还有很多语句和写法上也相差很大。那么造成差异的原因是什么,这个链接文件是由STM32CubeMX直接生成的,不难猜测是版本差异,之前的工程都是用老版本生成的链接文件,这一次使用的是最新版的STM32CubeMX生成的版本为6.12,那么也就是说,后面使用6.12及其以上的版本,如果GCC版本不在11以上,都要删除“READONLY
” 这个关键字。如果不想麻烦,这里也提供原始版本的链接文件的相关代码,可以复制直接使用。
/* ****************************************************************************** ** ** File : LinkerScript.ld ** ** Author : Auto-generated by System Workbench for STM32 ** ** Abstract : Linker script for STM32F103C8Tx series ** 64Kbytes FLASH and 20Kbytes RAM ** ** Set heap size, stack size and stack location according ** to application requirements. ** ** Set memory bank area and size if external memory is used. ** ** Target : STMicroelectronics STM32 ** ** Distribution: The file is distributed “as is,” without any warranty ** of any kind. ** ***************************************************************************** ** @attention ** ** <h2><center>© COPYRIGHT(c) 2019 STMicroelectronics</center></h2> ** ** Redistribution and use in src and binary forms, with or without modification, ** are permitted provided that the following conditions are met: ** 1. Redistributions of src code must retain the above copyright notice, ** this list of conditions and the following disclaimer. ** 2. Redistributions in binary form must reproduce the above copyright notice, ** this list of conditions and the following disclaimer in the documentation ** and/or other materials provided with the distribution. ** 3. Neither the name of STMicroelectronics nor the names of its contributors ** may be used to endorse or promote products derived from this software ** without specific prior written permission. ** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** ***************************************************************************** */ /* Entry Point */ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = 0x20005000; /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x200; /* required amount of heap */ _Min_Stack_Size = 0x400; /* required amount of stack */ /* Specify the memory areas */ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K } /* Define output sections */ SECTIONS { /* The startup code goes first into FLASH */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH /* The program code and other data goes into FLASH */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH /* Constant data goes into FLASH */ .rodata : { . = ALIGN(4); *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); } >FLASH .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH .ARM : { __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; } >FLASH .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); } >FLASH .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); } >FLASH .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); } >FLASH /* used by the startup to initialize data */ _sidata = LOADADDR(.data); /* Initialized data sections goes into RAM, load LMA copy after code */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH /* Uninitialized data section */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss secion */ _sbss = .; /* define a global symbol at bss start */ __bss_start__ = _sbss; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; } >RAM /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM /* Remove information from the standard libraries */ /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } .ARM.attributes 0 : { *(.ARM.attributes) } } ————————————————
5.烧录配置
5.1添加烧录配置(OpenOCD)
点击,编辑配置选项
在弹出的对话框,中点击左上角+,选择添加配置。找到OpenOCD下载并运行选项,添加该选项
点击面版配置文件选择后面的辅助,弹出的对话框,选择stm32f103c8_blue_pill.cfg文件,点击复制到项目并使用按钮
5.2配置cfg文件
打开刚才的stm32f103c8_blue_pill.cfg,将下面代码,复制到下面
# SPDX-License-Identifier: GPL-2.0-or-later
# STM32F103C8 "Blue Pill"
adapter driver cmsis-dap
#source [find interface/cmsis-dap.cfg]
transport select swd
# 0x10000 = 64K Flash Size
set FLASH_SIZE 0x20000
source [find target/stm32f1x.cfg]
# download speed = 10MHz
adapter speed 10000
前两行设置了仿真器的类型和接口,下面几行指定了Flash大小、芯片类型、下载速度等,如果这些参数不一样可以根据实际情况更改以下文件
如果对自己的芯片不知道怎么设置,可以参考OpenOCD自带的一系列配置文件,路径在OpenOCD安装目录的share\openocd\scripts
下:
只需要关注这几个目录:
- board:板卡配置,各种官方板卡
- interface:仿真器类型配置,比如ST-Link、CMSIS-DAP等都在里面
- target:芯片类型配置,STM32F1xx、STM32L0XX等等都在里面
5.3编写测试程序
新建main.c、main.h文件,并编写简单点灯测试程序
5.4下载烧录
6.调试配置
6.1添加GDB服务器
点击,编辑配置选项,在弹出的对话框,中点击左上角+,选择添加配置。找到嵌入式GDB服务器选项,添加该选项
6.2配置GDB服务器
按下图配置
target remote(远程目标):localhost:3333(其中3333为OpenOCD端口号),据情况自行设置,默认为3333
GDB服务器:OpenOCD.exe文件的路径地址
GDB服务器实参:第一个是打开对应仿真器的.cfg文件,第二个是打开对应的芯片板子型号的.cfg文件(据情况自行设置,本套设置,适用于STM32F103C8T6野火开发板)
6.3外设文件添加
进入意法半导体-STMicroelectronics官网,搜索stm32f1svd(具体情况适自己而定)
下载并进行,解压
打开CLion,选择正在调试的程序,点击外设,点击加载SVD文件
选择加载文件的路径,和具体的芯片型号,点击确定
选择要显示的外设,这里按需自行设置
配置好后,选择外设就能观察到具体寄存器值
完结:
本教程从CLion搭建基础开发环境,到代码的编辑,项目的创建,从编辑,编译,到下载烧录,再到调试,全方位的展示了整个流程。后面还会涉及到串口中的输出重定向 printf,那又是后话了,就暂且写这么多。