文章目录
1. 交叉编译
交叉编译是指在一种计算机体系结构上生成在另一种计算机体系结构上运行的可执行代码的过程。具体来说,我们在PC机上编译程序,这些程序是为了在另一种架构(例如ARM)上运行的。
为什么需要交叉编译
-
性能限制:
- 虽然ARM板性能越来越强,但在很多情况下,它的性能仍然无法与PC机相比。因此,直接在ARM板上进行编译可能会很慢,甚至无法完成编译过程。
- 使用PC机进行编译,可以利用其强大的计算能力,提高编译速度和效率。
-
工具链问题:
- 通常我们使用的编译工具(如gcc)是为PC机编写的,这些工具生成的是PC机上可运行的X86指令。
- ARM板上的架构不同,无法直接运行这些指令,因此需要使用专门的交叉编译工具链来生成ARM架构的可执行代码。
交叉编译的工具链
交叉编译工具链是一套在一种体系结构(如X86)的机器上运行,但生成另一种体系结构(如ARM)的机器码的编译工具。它包括:
- 编译器(如gcc)
- 链接器
- 汇编器
这些工具被配置为生成适用于目标体系结构的二进制文件。
为什么叫“交叉”?
-
PC与ARM的交互:
- 在整个开发过程中,PC机与ARM板之间不断交互。PC机负责编写、编译和生成目标文件,ARM板负责运行和验证程序。
- 这种编译和运行环境的交替使用,形成了一个交叉的工作流程。
-
工具链的交叉使用:
- 交叉编译工具链是在一种体系结构上运行(如PC机上的X86架构),生成另一种体系结构上运行的代码(如ARM架构)。
- 这种工具链的使用方式也体现了“交叉”的含义。
交叉编译的流程
-
编写和编译源代码:
- 在PC机上编写源代码,并使用交叉编译器进行编译。
-
生成目标代码:
- 编译器生成适用于目标体系结构(如ARM)的机器码。
-
传输和运行:
- 将生成的目标代码传输到目标设备(如ARM开发板)上运行和验证。
-
调试和修改:
- 如果发现问题,返回PC机进行修改和重新编译,然后再次传输到目标设备进行测试。
这个过程不断循环,直到程序正确运行。
交叉编译的优点
- 高效开发:利用PC机的高性能进行编译,提高开发效率。
- 灵活性强:可以在不同的目标平台之间快速切换,适应多种开发需求。
- 易于调试:在PC机上调试代码,发现问题后快速修复和重新编译。
实际应用
例如,使用交叉编译工具链在PC机上编译ARM板程序,然后将生成的二进制文件通过USB或网络传输到ARM板上运行和测试。这种方法在嵌入式开发中非常常见,可以显著提高开发和调试效率。
2. 交叉工具链
交叉编译工具链是指在一个平台(如 PC)上编写和编译代码,并生成可以在另一个平台(如 ARM 板)上运行的可执行文件的工具集。这些工具链通常包含编译器、链接器和库等组件。
1. Ubuntu 平台
-
arm-linux-gcc:
- 这是一个早期的交叉编译工具链,基于 GNU Compiler Collection (GCC)。
- 主要用于编译针对 ARM Linux 平台的程序。
- 通常包含在 GNU Binutils 中,包括编译器、汇编器、链接器和调试器。
-
arm-linux-gnueabihf-gcc:
- “gnueabihf”代表“GNU Embedded Application Binary Interface, Hard Float”。
- 这个工具链针对 ARM 硬件浮点单元进行了优化,可以生成更高效的浮点运算代码。
- 适用于现代的 ARM Cortex-A 系列处理器,通常用于嵌入式 Linux 系统。
2. Windows 平台
-
ADS (ARM Developer Suite):
- 使用
armcc
编译器,这是 ARM 公司开发的专有编译器。 - 提供了一个全面的开发环境,包括编译器、汇编器、链接器和调试工具。
- 常用于嵌入式系统开发,如 Keil MDK 或 ARM DS-5 中。
- 使用
-
Cygwin 环境:
- arm-elf-gcc:
- 在 Cygwin 上运行的 GCC 编译器,支持 ELF(Executable and Linkable Format)。
- 允许在 Windows 上使用 GNU 工具链进行交叉编译。
- arm-elf-gcc:
3. MacOS 平台
-
Homebrew:
- 使用 Homebrew 包管理器可以安装 GCC 交叉编译器:
-
Xcode:
- Xcode 中集成了支持 ARM 架构的工具,但主要针对 iOS 开发。
- 可以配置使用 GCC 或 Clang 进行交叉编译。
3. 验证实例
编写并编译程序
首先在PC上编写一个的C程序,并使用gcc
进行编译:
#include <stdio.h>
int main()
{
printf("abc\n");
return 0;
}
在虚拟机上编译并运行:
gcc main.c -o abc
./abc
输出:
abc
在这个步骤中使用的是标准的GCC编译器,生成了一个在当前PC平台(通常是x86架构)上可以运行的可执行文件。通过运行这个文件,得到了预期的输出abc
,说明程序在PC上运行正常。
将可执行文件放到目标板上
接下来尝试将这个可执行文件传输到目标板(ARM架构)上运行:
修改文件权限,使其在目标板上可执行:
chmod 777 abc
在目标板上运行:
./abc
输出:
./abc: line 1: syntax error: unexpected "("
在目标板上运行这个文件时出现了错误。这是因为在PC上编译的可执行文件是针对x86架构的,而目标板是ARM架构,无法直接运行x86架构的可执行文件。这种情况下,我们需要进行交叉编译。
安装交叉编译工具链
在Ubuntu平台,我们可以使用以下步骤来安装交叉编译工具链:
-
更新包管理器并安装工具链:
sudo apt-get update sudo apt-get install gcc-arm-linux-gnueabihf
-
编译程序:
arm-linux-gnueabihf-gcc main.c -o abc
-
将编译好的可执行文件传输到目标板,并运行:
scp abc user@target_ip:/path/to/target
ssh user@target_ip
cd /path/to/target
./abc
通过上述步骤,就可以在PC上编写代码,使用交叉编译工具链生成ARM架构的可执行文件,并在目标板上成功运行。
4. GCC和编译器的区别
可能有人会疑惑,既然可以使用像keil这样的编译器一键烧录代码到单片机中,为什么还要使用gcc呢?
这个问题涉及开发工具链的选择和使用场景的不同。Keil和GCC各自有其优缺点和适用场景。
Keil
优点
- 集成环境:所有开发工具都集成在一个IDE中,提供了代码编辑、编译、调试和烧录的完整解决方案。
- 图形化界面:操作简单直观,减少了命令行的使用,适合不熟悉命令行的开发者。
- 库和示例代码:丰富的库和示例代码可以帮助快速开发,提高生产力。
- 优化和调试工具:强大的编译优化和调试工具,生成高效的代码并提供详细的调试信息。
缺点
- 跨平台限制:Keil主要支持Windows平台,跨平台支持不如GCC。
- 开源和社区支持:Keil是商业软件,虽然提供免费版本,但功能有限,并且社区支持不如开源的GCC。
- 自动化构建:虽然Keil也支持命令行操作,但其自动化构建和集成CI/CD流水线的能力不如GCC灵活。
GCC
优点
- 跨平台支持:可以在多种操作系统上使用,适合跨平台项目开发。
- 开源免费:没有使用限制和授权费用,适合开源项目和预算有限的团队。
- 自动化构建:GCC适合大型项目和团队协作,可以结合Makefile或CMake进行自动化构建,方便集成到CI/CD流水线中。
- 灵活性和可定制性:提供大量的编译选项和优化参数,可以根据项目需求进行灵活调整。
缺点
- 学习曲线:需要熟悉命令行操作和Makefile或CMake等构建工具,初学者可能觉得较难上手。
- 库支持:虽然也有丰富的库,但针对特定硬件的支持和示例代码不如Keil完善。
- 图形化界面:缺乏一体化的图形化IDE,虽然有如Eclipse、VSCode等编辑器支持,但需要额外配置。
使用流程对比
Keil使用流程
- 编写代码:在Keil的IDE中编写C代码。
- 编译:点击编译按钮,将C代码编译为机器码。
- 烧录:通过Keil的烧录工具将机器码写入STM32单片机。
- 调试:在Keil的调试工具中进行单步调试、变量监视和内存查看等操作。
GCC使用流程
1. 编写代码:在任意文本编辑器中编写C代码(如VSCode、Vim等)。
2. 编译:使用GCC命令行工具进行编译,例如arm-none-eabi-gcc
,将C代码编译为机器码。
arm-none-eabi-gcc -o output.elf main.c
3. 烧录:使用开放的烧录工具(如stlink、OpenOCD等)将机器码写入STM32单片机。
st-flash write output.elf 0x8000000
4. 调试:使用GDB等调试工具进行调试,通过命令行或集成到编辑器中的调试插件进行单步调试。