3. Linux内核编译与烧录:内核配置、设备树编译、分区表理解、烧录工具使用(RKDevTool)

这一章,我们聊聊嵌入式Linux开发中最基础、也最绕不开的一环——内核编译与烧录。很多刚入行的朋友觉得这步就是敲几个命令,等进度条跑完就完事了。其实不然。我在Rockchip平台上栽过不少跟头,后来才明白,内核配置、设备树、分区表、烧录工具这四块,每一块都有它的脾气。

说白了,你写的驱动再漂亮,如果内核没编对、设备树没配好、分区表搞错了、烧录工具不会用,板子就是跑不起来。嗯,咱们一个一个说。

3.1 内核配置:别用默认配置直接开干

拿到一个Rockchip的开发板,第一件事是什么?很多人会直接 make rockchip_linux_defconfig,然后就开始编译。我个人习惯是先看看这个defconfig到底开了什么。

我的习惯: 先执行 make menuconfig 进去扫一遍,重点关注三个地方:
  • Device Drivers → 你的外设驱动有没有被选中
  • File systems → 根文件系统类型是否匹配
  • General setup → Local version,加个自定义后缀方便区分

我在项目中遇到过一个问题:板子的以太网死活不通,查了两天硬件,最后发现是内核配置里把 CONFIG_REALTEK_PHY 给漏了。你说冤不冤?所以我的建议是:每次拿到新板子,先把 make savedefconfig 生成的 defconfig 和官方对比一下,差异一目了然。

另外,Rockchip 的 SDK 里通常有多个 defconfig,比如针对不同 DDR 容量、不同显示接口的变种。选错了,轻则某些功能用不了,重则起不来。我建议你直接看 arch/arm64/configs/ 下的文件名,一般命名规则是 芯片型号_板卡型号_defconfig。

3.2 设备树编译:DTS 改完别忘编译

设备树(Device Tree)是 Rockchip 平台硬件适配的核心。你改了一个 GPIO 的复用、加了一个 I2C 设备、调整了显示时序,都得动 DTS 文件。

编译设备树的命令很简单:

make dtbs

或者针对单板:

make rk3588-evb1-lp4.dtb

但这里有个坑——我见过不止一个同事,改了 DTS 文件后只编译了内核,没单独编译设备树,结果烧进去发现硬件没生效。为什么?因为内核编译流程里,make 默认会重新生成 dtb,但如果你用了 make modules 或者只编了部分代码,dtb 可能没更新。

我曾经踩过的坑: 有一次我改了一个 LED 的 GPIO 号,编了内核、烧了镜像,灯就是不亮。折腾半天,发现 dtb 还是旧的。从那以后,我每次改 DTS 都会手动执行一次 make dtbs,确保万无一失。

还有一点:Rockchip 的设备树是分层的。一个完整的 DTS 文件会 include 芯片级 .dtsi、SoC 级 .dtsi,最后才是板级 .dts。你改的时候要搞清楚改的是哪一层。我习惯在板级 .dts 里用 &pinctrl 这种引用方式覆写,而不是直接改 .dtsi,这样升级 SDK 时不容易冲突。

3.3 分区表理解:烧错分区等于白干

分区表,说白了就是告诉烧录工具:你的固件该往 Flash 的哪个位置写。Rockchip 平台用的是 parameter.txt 文件来定义分区。

一个典型的 parameter.txt 长这样:

FIRMWARE_VER: 1.0
MACHINE_MODEL: RK3588
MACHINE_ID: 007
MANUFACTURER: Rockchip
CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(misc),0x00020000@0x00008000(boot),0x00040000@0x00028000(recovery),0x00080000@0x00068000(rootfs),-@0x000e8000(userdata)

每个分区的格式是 大小@偏移(名称)。单位是 sector,一个 sector 通常是 512 字节。你想想看,如果大小算错了,或者偏移重叠了,烧进去的固件就会互相覆盖。

分区名 大小(sector) 偏移(sector) 用途
uboot 0x2000 (4MB) 0x4000 引导加载程序
misc 0x2000 (4MB) 0x6000 系统模式信息
boot 0x20000 (64MB) 0x8000 内核 + dtb
rootfs 0x80000 (256MB) 0x68000 根文件系统
userdata 剩余空间 0xE8000 用户数据

我在项目中遇到过最典型的问题:rootfs 分区大小设小了,导致文件系统解压到一半就报错。后来我学乖了,每次改分区表都会先算一下根文件系统镜像的实际大小,再留出 20% 的余量。

关键点: 分区表改了之后,烧录工具里的地址也要同步更新。RKDevTool 的配置文件中,每个镜像的烧录地址必须和 parameter.txt 里的偏移一致。

3.4 烧录工具使用:RKDevTool 的正确打开方式

RKDevTool 是 Rockchip 官方的烧录工具,支持 USB 和 SD 卡两种模式。我个人更常用 USB 模式,因为速度快、操作简单。

基本流程是这样的:

  1. 板子进入 MaskROM 模式(按住 Recovery 键上电,或者短接 EMMC 的 CLK 和 GND)
  2. 打开 RKDevTool,点击「切换」按钮,确保设备已识别
  3. 在「下载镜像」页面,按分区表配置好每个镜像的路径和地址
  4. 点击「执行」开始烧录

这里有个细节:RKDevTool 的地址是十六进制的,而且单位是 sector。你从 parameter.txt 里看到的偏移,直接填进去就行。但要注意,有些版本的 RKDevTool 地址单位是字节,需要乘以 512。我建议你烧录前先看一眼工具界面上的提示,确认单位。

我曾经踩过的坑: 有一次我烧录时忘了勾选「强制按地址写」,结果工具自动把镜像写到了默认位置,覆盖了 uboot。板子直接变砖。后来我养成了习惯:每次烧录前都检查一遍配置,特别是地址和勾选框。

另外,如果你用的是 SD 卡启动,需要用 SD_Firmware_Tool 制作启动卡。这个工具会把整个固件包(包括分区表)写到 SD 卡上。我个人觉得 SD 卡模式适合调试阶段,因为换固件方便,不用每次都插拔 USB。

3.5 本章知识体系

下面这张图把内核编译与烧录的完整流程串起来了,你可以对照着看:

Linux内核编译与烧录流程 内核编译与烧录完整流程 内核配置 make menuconfig 设备树编译 make dtbs 分区表 parameter.txt 编译内核 make -j8 生成镜像 boot.img / rootfs.img 烧录 RKDevTool / SD_Firmware_Tool 注意事项 • 分区地址必须对齐 • 烧录前确认MaskROM模式 • 改DTS后记得编dtb • 分区大小留余量

从图上你能看到,内核配置、设备树、分区表是三个并行的输入,最终汇聚到编译环节,生成镜像后再烧录到板子上。任何一个环节出问题,都会导致最终结果不对。

嗯,这一章的内容就这些。内核编译与烧录看似基础,但细节很多。你只要把配置、设备树、分区表、烧录工具这四个点吃透,后面写驱动、调硬件的时候就会顺畅很多。