4. Linux系统移植总览

在嵌入式RISC-V开发中,把Linux运行到一块新板子上,并不是简单地把内核复制进去。所谓Linux系统移植,是指针对特定处理器架构和具体硬件板卡,对启动引导程序、Linux内核、设备树和根文件系统进行配置、编译、适配与烧写,使操作系统能够正确识别硬件、挂载文件系统并最终进入用户空间的过程。它解决的是“通用Linux如何变成这块板子专属的Linux”这一问题。

理解移植,关键是理解它的层次划分。一个可启动的嵌入式Linux系统通常由四部分构成:Bootloader、设备树、Linux内核、根文件系统。它们按启动顺序层层接力,任何一层不匹配,系统都无法正常进入用户态。

RISC-V Linux 系统移植层次与启动接力 ① Bootloader(如 U-Boot SPL + U-Boot) 上电初始化时钟/DDR/串口 → 加载内核镜像与设备树 → 传递启动参数 ② 设备树 DTB 描述CPU、内存、外设地址与中断 内核据此匹配并初始化驱动 ③ Linux 内核 zImage/Image 进程调度、内存管理、驱动框架 解析设备树,挂载根文件系统 ④ 根文件系统 RootFS(ext4 / squashfs / initramfs) 提供 /bin、/etc、/lib、/dev 与 init 进程,是用户空间运行的基础 进入用户空间:init → 登录/应用 移植工作贯穿四层:Bootloader 适配板级初始化、设备树描述硬件、内核配置驱动、RootFS 提供运行环境

一、移植的核心原理

Linux内核本身是高度可移植的,它通过架构层与板级层分离来支持不同硬件。RISC-V架构代码位于 arch/riscv,负责异常入口、页表、时钟中断等通用机制;而具体板卡的内存地址、外设寄存器、中断号等信息,则通过设备树在启动时动态传入。这样同一份内核镜像,配合不同设备树,就能运行在不同板子上。

Bootloader的作用是“把系统带起来”。它完成最底层的DDR初始化后,从存储介质读取内核镜像和设备树到内存,设置好启动参数,最后跳转到内核入口。内核启动后解析设备树,匹配并加载驱动,再根据 bootargs 中的 root= 参数找到并挂载根文件系统,执行 /sbin/init,系统才算真正可用。

移植的本质不是“改内核”,而是“让通用组件认识你的板子”。设备树负责描述硬件,配置负责选择功能,Bootloader负责搬运和传参,RootFS负责提供运行环境。

二、移植的方法流程

一次完整的移植通常遵循以下步骤,顺序不可颠倒:

  1. 确认硬件资源:整理CPU型号、DDR容量与地址、串口、存储介质(eMMC/SD/NAND)、网络PHY等。
  2. 准备工具链:安装RISC-V交叉编译器,如 riscv64-linux-gnu-gcc。
  3. 移植Bootloader:配置板级文件,编译SPL与U-Boot,确认串口有输出。
  4. 编写设备树:在 arch/riscv/boot/dts 下新增或修改板级 .dts,描述内存与外设。
  5. 配置并编译内核:选择默认配置,打开所需驱动,生成 Image 与 dtb。
  6. 制作根文件系统:用BusyBox或Buildroot生成最小RootFS,放入SD卡或打包进镜像。
  7. 烧写与联调:通过串口观察启动日志,逐层定位问题。
# 典型编译与启动命令
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j8 Image dtbs

# U-Boot 中加载并启动
setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rw"
fatload mmc 0:1 0x84000000 Image
fatload mmc 0:1 0x83000000 board.dtb
booti 0x84000000 - 0x83000000

三、典型场景:一块新RISC-V开发板上电

假设拿到一块基于RISC-V SoC的开发板,串口无任何输出。首先检查Bootloader是否烧写正确,若SPL阶段就无打印,多半是DDR初始化参数或时钟配置错误。若U-Boot能启动但内核卡住,常见原因是设备树中 memory 节点地址与真实DDR不符,或 bootargs 里 root= 指向错误分区。若内核启动到最后提示 Kernel panic - not syncing: VFS: Unable to mount root fs,则说明根文件系统未找到或格式不被支持。

下表总结了四层组件的职责与常见故障点,便于排障时快速定位:

层次 核心职责 关键产物 常见故障
Bootloader 初始化硬件、加载内核与设备树、传参 SPL、u-boot.bin 无串口输出、DDR初始化失败
设备树 描述硬件资源与连接关系 board.dtb 内存地址错、外设不识别
Linux内核 管理资源、加载驱动、挂载根文件系统 Image 驱动缺失、启动卡死
根文件系统 提供用户空间程序与init rootfs.ext4 / initramfs 无法挂载、init找不到

四、误区与复盘

常见误区一:把设备树当成“可选配置”。在RISC-V Linux中,设备树是内核识别硬件的唯一依据,缺少正确节点,驱动不会加载。
常见误区二:只改内核不改Bootloader。启动参数、加载地址、机器码匹配都依赖Bootloader,二者必须协同。
常见误区三:忽略根文件系统的init权限与库依赖,导致内核已启动却停在 No init found。