第3章:Linux内核编译与烧录——从配置到跑起来

说实话,很多刚接触R-Car平台的工程师,最头疼的不是写驱动代码,而是怎么把内核正确编译出来、烧到板子上。我见过有人卡在menuconfig里三天出不来,也有人烧录后板子直接变砖。这一章,咱们就把这条路走通。

内核编译与烧录,说白了就三步:配置、编译、部署。但每一步都有坑。我把自己踩过的坑、总结的经验,全放在这里了。

本章核心目标:在R-Car M3N开发板上,完成Linux内核的menuconfig配置、设备树编译、最终烧录到SD卡并成功启动。

3.1 内核配置——menuconfig的正确打开方式

内核配置不是让你从头造轮子。R-Car官方已经提供了基础配置,咱们要做的是“裁剪+适配”。

第一步:加载基础配置

# 进入内核源码目录
cd linux-5.10.41-rcar

# 加载R-Car M3N的默认配置
make ARCH=arm64 defconfig
make ARCH=arm64 menuconfig

我个人习惯先执行defconfig,再进menuconfig微调。为什么?因为默认配置已经包含了大部分通用驱动,咱们只需要关注R-Car特有的部分。

第二步:关键配置项

在menuconfig界面里,这几个地方必须检查:

配置路径 配置项 说明
Device Drivers → SPI support Renesas R-Car SPI controller SPI总线驱动,很多传感器都用这个
Device Drivers → I2C support Renesas R-Car I2C bus controller I2C总线,R-Car的标配
Device Drivers → Network device support Renesas Ethernet AVB support 千兆以太网,调试必备
Device Drivers → Multimedia support Renesas VSP1 / DU support 显示和图像处理
File systems ext4 / vfat / squashfs 根文件系统类型

我的小技巧:用/键搜索功能。比如你想找“R-Car SPI”,直接按/输入关键字,比一层层翻菜单快得多。我在项目中经常用这招,省了不少时间。

第三步:保存配置

配置完成后,按Exit退出,系统会提示保存。默认保存到.config文件。我建议你额外备份一份:

cp .config config_rcar_m3n_v1

嗯,这里要注意:每次修改配置前,最好都备份一下。我曾经手滑把配置清空了,结果重配花了一下午。

3.2 内核编译——让代码变成二进制

配置搞定,接下来就是编译。R-Car M3N是ARM64架构,所以交叉编译工具链必须选对。

设置环境变量:

export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin

我个人用的是Linaro的7.5.0版本,稳定可靠。如果你用其他版本,记得确认兼容性。

开始编译:

# 编译内核镜像
make -j4 Image

# 编译设备树
make -j4 dtbs

# 编译内核模块
make -j4 modules

-j4表示用4个线程并行编译。我建议根据你电脑的CPU核心数来设,比如8核就设-j8。编译时间大概5-15分钟,取决于你的机器性能。

常见错误:如果编译报错“No rule to make target 'Image'”,八成是ARCH或CROSS_COMPILE没设对。检查一下环境变量,别问我怎么知道的……

编译产物:

文件 路径 用途
Image arch/arm64/boot/Image 内核镜像,烧录到SD卡
*.dtb arch/arm64/boot/dts/renesas/ 设备树二进制文件
*.ko 各驱动目录下 内核模块,按需安装

3.3 设备树编译——dtc工具的使用

设备树是R-Car平台的重中之重。说白了,它就是告诉内核“板子上有什么硬件、怎么访问”。

R-Car的设备树源文件在arch/arm64/boot/dts/renesas/目录下。以M3N为例,主要文件是:

  • r8a77965.dtsi — SoC级设备树,定义所有内部外设
  • r8a77965-m3nulcb.dts — 板级设备树,定义具体板子的硬件

手动编译设备树:

# 编译单个设备树
dtc -I dts -O dtb -o r8a77965-m3nulcb.dtb r8a77965-m3nulcb.dts

