3、嵌入式Linux系统移植:交叉编译环境搭建、U-Boot移植与配置、Linux内核裁剪与编译、根文件系统制作(Buildroot/Yocto)

嵌入式Linux系统移植,说白了就是给咱们的EPON光网络终端(ONT)装上“大脑”和“灵魂”。你想想看,一个光猫要跑起来,光有硬件可不行,得有一套完整的软件栈。这套栈从底层到上层,依次是:引导加载程序(U-Boot)、Linux内核、根文件系统。今天我就带大家把这几个环节串一遍。

核心逻辑图:嵌入式Linux系统移植全景

EPON ONT 嵌入式Linux系统移植流程 交叉编译环境搭建 gcc-arm-linux-gnueabihf U-Boot移植与配置 引导加载程序 Linux内核裁剪 make menuconfig 根文件系统制作 Buildroot / Yocto 最终固件镜像 烧录到EPON ONT 从交叉编译环境 → U-Boot → 内核 → 根文件系统 → 最终固件

3.1 交叉编译环境搭建

咱们做嵌入式开发,第一件事就是搭交叉编译环境。为什么叫“交叉”?因为你的开发机(通常是x86架构的PC)和目标板(EPON ONT,一般是ARM或MIPS架构)的CPU不一样。你不可能在ONT上直接编译代码——那点资源跑个gcc都费劲。

我个人习惯用 gcc-arm-linux-gnueabihf 这个工具链。安装很简单,在Ubuntu上直接:

sudo apt-get install gcc-arm-linux-gnueabihf

但这里有个坑——我遇到过好几次,系统自带的工具链版本太老,编译出来的内核在启动时莫名其妙地崩溃。所以我现在更推荐从ARM官网或Linaro下载预编译的工具链。

我的小技巧: 下载后解压到 /opt/toolchains/ 目录,然后把 bin 目录加到 PATH 里。这样多个项目可以共用,不会污染系统。

验证环境是否搭好,跑一句:

arm-linux-gnueabihf-gcc --version

看到版本号输出,就说明环境OK了。嗯,这一步虽然基础,但后面所有工作都依赖它,马虎不得。

3.2 U-Boot移植与配置

U-Boot,全称是“Universal Boot Loader”。它负责初始化硬件、加载内核到内存、然后跳转到内核入口。说白了,它就是嵌入式系统的“BIOS”。

对于EPON ONT这种设备,U-Boot的移植主要做三件事:

  • 板级配置:在 board/ 目录下创建你的板子文件夹,定义好DDR、Flash、网口等参数。
  • 设备树(Device Tree):现在都流行用设备树来描述硬件,U-Boot也要支持。我建议直接拿厂商提供的参考设计改。
  • 网络启动支持:开发阶段用TFTP下载内核镜像,比反复烧写Flash快得多。

配置U-Boot的命令行参数时,我踩过一个坑:环境变量保存位置。有一次我把环境变量保存在了Flash的某个扇区,结果那个扇区和内核镜像重叠了,一保存环境变量,内核就坏了。后来我学乖了,先用 saveenv 测试一下,确认地址不冲突再正式用。

注意: U-Boot的 bootargs 参数一定要仔细核对。比如 console=ttyS0,115200 这个串口参数,波特率错了,你连控制台输出都看不到。

3.3 Linux内核裁剪与编译

Linux内核是个庞然大物,但咱们的ONT不需要那么多功能。裁剪内核,就是去掉用不到的驱动和子系统,让内核更小、启动更快。

我一般这样操作:

  1. make ARCH=arm defconfig 生成默认配置。
  2. 然后 make ARCH=arm menuconfig 进入图形界面,手动勾选需要的功能。

对于EPON ONT,下面这些是必须保留的:

功能模块 说明 裁剪建议
网络协议栈 TCP/IP、VLAN、桥接 必须保留,去掉IPv6可省空间
OMCI驱动 EPON管理通道 必须保留,否则无法注册
串口驱动 调试用 保留,量产时可去掉
文件系统支持 squashfs、jffs2 根据根文件系统类型选择

编译命令很简单:

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j4

这里 -j4 是并行编译,能快不少。我第一次编译内核时,傻等了好久,后来才发现没加这个参数。

经验之谈: 裁剪内核时,别贪心。我曾经为了省空间,把 devtmpfs 去掉了,结果系统启动后 /dev 目录是空的,所有设备都找不到。嗯,从那以后我每次裁剪完都会先跑一遍 make savedefconfig,把配置备份下来。

3.4 根文件系统制作(Buildroot / Yocto)

根文件系统,就是Linux启动后挂载在 / 的那个目录。它里面放着 /bin/etc/lib 这些基本目录和工具。对于嵌入式设备,我们一般不用完整的发行版,而是自己定制。

这里有两个主流工具:BuildrootYocto

  • Buildroot:轻量级,配置简单,适合小团队快速出活。我个人的项目大多用这个。
  • Yocto:功能强大,但学习曲线陡。适合大型项目,比如需要同时支持多个硬件平台。

用Buildroot制作根文件系统,基本流程是:

make menuconfig          # 选择目标架构、工具链、软件包
make                     # 开始编译

编译完成后,在 output/images/ 下会生成 rootfs.tarrootfs.squashfs。我一般用squashfs,因为它是只读的,能防止意外修改,而且压缩率高。

避坑指南: 我曾经在Buildroot里选了 busybox 的完整版,结果根文件系统大了好几兆。后来我改用 busybox 的最小配置,只保留 initshmount 等几个核心命令,空间一下子就省下来了。

如果你用Yocto,那就要准备好迎接它的“复杂性”了。Yocto的配置文件是 .bb.bbappend 文件,写起来像写Python。但它的好处是,一旦配好,后续的版本升级、补丁管理都非常方便。

最后,把U-Boot、内核镜像、设备树、根文件系统打包成一个固件,烧录到ONT的Flash里。上电,看串口输出——如果看到 Starting kernel ... 然后进入shell,恭喜你,移植成功了!


好了,这一章的内容就到这里。嵌入式Linux系统移植,说白了就是“搭积木”——把交叉编译环境、U-Boot、内核、根文件系统一块块拼起来。每一步都有坑,但只要你细心,多试几次,总能跑起来。