Clion STM32 开发环境配置教程
Clion STM32 开发环境配置教程
STM32 CubeMX(6.5)
下载固件库
- 若固件库还未下载,可在启动界面点击,INSTALL/REMOVE下载所需要的固件库
- 选中对应固件库,点击Install即可
Clion(2023.3.1)
- 略
MinGW
MinGW(Minimalist GNU for Windows)是一个允许你在Windows平台上使用GCC(GNU Compiler Collection)编译器的工具集合。它提供了一套完整的开源编程工具,包括C、C++、Fortran编译器和相关工具,如make等。MinGW是一个轻量级的开发环境,与传统的GNU工具链相比,它去掉了对于Windows平台不必要的部分。
MinGW的特点
- 轻量级:相比完整的Linux GNU工具链,MinGW更为精简。
- 兼容性:生成的可执行文件可以在没有MinGW环境的Windows系统上运行。
- 开源:MinGW是开源软件,免费提供。
-
下载链接Download File List - MinGW - Minimalist GNU for Windows - OSDN
-
右键单击选择Mark for Installation,勾选Basic Setup里的全部组件,点击Apply Changes下载。
-
配置环境变量,在Path里添加MinGW的bin文件夹。
-
打开命令行,输入gcc -v,验证是否安装成功
OpenOCD
OpenOCD(Open On-Chip Debugger)是一个开源项目,提供了一个调试工具,主要用于嵌入式系统的芯片和开发板。它支持多种通信接口,如JTAG和SWD(Serial Wire Debug),并且与多种调试硬件和芯片系列兼容。
OpenOCD的特点
- 多协议支持:支持JTAG, SWD等调试接口。
- 跨平台:可在Windows、Linux、macOS等操作系统上运行。
- 开源:作为一个开源项目,OpenOCD拥有活跃的社区支持。
- 广泛的兼容性:支持众多芯片制造商和调试器。
-
下载链接Download OpenOCD for Windows (gnutoolchains.com)
-
配置环境变量,在Path里添加OpenOCD的bin文件夹。
-
打开命令行,输入openocd -v,验证是否安装成功
arm-none-eabi-gcc
arm-none-eabi-gcc是 ARM 架构的交叉编译器,用于编译针对 ARM 处理器的嵌入式应用程序。这个编译器生成的代码可以运行在没有操作系统的裸机(Bare-metal)环境,或者用于运行RTOS(实时操作系统)的环境。
特点
- 交叉编译:它能在一种架构(如x86)上编译代码,生成另一种架构(如ARM)的可执行文件。
- 针对ARM架构优化:提供了对ARM架构的支持和优化。
- 广泛支持:广泛用于开发ARM基础的嵌入式系统,如STM32、LPC等微控制器。
-
下载链接Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer
-
配置环境变量,在Path里添加arm-none-eabi-gcc的bin文件夹。
-
打开命令行,输入arm-none-eabi-gcc -v,验证是否安装成功。
CMake
- 这部分默认即可
- 如果创建了多个ToolChain,选择对应STM32下的
这张图是一个IDE的设置界面截图,具体来说是CMake配置部分的截图。下面详细解释图中显示的内容:
Build type: 这里选择的构建类型是
Debug
。这意味着构建的项目将包含调试信息,通常编译器优化会被关闭或减到最小以便于调试。Toolchain: 选中的工具链是
MinGW
。MinGW是Minimalist GNU for Windows的缩写,它提供了一套允许你在Windows平台上进行本地Windows应用的GNU工具集,包括gcc编译器等。Generator: 这里使用的是默认的MinGW Makefiles。这个生成器是CMake用来控制构建过程的一系列Makefile。
CMake options: 附加给CMake的选项有:
-G "CodeBlocks - MinGW Makefiles"
:指定了CMake应该生成CodeBlocks IDE可用的Makefiles。-DCMAKE_BUILD_TYPE=Debug
:指定了构建类型为Debug。-DCMAKE_MAKE_PROGRAM=P:/mingw/x86_64-8.1.0-release-win32-sjlj-rt_v6-rev0/mingw64/bin/mingw32-make.exe
:这指定了CMake应该使用的make程序的路径。
Cache variables: 这个部分可能包含了一些额外的CMake缓存变量设置,但在截图中未展开。
Build directory: 指定了构建目录为
cmake-build-debug-mingw
,这是项目构建时所有中间文件和最终输出文件存放的地方。Build options: 这里
-j 18
表示构建过程将尝试并行编译,并使用最多18个进程。这可以显著提高大型项目的编译速度。Environment: 环境变量部分在截图中未展开,但这里可以设置影响CMake运行环境的变量。
这个设置界面允许用户配置IDE使用CMake构建项目的方式,包括构建类型、工具链、生成器选项、构建目录等。用户可以根据需要调整这些设置,以便在特定环境或平台上进行项目的构建。
嵌入式开发环境配置(Embedded Development)
- OpenOCD Location:openocd.exe
- Stm32CubeMX Location:STM32CubeMX.exe
这张图显示了集成开发环境(IDE)中的设置界面,特别是嵌入式开发的部分。下面是对界面中各个部分的详细解释:
OpenOCD Location: 这是一个指向OpenOCD可执行文件的路径。OpenOCD是一个用于嵌入式系统的开源调试工具,它支持多种通信接口和协议。在这里,它被配置为P盘中的某个目录下的
openocd.exe
。Stm32CubeMX Location: 这是STM32CubeMX工具的路径,它是一个图形化的软件配置工具,由STMicroelectronics提供,用于STM32微控制器的配置和初始化。在这里,它被配置为P盘中的
STM32CubeMX.exe
。Test Buttons: 旁边的“Test”按钮可能用于验证路径是否正确,点击它可以测试IDE是否能够成功地调用这些工具。
Embedded Development Section: 这个部分可能包含与嵌入式开发相关的其他设置,比如实时操作系统(RTOS)集成、运行目标配置和信任的位置。
这个配置界面允许开发者设置和管理与嵌入式项目开发相关的工具和环境路径。正确配置这些工具是进行嵌入式开发的重要步骤,因为它们直接关系到编译、调试和部署代码到目标硬件的能力。通过提供工具的精确位置,IDE可以为开发者提供一整套集成的开发和调试流程。
工具链配置(Toolchains)
- Toolset:MingGW的安装路径
- Bulid Tool:mingw32-make.exe
- C Complier:arm-none-eabi-gcc.exe
- C++ Complier:arm-none-eabi-g++.exe
这张图显示的是集成开发环境(IDE)中的“Toolchains”配置页面,它是用于设置编译和调试环境的地方。
在这个界面上,我们可以看到以下几个部分:
菜单列表:左侧的菜单栏列出了多个配置选项,包括插件(Plugins)、版本控制(Version Control)和构建、执行、部署(Build, Execution, Deployment)。当前选中的是“Build, Execution, Deployment”下的“Toolchains”。
工具链配置:
“MinGW”条目已被选中,这意味着正在配置MinGW工具链。
“Name”字段指定了这个工具链的名称,这里是“MinGW”。
“Toolset”字段指明了MinGW的安装路径。
“CMake”条目下的“Bundled”表明该工具链使用的CMake是预打包的版本,随IDE提供。
“Build Tool”显示了make工具的路径,这里使用的是MinGW中包含的
mingw32-make.exe
。
在软件开发中,“Build Tool” 是一个用于自动化编译代码、打包软件和管理依赖关系的程序。它允许开发者通过简单的命令来构建和测试他们的项目,而不是手动执行这些繁琐的过程。
以下是一些常见的 Build Tool 的特点和功能:
- 编译源代码:将源代码转换成可执行文件或字节码。
- 依赖管理:自动下载和管理项目所需的库和框架。
- 自动化测试:运行预定义的测试脚本来验证代码更改。
- 打包:将编译后的代码和资源文件打包成可分发的格式,如JAR、WAR或者可执行文件。
- 部署:将软件包自动部署到生产环境或测试环境。
- 清理:清除构建过程中生成的临时文件。
- 文档生成:自动从源代码注释中生成文档。
具体到这张图中的设置,“Build Tool” 显示为
P:\mingw\...\mingw32-make.exe
,这意味着用于构建过程的工具是 MinGW 版本的 make 工具。在 MinGW 或类 Unix 系统中,make
是一个经典的命令行工具,它使用 Makefile 文件中定义的指令来构建和管理项目。在IDE中配置 Build Tool 的正确路径是很重要的,因为IDE将依赖这些工具来执行构建、清理和其他相关的任务。通过集成 Build Tool,IDE能够提供一键构建和部署功能,极大地提高了开发效率。
- 编译器和调试器设置:
- “C Compiler”和“C++ Compiler”分别指定了C和C++编译器的路径。在这个配置中,使用的是
arm-none-eabi-gcc
和arm-none-eabi-g++
,它们是用于ARM架构的交叉编译器。- “Debugger”选项显示使用的是“Bundled GDB”,即随IDE一起打包的GNU调试器(GDB)。
- 版本信息:
- 每个工具后面的绿色勾选标记和版本号表示该工具已被正确配置,并显示了它的版本。
- 测试按钮:
- 工具路径旁边的“Test”按钮可以用来测试指定路径的工具是否可以正确执行。
- 确认和应用按钮:
- 窗口底部的“OK”和“Apply”按钮用于保存更改,而“Cancel”则用于放弃更改。
这种配置页面对于嵌入式开发尤为重要,因为它允许开发者指定用于不同目标平台的特定编译器和工具。通过正确配置这些工具,开发者可以在主机系统(如Windows)上开发和调试针对ARM等架构的嵌入式应用程序。
创建工程
- 选择STM32CubeMX 创建工程
- 工程名和路径之后在STM32CubeMX中还有用
- 我这里是P:\clion_stm32\Demo01
- 出现Select Board Config File窗口,先都选择Skip
- 选中Demo01.ioc(.ioc为STM32CubeMX生成的配置文件),点击Open with STM32CubeMX,跳转到STM32CubeMX
-
由于其默认选择的是STM32F030F4Px,因此我们需要重新选择自己正在开发的芯片
- 点击左上角的Home或者STM32030F4Px
- Home 返回启动界面
- STM32030F4Px 返回芯片选择界面
- 这里为了方便,直接选择STM32030F4Px,进入芯片选择界面
- 在Commercial Part Number中输入芯片型号
- 选择需要的芯片
- 点击Start Project
- 点击左上角的Home或者STM32030F4Px
-
进入配置界面,由于只是测试,因此只配置一些必要选项
-
System Core
-
RCC
- Hign Speed Clock(HSE):Crystal/Ceramic Resonator 使能外部高速晶振
- 之后点击Clock Configuration,进入时钟树配置界面
- 将HCLK设置为72MHz,回车,之后STM32CubeMX会自动计算其余参数
-
SYS
- Debug 选择 Serial Wire (因为我这里使用的是SWD 节省点引脚)
-
-
-
基本配置好之后,点击Project Manger,进入工程配置界面
-
我之前的P:\clion_stm32\Demo01
-
Project Name 要和之前Clion中创建的工程名一致
-
Project Location 要和之前Clion中工程所在的路径一致
-
Toolchain/IDE 选择SW4STM32,并勾选Generate Under Root
这张图是 STMicroelectronics 公司的 STM32CubeMX 配置软件的屏幕截图。STM32CubeMX 是一种图形化工具,用于配置 STM32 微控制器和生成初始化代码。以下是这个界面的各个部分的详细解释:
- 项目设置:
- 项目名称:用户为当前项目设定的名称,在这个例子中是“Demo01”。
- 项目位置:项目文件存放的目录路径,这里设置为
\c\ion_stm32
。 - 应用程序结构:选择应用程序的结构(例如“高级”),它影响生成的代码组织。
- 工具链/IDE:选定的集成开发环境(IDE),在这里是 SW4STM32,即 System Workbench for STM32。
- 代码生成器:
- 工具链文件夹位置:为IDE指定的文件夹路径。
- 在根目录下生成代码:如果勾选此选项,代码将在指定的根目录下生成。
- 链接器设置:
- 最小堆栈大小:为系统堆栈指定的最小大小。
- 最小堆大小:为系统堆指定的最小大小。
- 线程安全设置:
- Cortex-MNNS:指定是否启用与ARM Cortex-M处理器的非安全功能相关的设置。
- 启用多线程支持:若勾选,将为操作系统或多线程应用启用支持。
- 线程安全锁定策略:选择线程安全的锁定策略,依赖于实时操作系统的选择。
- MCU和固件包:
- MCU参考:选定的微控制器型号,这里是 STM32F103C8Tx。
- 固件包名称和版本:选择使用的固件库的版本,在这里是 STM32Cube FW F1 V1.8.5。
- 使用默认固件位置:若勾选,将使用默认的固件库位置。
- 固件相对路径:
- 显示固件库的存放路径,这里是
\Users\ZACK\STM32Cube\Repository\STM32Cube_FW_F1_V1.8.5
。
- 上方的菜单栏和工具栏:
- 包括文件、配置、窗口和帮助等菜单选项。
- 有快速访问按钮,如生成代码的“GENERATE CODE”按钮。
STM32CubeMX 工具用于在开始编写任何代码之前,配置微控制器的硬件特性(如时钟、外设和中断)并生成对应的初始化代码。这个工具极大地简化了STM32微控制器的初始设置过程,并帮助开发者避免了手动配置寄存器的繁琐工作。通过图形化的界面,它提供了一种直观的方式来选择微控制器的特性和外设,并自动生成可在多种IDE中使用的代码框架。
这张图展示的是 STM32CubeMX 配置软件中的一个下拉菜单,列出了不同的集成开发环境(IDEs)和工具链,用于开发 STM32 微控制器。以下是各个选项的详细解释和它们之间的区别:
- SW4STM32 (System Workbench for STM32):
- 这是一个免费的Eclipse基于的开发环境,为STM32微控制器系列提供支持。
- 它是用于开发STM32微控制器应用的完整工具链,包括编译器、调试器等。
- EWARM (IAR Embedded Workbench for ARM):
- IAR Embedded Workbench 是由IAR Systems提供的一款高级开发环境,针对ARM处理器。
- 它包括了一个编译器、调试器、链接器以及一个集成的开发环境,特别注重代码优化和效率。
- MDK-ARM (Keil Microcontroller Development Kit):
- Keil MDK-ARM 是由ARM公司提供的一个全面的软件开发解决方案,适用于基于ARM的微控制器。
- 它包括了uVision IDE、ARM编译器、调试器和广泛的中间件选项。
- STM32CubeIDE:
- STM32CubeIDE 是 STMicroelectronics 提供的集成开发环境,集成了STM32CubeMX配置工具和一个IDE。
- 它提供了代码编写、编译、调试一体化的服务,并包括了STM32Cube库和硬件抽象层(HAL)。
- TrueSTUDIO:
- TrueSTUDIO 是由Atollic公司开发的一个Eclipse基于的IDE,特别为ARM核心的微控制器设计。
- 它包含了强大的工具,如编辑器、编译器和调试器,以及复杂的项目管理功能。
- Makefile:
- 选择Makefile将允许用户手动管理构建过程,而不是依赖于特定的IDE来管理。
- 这种方法为有经验的开发者提供了更多的控制和灵活性,但也要求更多的构建过程知识。
- Other Toolchains (GPDSC):
- 这个选项允许使用支持Generic Project Description for Toolchains (GPDSC)的其他工具链。
- 它是为了兼容那些可能不在下拉菜单中列出的特定或者定制的工具链。
不同选项的主要区别在于它们提供的功能、用户界面、以及支持的额外工具和库。选择哪个IDE或工具链可能取决于开发者的个人偏好、项目需求、公司政策或者对特定工具的依赖。例如,一些IDE可能对代码优化提供更好的支持,而另一些可能提供更强大的调试工具。
-
点击左侧 Code Generator,勾选Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral (模块化)
-
之后,点击GENERATE CODE生成代码
-
-
报警告,点击Yes,覆盖之前的项目
这张图显示了一个警告对话框,它是在使用STM32CubeMX软件时可能遇到的。STM32CubeMX是一个用于配置STM32微控制器和生成初始化代码的工具。图中的对话框具体说明如下:
标题栏:显示“Warning: Save Project As”,这表明用户正在尝试以新名称保存一个项目,或者保存到一个新位置。
警告消息:消息内容为:“P:\c\ion_stm32\Demo01\Demo01.ioc project already exists would you like to overwrite it?”这说明用户试图保存的项目文件(.ioc文件)已经存在于指定的路径下。
.ioc文件:是STM32CubeMX的项目文件格式,包含了用户对STM32微控制器进行的所有配置信息。
覆盖确认:对话框询问用户是否希望覆盖已存在的文件。如果用户选择“是”,现有的文件将被新文件替换;如果选择“否”,则不会替换,并且用户可能会被提示选择一个新的文件名或保存位置。
按钮:有两个选项,“Yes”和“No”,允许用户选择是否覆盖文件。在“是”的选项上有一个红色的框,这通常意味着用户界面(UI)设计希望引起用户的注意,或者这个选项已经被选中。
在实际操作中,如果用户不希望覆盖原有文件,应选择“No”并给项目一个新的名字或选择一个不同的保存路径。如果用户确认覆盖文件是安全的,即之前的文件不再需要,那么选择“Yes”将会保存当前的项目状态,覆盖旧文件。
- 报警告,点击Yes,仍然生成,因为Tool chain / IDE该选项在新版本的STM32CubeMX 不再支持
这张图显示的是 STM32CubeMX 软件的一个警告对话框,它是在用户尝试生成代码时弹出的。STM32CubeMX 是用于配置 STM32 微控制器和生成初始化代码的工具。对话框的具体内容包括:
标题栏:显示“Warning: Code Generation”,这表明警告与代码生成过程有关。
警告内容:
提示用户他们选择的“Tool chain / IDE”即将在未来的 STM32CubeMX 版本中不再支持。
如果用户希望他们的项目能够从未来的 STM32CubeMX 版本中获益,建议他们切换到 STM32CubeIDE 或其他IDE。
代码生成询问:对话框询问用户“Do you still want to generate code?”(您仍然想要生成代码吗?)。
按钮:有两个选项,分别是“是”和“否”,允许用户决定是否继续生成代码。红色框标注的“是”按钮表示用户界面(UI)可能希望用户注意这一选项,或者它已经被用户选中。
这个警告是给用户的提示,让他们知道他们当前所使用的集成开发环境或工具链可能很快不会被支持,因此在继续前应该考虑转移到 STM32CubeMX 支持的其他工具。这是一个重要的信息,因为它涉及到项目的未来兼容性和维护性。如果用户决定继续并点击“是”,代码将会被生成;如果他们不想继续,他们可能需要选择“否”并更改他们的工具链或IDE设置。
- 点击Close,之后转到Clion
- 出现如下窗口,选择Skip
这张图显示了一个名为“Select Board Config File”的对话框,这通常出现在配置调试器或编程软件时,需要选择一个特定开发板或设备的配置文件时。这些配置文件通常用于指定与硬件相关的设置,如引脚分配、时钟配置和外设接口。以下是对这个对话框的详细解释:
配置文件列表:列出了多个不同的配置文件,每个文件对应一个特定的硬件平台或开发板。例如:
8devices-lima.cfg
可能是为了8devices公司的 Lima 设备。adapteva_parallella1.cfg
可能是为了Adapteva公司的 Parallella 平台。adsp-sc584-ezbrd.cfg
可能是为了Analog Devices公司的 ADSP-SC584 EZ-Board。- 其他列出的
.cfg
文件也是为不同的硬件平台或开发板配置的。按钮功能:
- Use:选择突出显示的配置文件并使用它进行下一步操作。
- Copy to Project & Use:将选定的配置文件复制到当前项目的目录下并使用它。
- Skip:跳过选择配置文件的步骤。
这个对话框的目的是让用户为他们的开发环境选择合适的硬件配置文件。这是嵌入式开发过程中的一个关键步骤,因为正确的配置文件确保了软件可以与硬件正确通信。选择错误的配置文件可能导致编程或调试过程中的问题。
- 之后代码就会更新了
编译和烧录 (OpenOCD Doenload & Run)
编译
- 点击右上角的锤子按钮(Build),进行编译
- 编译成功会出现如下信息
- 生成.hex和.bin文件
这张图是集成开发环境(IDE)中的编译输出窗口的截图,它显示了在编译一个名为“Demo01.elf”的STM32项目时的状态和进度。以下是对该图的详细解释:
编译进度和输出:
- 输出显示了编译过程中的各个步骤,包括编译的对象文件(
.obj
文件)列表,这些文件是源代码文件(.c
文件)的编译结果。- 每行前的百分比表示编译进度。从
[ 4%]
开始,直至[100%]
表明编译完成。项目路径:
- 在窗口顶部的命令行,显示了启动编译过程的命令路径,表明编译是在路径
P:\clion_stm32\Demo01\
下执行的。构建命令:
cmake.exe --build P:\clion_stm32\Demo01\cmake-build-debug --target Demo01.elf -- -j
是实际执行的构建命令,其中:
--build
指定构建目录。--target
指定构建目标。-j
参数可能是用来指定并行构建的线程数。编译器输出:
- 显示了编译各个源文件和HAL(硬件抽象层)驱动文件的过程,HAL驱动是STM32软件库的一部分,用于简化硬件接口编程。
链接器输出:
[ 90%] Linking C executable Demo01.elf
表明链接器正在创建可执行文件Demo01.elf
,这是最后生成的目标文件,将被下载到微控制器。内存使用情况:
- 输出还显示了内存使用情况,包括 RAM 和 FLASH 的大小及使用百分比。在这个项目中,RAM 使用了 2656 字节(约 12.97%),FLASH 使用了 4792 字节(约 7.31%)。
额外的构建目标:
- 除了
.elf
可执行文件,还构建了.hex
和.bin
文件,这些格式通常用于将程序烧录到微控制器。编译成功信息:
[100%] Built target Demo01.elf
和 “Build finished” 提示编译成功完成。IDE界面元素:
- 顶部的工具栏和侧边的项目浏览器使用户可以执行不同的动作,如运行或调试程序,并在项目文件之间导航。
整体来说,此截图显示了一个使用 CMake 构建系统和可能是 CLion IDE(由 JetBrains 提供)的 STM32项目的成功编译过程。这窗口为开发者提供了重要的反馈,帮助他们理解构建过程中发生了什么,是否成功,以及如何优化他们的代码或构建配置。
烧录前的配置
ProjectName.elf 具体参考CmakeLists.txt下的设置
project(\${projectName} C CXX ASM) add_executable(\${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT})
- 点击右上角三点,选择Edit,进入Run/Debug Configurations界面(设置和管理运行和调试项目的配置)
- 点击左上角+号,选择OpenOCD Doenload & Run
这张图显示的是一个集成开发环境(IDE)的“Run/Debug Configurations”对话框,它用于设置和管理运行和调试项目的配置。在对话框中,用户可以定义如何执行和调试应用程序。以下是对图中显示的各个元素的详细解释:
- 导航栏(左侧红框内):
- “+”:添加新的运行/调试配置。
- “OpenOCD Download & Run”:这是一个预配置的运行/调试模板,用于通过OpenOCD(Open On-Chip Debugger)下载并运行程序。OpenOCD是一个流行的调试工具,常用于嵌入式开发。
-
Target:ProjectName.elf
-
Executable binary:ProjectName.elf
-
Board config file:
-
stlink.cfg(需要自己创建一个)
-
# choose st-link/j-link/dap-link etc. #adapter driver cmsis-dap #transport select swd source [find interface/stlink.cfg] transport select hla_swd source [find target/stm32f1x.cfg] # download speed = 10MHz adapter speed 10000
这段代码是一个OpenOCD(Open On-Chip Debugger)配置脚本的一部分,用于设置调试器接口和目标微控制器配置。OpenOCD是一个用于编程和调试嵌入式系统的工具。以下是对该脚本的详细解释:
# choose st-link/j-link/dap-link etc.
- 这是一行注释,说明该配置文件允许选择不同的调试器接口,如ST-Link、J-Link、DAP-Link等。
#adapter driver cmsis-dap
- 另一条注释,指出可以选择CMSIS-DAP作为调试适配器驱动程序,但这行实际被注释掉了。
#transport select swd
- 这行注释指出可以选择SWD(Serial Wire Debug)作为调试传输协议,但这行也被注释掉了。
source [find interface/stlink.cfg]
- 这行命令告诉OpenOCD加载ST-Link 调试器的配置文件。
source
是一个命令,用于加载另一个配置文件,[find interface/stlink.cfg]
是一个命令,用于查找和加载名为stlink.cfg
的文件,该文件包含了ST-Link v2调试器的特定配置。
transport select hla_swd
- 这行命令选择了HLA(高级调试适配器)接口的SWD传输协议。这通常用于ST-Link调试器。
source [find target/stm32f1x.cfg]
- 这行命令加载了STM32F1系列微控制器的配置文件。同样,
source
加载文件,[find target/stm32f1x.cfg]
查找并加载该文件,该文件包含了针对STM32F1系列微控制器的特定配置。
# download speed = 10MHz
- 这是一行注释,说明接下来的设置是调试器的下载速度。
adapter speed 10000
- 这行命令设置了调试器的通信速度为10000kHz(或10MHz)。这影响了调试器和目标微控制器之间的数据传输速率。
总的来说,这段脚本配置了OpenOCD以使用ST-Link v2调试器,通过HLA-SWD协议与STM32F1系列微控制器进行通信,并设置了适当的通信速度。这对于调试STM32微控制器非常常见。
-
-
Download
- Always :每次运行或调试时都下载。
- If updated:只有在程序更新后才下载。
- Never:不自动下载程序。
-
Reset:
- Run :执行重置并运行程序。
- Init :只初始化设备,不运行程序。
- Halt :在开始运行前暂停程序。
- None :不进行任何重置操作。
这张图展示了一个IDE(集成开发环境)的运行/调试配置界面,特别是针对嵌入式开发的一个配置。在这个界面中,开发者可以设置如何构建(编译和链接)、运行和调试一个嵌入式应用程序。
以下是对界面上各个部分的详细解释:
Name: 配置名称,在这里是
Demo01.elf
,通常对应于输出的可执行文件。Target: 目标设备或目标配置的名称。这通常是一个用户定义的名称,用于标识特定的构建目标。
Executable binary: 可执行文件的路径,这里也是
Demo01.elf
。这是构建系统生成的文件,将在嵌入式设备上运行。Debugger: 调试器工具的配置,这里使用的是“Bundled GDB multiarch”,意味着IDE附带了用于多种架构的GNU调试器。
Board config file: 开发板配置文件的路径,这里是
P:\clion_stm32\\Config\Demo01.cfg
。这个文件通常包含了用于OpenOCD的特定于开发板的配置信息。GDB port: 用于GDB(GNU调试器)服务器监听的端口号,这里设置为
3333
。Telnet port: 用于OpenOCD Telnet会话的端口号,这里设置为
4444
。Download: 这里有三个选项来指定何时应该将程序下载到目标设备:
- Always: 每次运行或调试时都下载。
- If updated: 只有在程序更新后才下载。
- Never: 不自动下载程序。
- Reset: 运行或调试前如何重置目标设备:
- Run: 执行重置并运行程序。
- Init: 只初始化设备,不运行程序。
- Halt: 在开始运行前暂停程序。
- None: 不进行任何重置操作。
Before launch: 在启动程序之前需要执行的任务,通常是构建项目。
Show this page: 是否在启动前显示此配置页面。
Activate tool window: 是否在运行时激活工具窗口。
Focus tool window: 是否在运行时将焦点移至工具窗口。
界面底部的“Run”、“OK”和“Apply”按钮允许用户运行配置、保存更改或应用更改而不关闭窗口。通过这些设置,开发者可以为嵌入式应用程序的构建、下载、运行和调试过程定义详细的参数。这样的配置有助于自动化开发流程,使调试过程更加高效。
烧录
- 确保在OpenOCD Doenload & Run下,点击三角形(Run)按钮,进行烧录
- 出现如下信息,烧录成功
您提供的图片是一个计算机界面截图,显示了OpenOCD(Open On-Chip Debugger)的输出信息。OpenOCD是一个用于嵌入式目标处理器的调试、系统内编程和边界扫描测试工具。
下面是截图信息的详细解释:
- 屏幕顶部部分显示了使用特定配置文件(在此案例中为ST-Link)调用OpenOCD的命令行。
- 还显示了OpenOCD的版本,提及了许可证(GNU GPL v2),以及一个用于报告错误的URL。
Info
行是OpenOCD的输出消息,提供了正在执行的操作的详细信息。它指定了适配器速度和检测到的处理器类型,在这个案例中是STM32系列的Cortex-M3(stm32f1x.cpu)。- 调试器已经确定目标拥有六个断点和四个监视点。
halted due to debug-request
消息表明目标CPU已经由于调试请求而停止。xPSR
和pc
是ARM CPU中的寄存器,分别显示程序状态和当前程序计数器的位置。- 还显示编程已经开始,并提供了设备ID和闪存大小,在此案例中为64 KiB。
- 关于额外擦除范围的警告可能表示已经标记了一部分内存以供擦除。
** Programming Finished **
消息表明编程操作已成功完成。shutdown command invoked
消息表明已经发出了终止OpenOCD会话的命令。这个输出在使用OpenOCD和ST-Link调试适配器进行微控制器编程和调试时是典型的。它表明过程已经完成,没有任何关键错误。用户可能正在为STM32系列的微控制器开发嵌入式软件。
遇到的问题
CMake Build消失(不知道具体原因)
- 如图,红框所示部分应有CMake和Build
清除系统缓存
- 点击File->Invalidate Caches 清除系统缓存
- 全部勾选,点击Invalidate and Restart
这张图片显示的是一个集成开发环境(IDE)中的“清除缓存”对话框。这个功能允许用户删除所有项目的缓存和索引,这样当重新打开项目时,新的缓存将被构建。具体的选项包括:
清除文件系统缓存和本地历史记录(Clear file system cache and Local History):这将删除文件系统的缓存和IDE的本地历史记录,可能包括文件更改的历史记录等。
清除版本控制系统日志缓存和索引(Clear VCS Log caches and indexes):如果你使用版本控制系统(如Git),这个选项将清除与之相关的日志和索引的缓存。
清除远程主机缓存(Invalidate remote hosts caches):这将标记任何远程主机(例如通过SSH或Docker连接的主机)的缓存为无效,远程主机的缓存将在下一次项目重新加载时重新下载。
重置CMake缓存(Reset CMake Cache):这将删除
CMakeCache.txt
文件,并在启动时重新加载项目。这个操作只针对当前打开的项目。删除嵌入式浏览器引擎缓存和cookies(Delete embedded browser engine cache and cookies):这会影响使用嵌入式浏览器渲染HTML内容的组件,例如可能清除在IDE中预览文档时的缓存和cookies。
下方的两个按钮提供了两个选项:
仅重启(Just restart):这将重启IDE,但不会清除缓存。
清除并重启(Invalidate and Restart):这将清除选定的缓存并重新启动IDE。
取消(Cancel):关闭此对话框而不进行任何操作。
如果IDE运行缓慢或者出现问题,清除缓存有时可以解决这些问题,因为它会删除旧的或损坏的缓存文件。在进行重大更改或更新后,也常常需要清除缓存以确保所有的最新更改都被正确加载和识别。
- 重启之后,右击CMakeLists.txt,点击Reload CMake Project即可解决
在STM32CubeMX中重新生成或者重启Clion
- 略
似乎只需要让CMake Project重新加载一次就可以解决
杂
CmakeLists.txt
#THIS FILE IS AUTO GENERATED FROM THE TEMPLATE! DO NOT CHANGE!
# 设置目标系统名称为 Generic,通常用于交叉编译环境
set(CMAKE_SYSTEM_NAME Generic)
# 设置目标系统版本,这里设置为 1
set(CMAKE_SYSTEM_VERSION 1)
# 指定运行此CMake脚本所需的最低CMake版本为 3.27
cmake_minimum_required(VERSION 3.27)
# specify cross-compilers and tools
# 设置C编译器为ARM架构的交叉编译器 arm-none-eabi-gcc
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
# 设置C++编译器为ARM架构的交叉编译器 arm-none-eabi-g++
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
# 设置汇编编译器为ARM架构的交叉编译器 arm-none-eabi-gcc
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
# 设置归档工具为ARM架构的 arm-none-eabi-ar
set(CMAKE_AR arm-none-eabi-ar)
# 设置对象复制工具为ARM架构的 arm-none-eabi-objcopy
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
# 设置对象转储工具为ARM架构的 arm-none-eabi-objdump
set(CMAKE_OBJDUMP arm-none-eabi-objdump)
# 设置用于报告文件大小的工具为ARM架构的 arm-none-eabi-size
set(SIZE arm-none-eabi-size)
# 在尝试编译时创建一个静态库而非可执行文件,适用于交叉编译环境
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
# project settings
# 定义一个名为Demo01的项目,指明该项目将包含C、C++和汇编语言的代码
project(Demo01 C CXX ASM)
# 设置C++编译器遵循的C++标准为C++17
set(CMAKE_CXX_STANDARD 17)
# 设置C编译器遵循的C标准为C11
set(CMAKE_C_STANDARD 11)
# 如果需要硬件浮点支持,请取消以下注释
#add_compile_definitions(ARM_MATH_CM4;ARM_MATH_MATRIX_CHECK;ARM_MATH_ROUNDING)
# 为编译器添加指令,启用ARM Cortex-M4的硬件浮点支持并进行相应的配置
#add_compile_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
# 为编译器添加指令,使用硬件浮点单元和特定的浮点处理单元类型
#add_link_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
# 为链接器添加相同的浮点处理指令
# 如果需要软件浮点支持,请取消以下注释
#add_compile_options(-mfloat-abi=soft)
# 为编译器添加指令,使用软件浮点运算
add_compile_options(-mcpu=cortex-m3 -mthumb -mthumb-interwork)
# 添加编译选项,指定CPU类型为Cortex-M3,使用Thumb指令集并支持Thumb与ARM指令集的互操作
add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0)
# 添加编译选项,优化函数和数据的段分布,禁用通用数据块,控制错误和警告信息的格式
# 如果需要减少C++17绝对地址警告,请取消以下注释
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")
# 更新C++编译器标志,禁用关于'register'关键字的警告
# 启用汇编文件的预处理
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-x$<SEMICOLON>assembler-with-cpp>)
# 对于汇编语言文件,添加编译选项以启用C预处理器支持
# 根据不同的构建类型设置相应的编译选项
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 ()
# 添加多个目录到编译器的头文件搜索路径,以便于在源代码中包含这些目录下的头文件
include_directories(Core/Inc Drivers/STM32F1xx_HAL_Driver/Inc Drivers/STM32F1xx_HAL_Driver/Inc/Legacy Drivers/CMSIS/Device/ST/STM32F1xx/Include Drivers/CMSIS/Include)
# 为编译器添加预处理器宏定义,启用STM32硬件抽象层驱动和指定微控制器型号为STM32F103xB
add_definitions(-DUSE_HAL_DRIVER -DSTM32F103xB)
# 递归收集 startup, Drivers 和 Core 目录及其子目录下所有文件的路径,并将这些路径赋值给 SOURCES 变量
file(GLOB_RECURSE SOURCES "startup/*.*" "Drivers/*.*" "Core/*.*")
# 设置变量 LINKER_SCRIPT 为CMake项目源代码根目录下的STM32F103C8Tx_FLASH.ld链接器脚本的路径
set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/STM32F103C8Tx_FLASH.ld)
# 添加链接器选项,用于优化未使用部分的移除,打印内存使用情况,生成链接映射文件
add_link_options(-Wl,-gc-sections,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map)
# 添加链接器选项,指定CPU为Cortex-M3,生成Thumb指令集代码,允许Thumb和ARM指令集互操作
add_link_options(-mcpu=cortex-m3 -mthumb -mthumb-interwork)
# 添加链接器选项,使用指定的链接脚本进行链接
add_link_options(-T ${LINKER_SCRIPT})
# 添加一个可执行文件目标,使用指定的源文件和链接器脚本来构建项目名称为 ${PROJECT_NAME}.elf 的 ELF 文件
add_executable(${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT})
# 设置HEX文件的输出路径,通常用于烧录到微控制器的固件
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
# 设置BIN文件的输出路径,通常用于烧录到微控制器的固件
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
# 添加一个在目标 ${PROJECT_NAME}.elf 构建完成后执行的自定义命令
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
# 使用CMAKE_OBJCOPY工具将ELF文件转换为Intel HEX格式,输出到HEX_FILE变量指定的路径
COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
# 使用CMAKE_OBJCOPY工具将ELF文件转换为二进制格式,输出到BIN_FILE变量指定的路径
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
# 在构建日志中输出消息,指明HEX和BIN文件正在被构建
COMMENT "Building ${HEX_FILE}
Building ${BIN_FILE}")
这段代码是一个为嵌入式ARM项目配置CMake的脚本。下面是脚本各部分的详细解释:
-
文件注释:
#THIS FILE IS AUTO GENERATED FROM THE TEMPLATE! DO NOT CHANGE!
这是一行注释,说明该文件是由模板自动生成的,不应该被修改。
-
基本CMake设置:
- 这段CMake代码用于设置一些基本的项目配置,特别是在进行交叉编译时。以下是每个命令的详细解释:
set(CMAKE_SYSTEM_NAME Generic)
- 这行代码设置了变量
CMAKE_SYSTEM_NAME
为Generic
。在CMake中,CMAKE_SYSTEM_NAME
用来指定目标系统的名称。设置为Generic
意味着目标系统不是一个特定的、CMake已知的系统,这是在配置交叉编译环境时常见的做法。交叉编译意味着你在一个类型的系统(比如Windows或Linux)上编译代码,但编译出的程序是为另一种系统(在这个上下文中,可能是一个嵌入式系统)运行的。
- 这行代码设置了变量
set(CMAKE_SYSTEM_VERSION 1)
- 这行代码设置了变量
CMAKE_SYSTEM_VERSION
为1
。这个变量通常用于指定目标系统的版本,但在设置为Generic
的系统中,这个值通常不太重要,可以是任意值。
- 这行代码设置了变量
cmake_minimum_required(VERSION 3.27)
- 这行代码指定了运行此CMake配置所需的最低CMake版本。在这个例子中,它要求至少使用CMake版本3.27。这是一个常见的做法,确保使用的CMake版本包含了脚本中使用的所有特性和语法。
- 这段CMake代码用于设置一些基本的项目配置,特别是在进行交叉编译时。以下是每个命令的详细解释:
-
交叉编译器和工具设置:
-
这段CMake代码配置了项目的交叉编译工具链,特别是针对ARM架构的嵌入式开发。以下是详细解释:
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
- 这行设置了C语言编译器为
arm-none-eabi-gcc
。arm-none-eabi-gcc
是一个专门用于ARM架构嵌入式系统的交叉编译器,它可以在非ARM系统(如x86架构的PC)上编译出可在ARM系统上运行的代码。
- 这行设置了C语言编译器为
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
- 类似地,这行设置C++语言编译器为
arm-none-eabi-g++
,这是arm-none-eabi-gcc
的C++版本。
- 类似地,这行设置C++语言编译器为
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
- 这行设置汇编语言编译器为
arm-none-eabi-gcc
。虽然主要用于C语言,但arm-none-eabi-gcc
也能处理汇编语言代码。
- 这行设置汇编语言编译器为
set(CMAKE_AR arm-none-eabi-ar)
- 设置归档工具为
arm-none-eabi-ar
。归档工具用于创建静态库。
- 设置归档工具为
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
- 设置对象复制工具为
arm-none-eabi-objcopy
,用于转换和复制对象文件。
- 设置对象复制工具为
set(CMAKE_OBJDUMP arm-none-eabi-objdump)
- 设置对象转储工具为
arm-none-eabi-objdump
,用于显示对象文件、可执行文件的信息。
- 设置对象转储工具为
set(SIZE arm-none-eabi-size)
- 设置用于报告目标文件大小的工具为
arm-none-eabi-size
。
- 设置用于报告目标文件大小的工具为
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
- 这行指示CMake在尝试编译过程中创建一个静态库,而非可执行文件。这在交叉编译环境中是常见的做法,因为它不需要可执行环境。
这些设置是为了确保CMake在构建过程中使用正确的交叉编译工具,这对于开发针对特定硬件(如ARM微控制器)的嵌入式应用程序是必需的。
-
-
项目设置:
-
这段代码是CMake配置脚本的一部分,用于设置项目的基本属性和C/C++语言标准。以下是详细解释:
-
project(Demo01 C CXX ASM)
project(...)
: 这是CMake中用来声明项目的命令。Demo01
: 这是项目的名称,这个名字会被用作该项目在CMake中的标识符。C CXX ASM
: 这些是项目支持的语言。C
表示项目中包含C语言代码,CXX
表示包含C++语言代码,ASM
表示包含汇编语言代码。这个声明使得CMake知道要为这些语言准备相应的编译器。
-
set(CMAKE_CXX_STANDARD 17)
set(...)
: 这是CMake中用于设置变量值的命令。CMAKE_CXX_STANDARD
: 这是一个CMake变量,用于指定C++编译器应该遵循的C++标准。在这里,它被设置为17
,意味着项目将使用C++17标准。
-
set(CMAKE_C_STANDARD 11)
- 类似于
CMAKE_CXX_STANDARD
,但这个是用于C语言的版本设置。 CMAKE_C_STANDARD
: 这个变量指定了C编译器应该遵循的C语言标准。这里被设置为11
,表示项目将使用C11标准。
- 类似于
综上所述,这段代码的作用是初始化项目
Demo01
,声明项目将使用C、C++和汇编语言,并且分别指定C++和C语言使用的标准版本为C++17和C11。这有助于确保项目代码使用的语言特性与指定的标准兼容。 -
-
-
编译器选项:
-
这段CMake代码包含了一系列用于配置编译选项的命令,这些选项对项目中的C、C++和汇编语言文件的编译过程有影响。下面是对这些命令的详细解释:
-
#Uncomment for hardware floating point
- 这是一条注释,指示如果你想要启用硬件浮点支持,可以取消以下两行的注释。
-
#add_compile_definitions(ARM_MATH_CM4;ARM_MATH_MATRIX_CHECK;ARM_MATH_ROUNDING)
- 如果取消注释,这将添加预处理器宏定义,可能与ARM Cortex-M4处理器的硬件浮点单元(FPU)相关。
-
#add_compile_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
- 如果取消注释,这将告诉编译器使用硬件浮点单元进行浮点运算,并指定浮点单元的类型(
fpv4-sp-d16
)。
- 如果取消注释,这将告诉编译器使用硬件浮点单元进行浮点运算,并指定浮点单元的类型(
-
#add_link_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
- 如果取消注释,这将为链接器添加相同的浮点指令集选项。
-
#Uncomment for software floating point
- 这是另一条注释,指示如果你想要启用软件浮点支持,可以取消以下一行的注释。
-
#add_compile_options(-mfloat-abi=soft)
- 如果取消注释,这将告诉编译器使用软件而非硬件来执行浮点运算。
-
add_compile_options(-mcpu=cortex-m3 -mthumb -mthumb-interwork)
- 这行命令为所有编译目标添加编译选项,指定了CPU类型为ARM Cortex-M3,并启用了Thumb指令集及Thumb和ARM指令集之间的互操作。
-
add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0)
- 这行命令添加了多个编译选项,用于优化生成的代码:
-ffunction-sections
和-fdata-sections
选项使得每个函数和数据项放在它们自己的段中,这有助于链接器移除未使用的函数和数据。-fno-common
防止生成通用数据(即未初始化的全局变量)。-fmessage-length=0
用于控制编译器错误和警告消息的格式。
- 这行命令添加了多个编译选项,用于优化生成的代码:
-
# uncomment to mitigate c++17 absolute addresses warnings
- 这是一条注释,指示如果你想要减少C++17编译中的绝对地址警告,可以取消以下一行的注释。
-
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")
- 如果取消注释,这将向C++编译器的标志中添加
-Wno-register
,用来关闭关于register
关键字的警告,这在C++17中已弃用。
- 如果取消注释,这将向C++编译器的标志中添加
-
add_compile_options($<$<COMPILE_LANGUAGE:ASM>:-x$<SEMICOLON>assembler-with-cpp>)
- 这行命令对汇编语言文件添加了编译选项
-x assembler-with-cpp
,启用预处理器支持。这允许在汇编文件中使用C预处理器指令。
- 这行命令对汇编语言文件添加了编译选项
总之,这些指令让你能够根据项目需要灵活配置编译器和链接器的行为,特别是针对特定的处理器特性和优化目标。
-
-
-
构建类型和编译优化:
-
这段CMake代码使用条件语句来根据不同的构建类型设置编译选项。不同的构建类型通常用于不同的开发阶段,例如调试、发布等。以下是代码的详细解释:
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")
- 这个
if
语句检查变量CMAKE_BUILD_TYPE
是否设置为Release
。Release
构建类型通常用于最终的产品发布,其中不包含调试信息,并且启用了最大程度的优化。 message(STATUS "Maximum optimization for speed")
: 输出一条状态消息,表明正在进行针对速度的最大优化。add_compile_options(-Ofast)
: 添加编译器选项-Ofast
,这是一个告诉编译器进行极致优化以提升执行速度的选项。
- 这个
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")
- 如果
CMAKE_BUILD_TYPE
设置为RelWithDebInfo
,则表示是一个发布版本但包含调试信息。这种类型常用于性能分析,同时保留了调试的能力。 message(STATUS "Maximum optimization for speed, debug info included")
: 输出一条状态消息,表明正在进行针对速度的最大优化,并包含调试信息。add_compile_options(-Ofast -g)
: 添加-Ofast
和-g
编译选项,其中-g
用于生成调试信息。
- 如果
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel")
MinSizeRel
构建类型专注于生成尽可能小的二进制文件。message(STATUS "Maximum optimization for size")
: 输出一条消息,表明正在进行最大程度的尺寸优化。add_compile_options(-Os)
: 添加-Os
编译选项,告诉编译器优化二进制文件的大小。
else ()
- 如果没有指定
CMAKE_BUILD_TYPE
或者它不是上述任何一个值,则进入此分支。 message(STATUS "Minimal optimization, debug info included")
: 输出一条消息,表明正在进行最小优化,并包含调试信息。add_compile_options(-Og -g)
: 添加-Og
和-g
编译选项,其中-Og
提供了足够的优化,同时仍然适合调试。
- 如果没有指定
endif ()
- 结束条件语句。
这段代码通过在不同构建类型下设置不同的编译选项,使得开发者可以根据需要选择适合的构建配置,以优化性能、减小文件大小或方便调试。
-
-
头文件目录:
-
这行CMake代码使用
include_directories()
命令来指定编译器在编译过程中应该搜索头文件的目录。具体来说:include_directories(...)
: 这是一个CMake命令,用于向编译器的头文件搜索路径中添加指定的目录。这意味着在编译项目中的源文件时,编译器会在这些目录中查找头文件。Core/Inc
: 这是项目结构中的一个目录,可能包含了核心功能的头文件。Core/Inc
路径表明头文件位于Core
目录下的Inc
子目录中。Drivers/STM32F1xx_HAL_Driver/Inc
: 这个路径指向STM32F1系列微控制器的硬件抽象层(HAL)驱动程序的头文件。这些驱动程序为硬件功能提供了一个抽象层,使得编程更加简单。Drivers/STM32F1xx_HAL_Driver/Inc/Legacy
: 这可能是HAL驱动的旧版或遗留接口的目录,用于兼容性或向后兼容。Drivers/CMSIS/Device/ST/STM32F1xx/Include
: 这是Cortex Microcontroller Software Interface Standard(CMSIS)的目录,为STM32F1xx系列微控制器提供了标准化的硬件接口。Drivers/CMSIS/Include
: 这是通用的CMSIS头文件目录,为所有CMSIS兼容的微控制器提供接口和宏定义。
通过添加这些目录到编译器的搜索路径,您的源代码可以方便地包含这些目录中的头文件,无需指定完整的路径。这在管理大型项目中非常有用,尤其是在涉及多个硬件抽象和驱动层时。
-
-
宏定义:
-
这行CMake代码使用
add_definitions()
命令来添加预处理器宏定义。在编译过程中,这些宏定义将被包含在编译器的命令行中。具体来说:add_definitions(...)
: 这是一个CMake命令,用于为编译器添加宏定义。它对整个项目中所有的编译目标有效。-DUSE_HAL_DRIVER
: 这是一个预处理器指令,用于定义宏USE_HAL_DRIVER
。在源代码中,可以通过检查这个宏是否被定义来条件编译特定的代码块。通常这种宏定义用于启用或禁用特定的功能或代码路径。在这个特定的上下文中,USE_HAL_DRIVER
可能用于启用与STM32的硬件抽象层(HAL)相关的代码。-DSTM32F103xB
: 这是另一个预处理器指令,定义了宏STM32F103xB
。这通常用于指定目标微控制器的型号。在这种情况下,它表明代码是为STM32F103xB系列微控制器编写的,这可能会影响硬件相关代码的编译,比如启用特定于该型号的寄存器和外设的配置。
这样的预处理器定义在嵌入式编程中非常常见,因为它们允许源代码根据目标硬件的不同特点进行条件编译。
-
-
源文件:
-
这行CMake代码使用
file(GLOB_RECURSE ...)
命令来收集指定路径模式下的所有文件,并将它们的列表赋值给变量SOURCES
。file(...)
: 这是一个CMake命令,用于文件操作,如读取、写入、复制文件等。GLOB_RECURSE
: 这个参数告诉CMake递归地搜索给定的路径模式,包括所有子目录。SOURCES
: 这是在命令中定义的变量名,所有匹配到的文件路径将被存储在这个变量中。"startup/*.*"
: 这是一个文件匹配模式,意味着搜索startup
目录及其所有子目录中的所有文件。"Drivers/*.*"
: 这个模式是为了收集Drivers
目录及其所有子目录中的所有文件。"Core/*.*"
: 同样,这个模式是为了收集Core
目录及其所有子目录中的所有文件。
综上所述,这行代码将会递归地查找
startup
、Drivers
和Core
目录下的所有文件,并将找到的文件路径列表存储在SOURCES
变量中。这个变量随后可以用来指定编译目标所需的源文件。这在嵌入式项目中非常常见,因为您可能会有多个源文件分布在不同的目录中,包括启动代码、硬件驱动、核心逻辑等。
-
-
链接器脚本:
-
这行CMake代码定义了一个变量
LINKER_SCRIPT
,并将其设置为项目源目录中的一个链接器脚本文件的路径。set(...)
: 这是CMake中用于设置变量的命令。LINKER_SCRIPT
: 这是被定义的变量的名称。在这个CMake脚本中,LINKER_SCRIPT
变量将被用于其他命令,特别是在链接步骤中。${CMAKE_SOURCE_DIR}
: 这是一个CMake预定义变量,它包含了CMake项目的源代码根目录的完整路径。这通常是包含顶层CMakeLists.txt
文件的目录。STM32F103C8Tx_FLASH.ld
: 这是链接器脚本文件的名称。链接器脚本指定了程序的内存布局,包括代码、数据和其他段应该在目标硬件的内存中的位置。对于嵌入式系统来说,链接器脚本非常重要,因为它告诉链接器如何将程序的不同部分放到微控制器的FLASH、RAM等区域。
结合在一起,这行代码设置了
LINKER_SCRIPT
变量,其值为CMake项目源目录下的STM32F103C8Tx_FLASH.ld
文件的路径。这个链接器脚本专门用于STM32F103C8Tx微控制器,它定义了程序的FLASH内存布局。
-
-
链接器选项:
-
这三行CMake代码向项目添加链接器选项。链接器选项用于控制链接阶段的行为,如内存布局、优化、调试信息等。以下是每个选项的详细解释:
add_link_options(-Wl,-gc-sections,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map)
-Wl,
: 这个前缀用于告诉编译器将后续的选项传递给链接器。-gc-sections
: 这个选项指示链接器移除未被引用的部分,可以减小最终可执行文件的大小。--print-memory-usage
: 这个选项会让链接器在链接过程结束后打印内存使用情况,对于嵌入式系统内存优化非常有用。-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map
: 这个选项让链接器生成一个映射文件,其中包含了符号到地址的映射以及其他链接信息,这对于调试和优化非常有用。
add_link_options(-mcpu=cortex-m3 -mthumb -mthumb-interwork)
-mcpu=cortex-m3
: 这个选项指定了目标CPU型号,这里是ARM Cortex-M3处理器。-mthumb
: 指示链接器生成Thumb指令集的代码,这是ARM架构的一种更紧凑的指令集。-mthumb-interwork
: 允许Thumb和ARM指令集之间进行互操作。
add_link_options(-T ${LINKER_SCRIPT})
-T
: 这个选项后面跟着的是链接器脚本文件的路径,它告诉链接器如何将不同的代码和数据段映射到目标的内存中。
这些链接器选项是为了确保生成的可执行文件能够适配特定的硬件架构(在这里是ARM Cortex-M3),同时优化其内存使用和指令集选择。此外,生成的映射文件和内存使用信息对于嵌入式系统开发来说非常重要,因为它们帮助开发者了解代码是如何被加载到硬件上的,并优化内存使用。
-
-
可执行文件生成:
-
这行CMake代码是用来定义一个可执行文件目标,它告诉CMake如何将一组源文件和链接脚本链接成一个
.elf
(Executable and Linkable Format)文件。.elf
文件通常用于嵌入式系统,如微控制器,因为它包含了程序的代码、数据、符号信息等。以下是详细的解释:-
add_executable()
: 这是一个CMake命令,用于创建一个可执行文件目标。当CMake运行时,它会根据提供的源文件和链接脚本来编译和链接生成一个可执行文件。 -
${PROJECT_NAME}.elf
: 在这里,${PROJECT_NAME}
是一个变量,代表了通过project()
命令设置的项目名称。.elf
是生成的可执行文件的后缀,表示输出文件将是ELF格式。例如,如果项目名称是MyProject
,则目标可执行文件将被命名为MyProject.elf
。 -
${SOURCES}
: 这是一个变量,包含了项目的所有源文件。通常这个变量是通过类似file(GLOB_RECURSE SOURCES src/*.cpp)
这样的命令定义的,它会递归地收集指定路径下的所有源文件。 -
${LINKER_SCRIPT}
: 这是一个变量,指向了链接脚本文件的路径。链接脚本告诉链接器如何将对象文件和库组合成最终的程序。它定义了内存布局、哪些部分放在哪里(例如代码段、数据段)、入口点等信息。在嵌入式开发中,链接脚本非常重要,因为它与硬件密切相关。
综上所述,这行代码指导CMake使用指定的交叉编译器和链接器,根据给定的源文件和链接脚本创建一个名为
项目名称.elf
的可执行文件。 -
-
-
输出文件:
-
这段代码是CMake脚本的一部分,用于在构建过程中添加自定义命令,以生成特定格式的固件文件。下面逐句解释这段代码:
-
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
- 这条命令设置了一个变量
HEX_FILE
,它的值是项目构建目录(${PROJECT_BINARY_DIR}
)下的一个文件,文件名由项目名称(${PROJECT_NAME}
)和文件扩展名.hex
组成。.hex
文件通常是用于嵌入式系统,可以直接烧录到微控制器内存中的固件格式。
- 这条命令设置了一个变量
-
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
- 类似于第一条命令,这条命令设置了一个变量
BIN_FILE
,它的值是项目构建目录下的一个文件,文件名由项目名称和文件扩展名.bin
组成。.bin
文件是另一种常见的固件格式,通常包含纯二进制数据。
- 类似于第一条命令,这条命令设置了一个变量
-
add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD
- 这条命令向CMake添加了一条自定义命令,它将在目标
${PROJECT_NAME}.elf
(通常是一个可执行文件)完成构建后执行。
- 这条命令向CMake添加了一条自定义命令,它将在目标
-
COMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}
COMMAND
关键字指定了要执行的命令。这里使用objcopy
工具(${CMAKE_OBJCOPY}
)将目标文件(${PROJECT_NAME}.elf
)转换成Intel HEX格式,输出到之前定义的HEX_FILE
路径。
-
COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}
- 这是第二个命令,与上一个类似,但它将目标文件转换成纯二进制格式,输出到
BIN_FILE
。
- 这是第二个命令,与上一个类似,但它将目标文件转换成纯二进制格式,输出到
-
COMMENT "Building ${HEX_FILE}\nBuilding ${BIN_FILE}"
- 这是一条注释,当上述
COMMAND
被执行时,CMake会在构建输出中显示这些信息,通知用户正在创建的文件。
- 这是一条注释,当上述
总之,这段代码在项目构建后自动执行,将生成的
.elf
文件转换成.hex
和.bin
格式的固件文件,并将这些文件保存在预定的位置,以便后续可以将它们烧录到嵌入式设备中。 -
-
PROJECT_NAME
在CMake中,PROJECT_NAME
是一个内置变量,它存储了通过 project()
命令指定的项目名称。当你调用 project()
命令并提供一个名称时,CMake 会将这个名称赋值给 PROJECT_NAME
变量,以便在整个CMake配置中引用。
在你提供的CMake脚本中,PROJECT_NAME
会在以下行中被指定:
project(${projectName} C CXX ASM)
在这行代码中,${projectName}
是一个变量,它应该在这个CMake脚本被调用或配置之前被定义。通常,这个变量定义在脚本的开始部分,或者在包含这个CMake脚本的父CMake配置文件中。如果 ${projectName}
变量没有被明确定义,那么 project()
命令可能不会正确设置 PROJECT_NAME
变量,或者它可能会尝试使用一个文字字符串“${projectName}”作为项目名称,这显然不是预期的结果。
一旦 project()
命令被执行,PROJECT_NAME
变量就会被设置,并可以在之后的CMake指令中使用,例如在设置目标名称、生成文件名称等场合。
例如,下面的代码:
add_executable(${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT})
在这里,${PROJECT_NAME}.elf
会根据 project()
命令中指定的项目名称生成一个输出的可执行文件名称。如果项目名称被设置为“untitled”,那么这条命令将会创建一个名为“untitled.elf”的可执行文件。
PROJECT_BINARY_DIR
PROJECT_BINARY_DIR
是 CMake 中的一个预定义变量,它指向的是生成构建系统的目录,也就是执行 CMake 命令时所在的目录。这通常是你创建的“build”目录,用于存放所有的中间构建文件、可执行文件、库文件等。
当运行 CMake 并生成构建系统时,CMake 会自动设置 PROJECT_BINARY_DIR
。你不需要手动指定它。如果你在项目的根目录下创建了一个名为“build”的目录,并且在该目录内运行了 cmake ..
命令,那么 PROJECT_BINARY_DIR
就会被设置为这个“build”目录的路径。
PROJECT_BINARY_DIR
与 CMAKE_BINARY_DIR
类似,但在使用多个项目时(例如使用add_subdirectory
命令时),CMAKE_BINARY_DIR
指向最顶层项目的二进制目录,而 PROJECT_BINARY_DIR
指向当前项目的二进制目录。
在你的 CMake 脚本中,PROJECT_BINARY_DIR
可能会用于指定生成文件的位置,例如:
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)
在这里,${PROJECT_BINARY_DIR}
用于构建最终的 HEX 和 BIN 文件的完整路径。这意味着无论你将构建目录放在何处,生成的 HEX 和 BIN 文件都将在那个目录中创建。
.elf
.elf
文件扩展名代表“Executable and Linkable Format”(可执行和可链接格式),这是一种常用的文件格式,用于定义程序、库文件,以及内存镜像的格式。它是在UNIX系统上广泛使用的标准文件格式,特别是在Linux系统中。
ELF格式文件用于多种目的:
- 可执行文件:包含可以直接在操作系统上运行的程序。
- 共享库:如
.so
(在Unix系统上)或.dll
(在Windows上的类似物),包含可以被多个程序共同使用的代码。 - 对象文件:包含源代码编译后的机器代码,但还未链接成最终的可执行文件或库文件。
- 核心转储:当程序异常终止时,系统可以生成一个核心转储文件,它包含了程序终止时的内存镜像和其他调试信息。
ELF文件包含了一系列的头部信息,它描述了文件的组织结构,包括程序如何映射到内存、程序入口点的位置、所需的共享库以及其他重要的数据。
在嵌入式系统和跨平台开发中,.elf
文件是非常重要的,因为它们可以在不同的操作系统和硬件平台上以相同的方式被处理。例如,使用GNU工具链(如arm-none-eabi-gcc
)编译的ARM架构的嵌入式应用通常会生成.elf
格式的文件。这些文件然后可以被调试器(如GDB)用来加载、运行和调试程序。
.ioc
.ioc
文件是由 STM32CubeMX 软件生成的配置文件。STM32CubeMX 是 STMicroelectronics 提供的一个图形化工具,用于配置 STM32 微控制器的各种硬件特性(如时钟、外设、中断等)以及相关的中间件。
当你在 STM32CubeMX 中配置好微控制器的硬件特性后,你可以保存这些配置信息到一个 .ioc
文件中。这个文件包含了所有的配置数据,它可以被 STM32CubeMX 再次打开以修改配置,也可以用于生成初始化代码。生成的代码通常包括了微控制器的初始化代码和用于不同外设的配置代码。
在嵌入式项目的开发流程中,.ioc
文件非常重要,因为它提供了一种快速配置和引导新项目的方法,特别是在初期的硬件抽象层(HAL)代码开发阶段。此外,STM32CubeMX 还可以根据 .ioc
文件直接生成对应的 CMake 配置文件,从而整合到基于 CMake 的构建系统中。
DAP
“DAP”(Debug Access Port)是一个关键组成部分,用于ARM架构中的调试和系统级访问。它是ARM调试架构的核心,具体来说,DAP提供了以下特点和功能:
-
接口角色:
- DAP为调试工具(如JTAG或SWD调试器)与ARM处理器或系统芯片内部组件之间的通信提供了物理接口。
- 它是调试器与目标设备之间通信的中间件。
-
支持的协议:
- DAP可以通过JTAG(Joint Test Action Group)或SWD(Serial Wire Debug)两种主要协议之一来实现。
- JTAG是一种较老的多线接口,而SWD是一种更新、更高效的两线接口。
-
访问功能:
- DAP使调试器能够访问和控制目标ARM微控制器的核心资源,例如处理器的寄存器、内存和其他重要功能。
- 它允许执行诸如读写内存、读写寄存器、控制处理器操作等调试操作。
-
组件构成:
- DAP通常包含多个子组件,如Access Port(AP)和Debug Port(DP)。
- Debug Port是DAP的外部接口,负责与外部调试工具通信。
- Access Port是DAP的内部接口,负责与微控制器内部通信。
-
扩展性和多样性:
- DAP设计允许多个Access Port并行存在,这使得同时访问不同类型的资源(如内存、输入/输出、系统功能)成为可能。
- 这种设计为复杂的调试和系统检测提供了强大的灵活性。
-
对ARM体系结构的适应性:
- DAP是专为ARM处理器设计的,它与ARM的多种处理器系列和核心兼容。
- 它是ARM调试和系统级访问的标准组成部分,对于ARM基础设施的开发和调试至关重要。
总而言之,DAP是ARM架构中一个非常重要的部分,为开发者和工程师提供了强大的工具来访问和控制ARM微控制器的内部。通过DAP,可以有效地进行复杂的调试任务和系统级访问,这对于嵌入式系统开发、故障诊断和性能优化至关重要。
SWD
“SWD”(Serial Wire Debug)是一种用于调试和编程ARM微控制器的通信协议。它是专为ARM处理器设计的,旨在提供一种高效的调试接口。下面是SWD的详细解释:
-
基本概念:
- SWD是一个两线协议,只需要两个物理连接:一个数据线(SWDIO)和一个时钟线(SWCLK)。
- 它是JTAG(Joint Test Action Group)接口的替代方案,专门为减少所需引脚数量而设计。
-
与JTAG的比较:
- 相比传统的JTAG接口,SWD使用更少的线(两线对比JTAG的四线或五线)。
- 这种简化不仅减少了物理空间的需求,还简化了硬件设计和连接的复杂性。
-
功能和操作:
- SWD提供了对目标设备的调试和访问功能,包括读写寄存器、控制处理器、设置断点和观察点等。
- 它还支持实时存取内存,允许开发者在不中断目标设备运行的情况下进行调试。
-
调试接口:
- SWD作为一个调试接口,是与ARM的Debug Access Port(DAP)相连的,DAP负责与处理器核心和其他系统资源的交互。
- 通过这种连接,调试器可以通过SWD接口与ARM处理器进行通信。
-
高效性和优势:
- SWD的高效性体现在其简洁的物理接口和高数据吞吐量上。
- 对于小型和便携式设备,如智能手机和其他嵌入式系统,SWD尤其受欢迎,因为它有助于减少设计的复杂性和制造成本。
-
广泛的适用性:
- SWD已成为许多ARM微控制器和系统芯片的标准调试接口。
- 它被广泛用于从小型嵌入式设备到大型系统级应用的开发和调试。
总结来说,SWD是一种专为ARM处理器设计的高效、简洁的调试协议。它通过最小化所需的物理连接,提供了强大的调试和编程功能,使得它成为现代嵌入式系统开发中的重要工具。
JTAG
“JTAG”(Joint Test Action Group)是一种广泛使用的通信协议,主要用于测试、验证和调试电子系统,尤其是微处理器、微控制器和其他集成电路。以下是关于JTAG的详细解释:
-
历史和背景:
- JTAG的名字来源于其制定的组织——联合测试行动小组(Joint Test Action Group)。这个标准最初是为了简化电路板上集成电路的测试而设计的。
- 它被正式纳入IEEE标准,编号为IEEE 1149.1。
-
物理接口:
- JTAG接口通常包括至少四条线:TCK(测试时钟)、TDI(测试数据输入)、TDO(测试数据输出)和TMS(测试模式选择)。有时还包括一条可选的TRST(测试复位)线。
- 这些线路用于在JTAG兼容设备之间传输数据和指令。
-
功能和用途:
- JTAG用于访问连接在一起的集成电路上的测试访问端口(TAP)。通过这些端口,可以实现对设备内部状态的检查和控制。
- 它被用于执行诸如边界扫描测试(用于检测焊接故障)、编程、调试(设置断点、单步执行等)和验证。
-
调试能力:
- 在调试方面,JTAG允许开发者访问微控制器或处理器的内部寄存器,读写内存,甚至在某些情况下控制CPU的执行。
- 这使得JTAG成为微处理器和微控制器开发和维护的重要工具。
-
链式架构:
- JTAG支持所谓的“链式架构”,即多个JTAG兼容设备可以串联连接,通过单一的JTAG接口进行控制和访问。
- 这种设计简化了复杂系统中的测试和调试过程。
-
通用性:
- 虽然JTAG最初是为测试设计的,但它已经发展成为一个通用的工具,广泛应用于电子设计自动化(EDA)和电子系统的调试。
- 它被广泛支持,是多种微处理器和微控制器的标准接口。
-
扩展性和兼容性:
- JTAG标准后来得到了扩展,如IEEE 1149.7,增加了额外的功能和提高了效率。
- 它与其他调试和测试协议(如SWD)兼容,允许更灵活和强大的测试和调试能力。
总之,JTAG是一个强大且多功能的接口,被广泛用于电子系统的测试、编程和调试。它的通用性、灵活性和广泛的支持使其成为微处理器和微控制器开发的重要工具。
ST-Link
“ST-Link” 是 STMicroelectronics 开发的一种调试工具,专门用于其 STM32 和 STM8 微控制器系列。ST-Link 是一种专用的编程和调试接口,允许开发者与这些微控制器进行通信、编程和调试。以下是关于 ST-Link 的详细解释:
-
主要功能:
- 编程:ST-Link 允许开发者为 STM32 或 STM8 微控制器上传和下载程序。这是在开发周期中编写和测试代码的关键步骤。
- 调试:除了编程之外,ST-Link 也提供了调试功能,使开发者能够进行断点设置、单步执行、变量监视等常见调试操作。
-
接口支持:
- ST-Link 支持多种通信接口,包括 JTAG 和 SWD。这些接口使得 ST-Link 能够与不同的微控制器建立连接和通信。
- 其中,SWD(Serial Wire Debug)接口因为其简洁性(只需要两条线)在 STM32 微控制器中尤其受欢迎。
-
版本和型号:
- 随着时间的推移,ST-Link 经历了几代版本迭代,例如 ST-Link/V1、ST-Link/V2 和 ST-Link/V3。每一代都有其特定的功能增强和性能改进。
- 这些不同版本的 ST-Link 在物理尺寸、传输速度、接口支持等方面有所区别。
-
集成开发环境(IDE)兼容性:
- ST-Link 与多种集成开发环境(IDE)兼容,包括官方的 STM32CubeIDE、Keil MDK-ARM、IAR Embedded Workbench 等。
- 这种兼容性为开发者提供了灵活选择开发环境的自由,使得 ST-Link 成为了一个通用的调试和编程解决方案。
-
易用性和可访问性:
- ST-Link 设计简单易用,即插即用,方便开发者快速开始他们的项目。
- 它通常以独立的调试探针的形式存在,或者直接集成在一些 STM32 开发板上,如 STM32 Discovery 和 Nucleo 系列。
-
驱动程序和软件工具:
- 为了使用 ST-Link,开发者需要安装相应的驱动程序和软件工具。STMicroelectronics 提供了用于配置和操作 ST-Link 的官方软件工具,如 ST-LINK Utility。
-
广泛应用:
- 由于 STM32 和 STM8 微控制器的广泛应用,ST-Link 成为了嵌入式系统开发者的重要工具,尤其是在需要高效率和可靠性的应用场景中。
总之,ST-Link 是一种专为 STMicroelectronics 微控制器设计的编程和调试工具,以其兼容性、易用性和高效性而受到开发者的欢迎。它支持了从基本编程到复杂调试的全套功能,是 STM32 和 STM8 微控制器开发不可或缺的工具。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!