1. 课程导论与环境搭建

各位同学,欢迎来到《Linux ARM架构驱动移植与系统启动优化实战》的第一章。

做嵌入式Linux开发,说白了就是跟硬件和内核打交道。你想想看,没有一套顺手的开发环境,后面所有的工作都像在沙子上盖楼。这一章,我们先打好地基。

1.1 ARM架构演进史:从简单到复杂

ARM架构的发展,我算是亲眼见证了它从低功耗单片机走向服务器级别的过程。早期做驱动时,ARM9和Cortex-M系列用得最多,现在Cortex-A系列几乎统治了移动设备和物联网网关。

我个人习惯把ARM架构分成几个关键阶段:

架构版本 代表核心 关键特性 我的印象
ARMv4/ARMv5 ARM7TDMI, ARM9 冯·诺依曼结构,5级流水线 经典,但指令集简单
ARMv6 ARM11 SIMD指令,Jazelle技术 多媒体能力开始增强
ARMv7-A Cortex-A8/A9/A15 多核,NEON,VFPv3 移动时代的基石,我在这上面踩过不少坑
ARMv8-A Cortex-A53/A72/A76 64位,AArch64/AArch32双态 性能飞跃,兼容性复杂
ARMv9-A Cortex-X2/A710 机密计算,SVE2 面向未来,安全增强
避坑指南: 我曾经在移植一个老驱动到Cortex-A53时,发现它死活不工作。查了三天,最后发现是ARMv8的异常级别(EL1/EL2/EL3)配置错了。记住,64位模式下,内核跑在EL1,Hypervisor在EL2,安全固件在EL3。这个层级关系搞反了,系统直接挂掉。

为什么ARM能这么成功?我个人觉得,关键在于它的授权模式和低功耗设计。你想想看,一个架构能同时用在你的手机、路由器、甚至服务器里,这本身就是生态的力量。

1.2 Linux内核源码获取与配置

获取内核源码,我建议直接从主线仓库拉取。别用那些过时的发行版自带内核,除非你确定要修一个特定的老bug。

# 获取主线内核(推荐)
git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

# 或者获取稳定版
git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

# 进入目录,查看分支
cd linux
git branch -a

配置内核,我个人习惯用make menuconfig。它基于ncurses,在终端里操作直观。但如果你在做一个新板子,我建议从defconfig开始。

核心配置流程:
  1. 选择架构: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
  2. 微调配置: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
  3. 保存配置: 退出时选择保存为.config
  4. 编译内核: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4 zImage
  5. 编译设备树: make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs
注意: 配置内核时,别一股脑把所有驱动都选上。我曾经编译了一个包含所有模块的内核,结果镜像大了3倍,启动时间长了5秒。对于嵌入式设备,按需配置是基本原则。只选你板子上有的硬件驱动,其他的统统去掉。

1.3 交叉编译工具链搭建

交叉编译,说白了就是在你的x86电脑上编译出能在ARM上跑的程序。工具链的选择,我建议用Linaro提供的预编译版本,省时省力。

我个人习惯用gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf这个版本,稳定且兼容性好。

# 下载并解压
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
tar -xf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

# 设置环境变量(建议写入 ~/.bashrc)
export PATH=$PATH:/path/to/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin
export CROSS_COMPILE=arm-linux-gnueabihf-
export ARCH=arm

# 验证
arm-linux-gnueabihf-gcc --version
小技巧: 如果你需要调试内核,我建议同时安装gdb-multiarch。它支持多种架构,调试ARM内核时特别方便。我曾经用它在QEMU里单步调试过中断处理流程,那感觉,就像在硬件上跑一样。

1.4 QEMU模拟环境部署

QEMU,嵌入式开发者的瑞士军刀。在没有真实板子的时候,它就是你的调试利器。我建议用qemu-system-arm来模拟ARM平台。

我个人最常用的模拟平台是vexpress-a9,它支持设备树,配置灵活。

# 安装QEMU(Ubuntu/Debian)
sudo apt-get install qemu-system-arm

# 启动内核(使用我们之前编译的zImage和dtb)
qemu-system-arm \
    -M vexpress-a9 \
    -kernel arch/arm/boot/zImage \
    -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb \
    -append "console=ttyAMA0,115200 root=/dev/mmcblk0" \
    -sd rootfs.ext4 \
    -nographic

为什么用-nographic?因为这样QEMU会把串口输出重定向到当前终端,方便我们看内核启动日志。我调试驱动时,经常开着两个终端:一个跑QEMU看日志,一个编辑代码。

QEMU调试内核的常用参数:
  • -s:在端口1234开启GDB服务器
  • -S:启动时暂停CPU,等待GDB连接
  • -d in_asm:打印执行的指令流(调试汇编时有用)
  • -m 512M:分配512MB内存给模拟器

你想想看,有了QEMU,你可以在你的笔记本上模拟一个完整的ARM系统。我当年做驱动移植时,就是先在QEMU上验证逻辑,再烧到真实板子上。这样能省下大量烧写和重启的时间。

1.5 本章知识体系

下面这张图,是我梳理的本章核心知识结构。你可以把它当作一个地图,随时回来查阅。

第一章知识体系图 环境搭建核心 ARM架构演进 ARMv7 → ARMv8 → ARMv9 异常级别:EL0-EL3 内核源码获取 git clone 主线/稳定版 make menuconfig 配置 交叉编译工具链 Linaro GCC 预编译 CROSS_COMPILE 环境变量 QEMU模拟环境 vexpress-a9 平台 -s -S GDB调试

这张图把本章的四个核心模块串起来了。从ARM架构开始,理解硬件基础;然后获取和配置内核源码;接着搭建交叉编译工具链;最后用QEMU验证整个环境。每一步都是下一步的前提。

常见问题: 很多新手在配置内核时,会忘记设置ARCH和CROSS_COMPILE环境变量。结果编译出来的内核是x86的,放到ARM上当然跑不起来。我建议你把这两个变量写入~/.bashrc,这样每次打开终端都自动生效。

好了,环境搭建就讲到这里。记住,一个干净、可复现的开发环境,是高效工作的前提。别嫌麻烦,把每一步都走扎实了,后面写驱动、调启动流程时,你会感谢现在的自己。