第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 知识结构图
下面这张图总结了整个流程,我建议你保存下来,每次编译时对照着走一遍:
3.6 常见问题与避坑指南
最后,分享几个我实际项目中遇到过的问题,希望能帮你少走弯路:
- 启动卡在“Starting kernel...” — 八成是设备树不对。检查dtb文件名和路径,或者反编译看看内容。
- 网络不通 — R-Car的AVB驱动需要PHY芯片的配置。检查设备树中phy-handle是否正确。
- SD卡无法挂载 — 分区表或文件系统类型不对。用
fdisk -l确认分区,用mkfs.ext4重新格式化。 - 内核模块加载失败 — 内核版本和模块版本不匹配。重新编译模块,或者检查
modprobe的依赖。
我的经验:第一次烧录成功后,建议先做一次完整的启动日志记录。用dmesg或串口工具保存下来。后面出了问题,对比日志就能快速定位。这招帮我解决过不少疑难杂症。
好了,这一章的内容就到这里。配置、编译、烧录,每一步都有它的门道。你按照这个流程走一遍,应该能顺利让R-Car板子跑起来。如果遇到问题,回头看看这张流程图,基本都能找到答案。