文章目录
背景
- 传统STM32开发常用keil,keil同时集成了代码编辑、文件编译、调试的功能,用起来方便快捷。
- 但是,keil为付费软件,在版权要求较为严格的场景中不适用。且Keil不可以跨平台使用,还存在代码提示不完善、界面功能老旧的问题。
- 因此,本文将和读者一起了解STM32代码编译的原理,使我们更深刻得理解STM32从c文件代码到hex烧录文件背后的原理,拓宽自己的技术栈。
STM32代码编译过程及常见工具介绍
编译过程
- 众所周知,在.c文件转换为二进制bin文件的过程中,将依次经历以下过程:
- 代码预处理: 包括处理各种宏定义。预处理由预处理器(Preprocessor)完成,例如在 C/C++ 中是由 gcc 或 g++ 中的预处理器部分负责。预处理器处理源文件中的预处理指令(如 #include、#define、#ifdef 等),展开宏定义,进行条件编译等操作,生成经过预处理的中间文件(通常是以 .i 或者在内存中处理后)。
- 编译和汇编阶段: 此阶段,并生成临时二进制文件(.o 文件)。编译阶段由编译器完成。在 C/C++ 开发中,常用的编译器包括 gcc(GNU Compiler Collection)或者特定厂商提供的编译器,如keil的 ARM GCC。编译器将预处理后的文件(通常是以 .i 结尾的文件)转换为汇编语言(Assembly Language)文件(通常是以 .s 结尾的文件),然后将其转换为机器可执行的目标文件(通常是以 .o 结尾的文件)。
- 链接: 链接器将编译生成的 .o 文件,以及所需的库文件和启动文件(startup files),进行链接。链接过程将所有的目标文件合并成一个可执行文件(.elf 文件)。链接阶段由链接器(Linker)完成。链接器将编译器生成的多个目标文件(.o 文件)、库文件(如静态库 .a 或动态库 .so)以及启动文件(startup files)等链接在一起,形成最终的可执行文件或者目标文件(如 ELF 格式的可执行文件)。在 C/C++ 开发中,常用的链接器有 GNU ld(GNU Linker)。
- 生成二进制文件(.bin): 从生成的 .elf 文件中,使用特定的工具(例如 objcopy),提取出需要的二进制数据并格式化为二进制文件(.bin 文件)。通常,这个二进制文件包含了程序的代码段和数据段,可以直接加载到 STM32 的内存中运行。
- 烧录: 最后,将生成的 .bin 文件通过烧录工具(例如 ST-Link 或者 JTAG 调试器)烧录到目标的 STM32 微控制器中。这个过程将程序加载到芯片的闪存(Flash)中,使得 STM32 可以运行这个程序。
- 了解了上述编译流程后,我们只需要依次的选择工具,一步一步的进行转换即可。
常见工具
- 我们了解了上述编译过程之后,可能还是会看着cmake、make、ninja、cmakelist.txt、makefile等一些东西一头雾水。这就是理论原理和实际工具之间的差异。
- 我们上面说了GCC、GNU ld等工具,他们是负责代码的转换的,即将.c代码转换为二进制文件。
- 但是我们实际的工程,有很复杂的文件架构,很多个.c文件,且互相之间存在依赖关系,如果让人指定一条一条的编译,最后再链接,就很复杂。
make工具及makefile文件
- 因此,早在1976年,就产生了自动化的构建管理工具 make ,即我们命令行中常见的make。用于管理源代码的编译和链接过程。其原理是通过读取名为 Makefile 的文件来确定如何编译和链接源文件,从而生成可执行文件或者库文件。
- 在Makefile 文件中定义了目标(targets)、依赖关系(dependencies)和命令(commands),Make 根据这些规则来执行构建任务,确保只有修改的文件及其相关依赖才会重新编译。makefile文件如下:cubemx生成的makefile
- 在makefile文件中指定了编译后存放的路径、要编译的源文件有哪些、编译目标等信息,在早期需要程序员手动维护makefile文件,以确定编译顺序。
- 因此,我们在编译过程时,不需要手动地一条条进行编译,而是可以cd到makefile文件下,运行make命令,就可以完成整个工程的编译。
Ninja工具
- 随着时代发展,项目越来越大,使用make工具进行构建的时间越来越长,make工具面临着效率不高、并行处理和依赖分析方面效率低的问题。
- 且make工具最初是为linux设计的,在win上运行困难。因此,google的工程师开发了一个简洁高效、跨平台、可以并行构建的工具:Ninja 。
- 与make工具通过makefile工作一样,ninja通过build.ninja文件进行指定编译顺序及路径。程序员可以之间编写build.ninja文件,如下图。但目前一般是通过更上层的工具自动生成该文件了。
CMake工具及CMakeLists.txt 文件
- 随着计算机软件开发的发展,项目需要在不同的操作系统和编译器上进行构建。因此同一套代码,可能使用visual studio编译器、也可能使用MinGW编译器,可能生成的目标平台是windows、也可能是linux,而每个平台和编译器都有自己的构建系统和配置需求。
- 这要求不仅仅需要make这种构建管理工具对工程内的.c文件的编译顺序进行管理,还需要一套工具可以对构建系统进行管理,根据不同的目标选择不同的构建工具,如选择Visual studio、还是选择ninja、还是选择make。
- 而庞大的项目,编写make工具的makefile、ninja工具的build.ninja都是一个很困难的事情。
- 因此,在2000年,诞生了cmake工具。CMake 的产生是为了解决跨平台构建配置的问题。它提供了一种高级语言来描述项目的构建过程和依赖关系,然后根据操作系统和编译器生成适用于不同构建系统(如 Make、Ninja、Visual Studio 等)的配置文件。
- cmake通过使用 CMakeLists.txt 文件进行工作,程序员通过编写更简洁的CMakeLists.txt 可以定义项目的目录结构、源文件列表、编译选项和链接库,然后再指定cmake是要生成makefile文件还是build.ninja文件,从而可以实现跨平台和复杂项目的统一构建管理。
- CMakeLists.txt更加简洁,可由程序员手动维护。
工具链配置
代码编写:VSCode
- 首先,我们下载并安装好VSCode,用于代码编写。
- 这里已经默认大家安装成功,不详细介绍安装过程。
工程配置及生成:CubeMX
- 使用CubeMX可以用于STM32的工程配置。
- 这里已经默认大家安装成功,不详细介绍安装过程。
- 在配置好工程之后,在最后的代码生成阶段,选择生成cmake。如果没有该选项,可能需要先下载cmake并将其加到系统的环境变量中。如下:
工程管理工具:CMake及CMakeLists.txt文件
- 上面在CubeMX中配置好过程后,已经自动生成了CMakeLists.txt文件,用于指导CMake进行编译。
- 首先我们下载并安装cmake,链接如下:https://cmake.org/![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/2e74c1af8d7e4600b69e753d4b6c0603.png)
- cmake解压后不需要安装,我们将其放到英文路径的文件夹下,并将bin目录添加到环境变量里,使系统可以找到:
- 在命令行运行 cmake --help,有输出,即表示安装完成
- 我们可以看的,cmake支持生成的配置工具文件有很多:包括ninja、make、VS等
构建工具:ninja
- 上面我们选择了CMake进行工程管理,CMake可以生成ninja的build.ninja配置文件,ninja按照该配置文件指导编译器进行依次编译即可。
- 首先我们下载ninja,官网:https://ninja-build.org/
- 下载链接:https://github.com/ninja-build/ninja/releases![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/71300da594e0415fabaf2c5b364f6135.png)
- 下载好后,解压,将目录添加到系统环境变量:
- 在命令行运行ninja --version,有输出,表示安装成功
编译器:arm-none-eabi-gcc
- 上面我们讲过,最终负责将.c文件转换为.o文件并链接最终生成bin文件的,是编译器。
- 在win系统上面,一般常见的编译器是Visual Studio和GCC,但是这些编译器是针对通用操作系统的。
- 对于STM32,目前的编译器有2个可以选择,一个是keil的编译器ARMCC,如下:
- 另一个是STM32架构设计者ARM官方的提供的编译器:gcc-arm-none-enbi,下载链接如下:https://developer.arm.com/downloads/-/gnu-rm![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/8c529d9f64d04ca9a2893184a56e687d.png)
- 下载后安装,并将bin路径添加到环境变量即可,在命令行运行:arm-none-eabi-gcc -v,有输出,表示安装成功:
编译方法
- 自此,我们搭建了完整的编译器arm-none-eabi-gcc、自动化构建工具ninja、项目管理工具cmake,可以将.c文件输出生成为elf文件了。
- 我们使用vscode打开cubemx生成后的文件夹:
- 首先,我们使用cmake,按照cubemx生成的cmakelist.txt文件,生成相应的ninja配置文件。执行命令如下:
cmake -B build -G"Ninja"
- 其中,-B是说生成的配置文件目录为build,-G是说明生成的配置文件目标为Ninja。
- 运行之后,
- 我们可以看的多了build文件夹,且该文件夹内有build.ninja文件:
- 然后,我们通过ninja工具,调用arm-none-eabi-gcc编译器,进行编译即可,执行命令:
ninja -C build
- 其中,-C是说明build.ninja所在路径为当前路径下的build目录(content)。
- 运行之后:
- 可以看的,编译成功,生成了elf文件,elf文件可以之间用调试软件加载到调试器中进行调试,也可以转换为bin文件或者hex文件。
参考
- cubemx生成的makefile
本文转载自: https://blog.csdn.net/wcc243588569/article/details/140269560
版权归原作者 天城寺电子 所有, 如有侵权,请联系我们删除。
版权归原作者 天城寺电子 所有, 如有侵权,请联系我们删除。