第1章 ARM平台与嵌入式Linux概述

各位同学,咱们开始第一课。做嵌入式Linux开发,说白了就是跟ARM和Linux内核打交道。我入行那会儿,ARM还是ARM9、ARM11的天下,现在Cortex系列已经铺天盖地了。这一章,咱们把基础打牢。

1.1 ARM架构演进史

ARM从1985年的Acorn RISC Machine起步,最初只是给Acorn电脑用的。后来发现这东西省电、体积小,特别适合移动设备。我最早接触ARM7TDMI,那会儿还在做MP3播放器,一颗芯片搞定所有。

ARM架构的几个关键节点:

  • ARMv4T:引入Thumb指令集,代码密度提升30%。
  • ARMv5TE:加入DSP指令扩展,信号处理能力增强。
  • ARMv6:支持SIMD,多媒体性能起飞。
  • ARMv7-A:Cortex-A系列诞生,多核、乱序执行,性能大幅提升。
  • ARMv8-A:64位架构,兼容32位,现在主流。
  • ARMv9-A:强化安全、AI、虚拟化,未来方向。

为什么会从v7跳到v8?因为32位地址空间不够用了。我记得2012年做平板项目,内存加到2GB就遇到瓶颈,后来换Cortex-A53才解决。

1.2 Cortex-A/R/M系列选型

ARM把Cortex分成三个系列,各有侧重。选型错了,项目就废了一半。

系列 典型型号 应用场景 特点
Cortex-A A53, A72, A76 手机、平板、服务器 高性能,支持MMU,跑Linux
Cortex-R R4, R5, R52 汽车、工业控制 实时性强,中断延迟低
Cortex-M M0, M3, M4, M7 物联网、传感器、电机控制 超低功耗,裸机或RTOS

我个人习惯:跑Linux选Cortex-A,跑RTOS选Cortex-R,做低功耗传感器选Cortex-M。但注意,Cortex-M也能跑Linux?不行,它没有MMU,Linux必须MMU支持。我曾经有个同事非要在M4上跑Linux,折腾两周放弃了。

选型避坑指南:我曾经在智能网关项目里选了Cortex-A7,结果发现需要硬实时控制,中断响应不够快。后来换成Cortex-R5,问题解决。记住:A系列追求吞吐量,R系列追求确定性。

1.3 嵌入式Linux系统组成

一个完整的嵌入式Linux系统,从底层到上层,大概分这么几块:

  1. Bootloader:引导程序,初始化硬件,加载内核。常见的有U-Boot、Barebox。
  2. Linux内核:操作系统的核心,管理进程、内存、设备驱动。
  3. 根文件系统:存放应用程序、库、配置文件。常用BusyBox、Buildroot构建。
  4. 用户空间:应用程序、服务、守护进程。

你想想看,系统上电后,Bootloader先跑,然后加载内核,内核挂载根文件系统,最后启动init进程。这个流程我调试过无数次,每次出问题都从Bootloader开始查。

小技巧:调试阶段,我习惯用NFS挂载根文件系统,这样修改代码后不用重新烧录,直接重启就行。开发效率提升一倍。

下面这张图展示了嵌入式Linux系统的整体架构:

嵌入式Linux系统架构 用户空间 (User Space) 应用程序 (App) | 服务 (Daemon) | 库 (libc, libpthread) Shell | 网络协议栈 | 文件系统工具 内核空间 (Kernel Space) 进程调度 | 内存管理 | 虚拟文件系统 (VFS) 网络协议栈 | 设备驱动 | 系统调用接口 中断处理 | 内核线程 硬件抽象层 (HAL / BSP) 硬件平台 (ARM SoC + 外设) 应用层 内核层 硬件层

1.4 交叉编译环境搭建

嵌入式开发,目标板资源有限,不能直接在板子上编译。所以我们在PC上编译,生成目标板能运行的二进制文件。这就是交叉编译。

搭建交叉编译环境,我一般分三步走:

  1. 安装交叉编译工具链:比如arm-linux-gnueabihf-gcc,可以从Linaro、ARM官网下载,或者用Buildroot自己编译。
  2. 配置环境变量:把工具链路径加到PATH里,方便调用。
  3. 测试编译:写个Hello World,编译后放到目标板上运行。

举个例子,我用Linaro的gcc 7.5.0版本:

# 下载工具链
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

# 解压到 /opt
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt

# 设置环境变量
export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH

# 测试编译
arm-linux-gnueabihf-gcc -o hello hello.c
file hello
# 输出: hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)

注意:工具链版本必须与内核版本匹配。我曾经用gcc 9编译Linux 4.9内核,结果编译出来的内核启动就崩溃。后来换成gcc 7才正常。建议用Linaro官方推荐的版本组合。

交叉编译环境搭建好了,下一步就是配置内核、裁剪驱动。这些内容咱们后面章节慢慢展开。