# 或者直接用内核的编译系统
make ARCH=arm64 dtbs

我建议用第二种方式,因为内核的编译系统会自动处理依赖关系。手动用dtc的话,万一漏了头文件就麻烦了。

调试技巧:设备树出问题时,可以用dtc -I dtb -O dts反编译,看看实际生效的是不是你想要的内容。我在项目中遇到过设备树编译成功但启动报错,反编译一看,发现某个节点被覆盖了。

3.4 烧录到SD卡——让板子跑起来

编译完成,终于到了最激动人心的环节——烧录。R-Car M3N从SD卡启动,需要准备一个启动分区和一个根文件系统分区。

SD卡分区规划:

分区 大小 文件系统 内容
/dev/sdb1 500MB FAT32 内核镜像、设备树、启动脚本
/dev/sdb2 剩余空间 ext4 根文件系统

烧录步骤:

# 1. 挂载SD卡
sudo mount /dev/sdb1 /mnt/boot
sudo mount /dev/sdb2 /mnt/rootfs

# 2. 复制内核和设备树
sudo cp arch/arm64/boot/Image /mnt/boot/
sudo cp arch/arm64/boot/dts/renesas/r8a77965-m3nulcb.dtb /mnt/boot/

# 3. 安装内核模块
sudo make ARCH=arm64 modules_install INSTALL_MOD_PATH=/mnt/rootfs

# 4. 卸载并安全弹出
sudo umount /mnt/boot
sudo umount /mnt/rootfs

注意:SD卡设备名不一定是/dev/sdb,用lsblk确认一下。我曾经把U盘当成SD卡烧了,结果……嗯,你懂的。

启动脚本(boot.scr):

R-Car的启动加载器需要知道从哪里加载内核。在SD卡第一个分区创建boot.scr:

# boot.cmd 内容
setenv bootargs 'console=ttySC0,115200 root=/dev/mmcblk1p2 rootwait rw'
fatload mmc 0:1 0x48080000 Image
fatload mmc 0:1 0x48000000 r8a77965-m3nulcb.dtb
booti 0x48080000 - 0x48000000

然后用mkimage工具生成boot.scr:

mkimage -A arm64 -O linux -T script -C none -n "Boot script" -d boot.cmd boot.scr

3.5 知识结构图

下面这张图总结了整个流程,我建议你保存下来,每次编译时对照着走一遍:

内核编译与烧录流程 Linux内核编译与烧录流程 1. 内核配置 make defconfig make menuconfig 2. 内核编译 make Image make dtbs make modules 3. 烧录部署 复制Image到SD卡 复制dtb到SD卡 安装内核模块 输出产物:Image + *.dtb + *.ko 启动验证:串口查看启动日志 提示:每次修改配置后,建议备份.config文件,避免配置丢失

3.6 常见问题与避坑指南

最后,分享几个我实际项目中遇到过的问题,希望能帮你少走弯路:

  • 启动卡在“Starting kernel...” — 八成是设备树不对。检查dtb文件名和路径,或者反编译看看内容。
  • 网络不通 — R-Car的AVB驱动需要PHY芯片的配置。检查设备树中phy-handle是否正确。
  • SD卡无法挂载 — 分区表或文件系统类型不对。用fdisk -l确认分区,用mkfs.ext4重新格式化。
  • 内核模块加载失败 — 内核版本和模块版本不匹配。重新编译模块,或者检查modprobe的依赖。

我的经验:第一次烧录成功后,建议先做一次完整的启动日志记录。用dmesg或串口工具保存下来。后面出了问题,对比日志就能快速定位。这招帮我解决过不少疑难杂症。

好了,这一章的内容就到这里。配置、编译、烧录,每一步都有它的门道。你按照这个流程走一遍,应该能顺利让R-Car板子跑起来。如果遇到问题,回头看看这张流程图,基本都能找到答案。