第一章:移植前的准备工作

做内核移植这事儿,我干了快十年了。每次拿到一块新芯片,第一步不是急着敲代码,而是先把准备工作做扎实。说白了,移植就像盖房子,地基没打好,后面全是坑。

这一章,我就把移植前必须搞定的四件事,掰开揉碎了讲给你听。

1.1 了解国产芯片架构

现在国产芯片主流就两个方向:RISC-V 和 LoongArch。你想想看,这两者虽然都是指令集架构,但脾气秉性完全不同。

RISC-V 架构

RISC-V 是个开放指令集,说白了就是免费、开源、谁都能用。我个人习惯先看它是 RV32 还是 RV64,然后确认扩展指令集——比如是否支持乘法除法(M扩展)、原子操作(A扩展)、浮点(F/D扩展)。

我在项目中遇到过一块 RISC-V 芯片,手册上写着支持 RV64IMAFDC,结果一跑起来发现浮点单元有 bug。嗯,从那以后我拿到芯片第一件事就是先跑一遍指令集测试用例。

关键点:RISC-V 的 Privileged Specification 版本很重要。v1.10 和 v1.11 在中断处理上差别很大,搞错了连系统都起不来。

LoongArch 架构

LoongArch 是龙芯自研的指令集,分 LA32 和 LA64 两个版本。说实话,这架构跟 MIPS 有点血缘关系,但改了不少东西。我记得第一次移植 Linux 到 LoongArch 时,光是搞清楚它的页表结构就花了两天。

LoongArch 有个特点:它的特权级分为 PLV0~PLV3,跟 RISC-V 的 M/S/U 模式不太一样。你移植内核时,大部分代码跑在 PLV0(最高特权级),用户程序跑在 PLV3。

我的建议:不管哪种架构,先花半天时间把指令集手册的「异常与中断」章节读完。这块搞不明白,后面调试时你会怀疑人生。

1.2 获取芯片手册与数据手册

做移植,手册就是你的命。我见过太多人拿着不完整的手册就开始干,结果卡在某个寄存器配置上进退两难。

你需要找齐这几份文档:

  • 芯片数据手册(Datasheet):芯片的引脚定义、电气特性、封装信息
  • 参考手册(Reference Manual):寄存器描述、外设功能、时钟树、中断控制器
  • 内核编程指南(Programming Guide):启动流程、MMU 配置、Cache 操作
  • 勘误表(Errata):芯片已知的 bug 和 workaround

我曾经因为没看勘误表,在一个 DMA 控制器上浪费了整整一周。后来才发现芯片手册里写的 DMA 传输完成标志位,实际硬件上根本不会置位。你说气不气人?

注意:有些国产芯片厂商的手册更新不及时。我建议你直接找 FAE 要最新版本,或者去官网的「技术资料」栏目翻一翻。别用百度搜到的版本,那可能是三年前的。

1.3 搭建交叉编译环境

交叉编译,说白了就是在你的 x86 电脑上编译出能在目标芯片上跑的代码。这个环节看似简单,但环境配不好,后面编译内核时会报一堆莫名其妙的错误。

我个人习惯用这套工具链:

架构 工具链前缀 推荐版本
RISC-V 64 riscv64-linux-gnu- gcc 12.2+
LoongArch 64 loongarch64-linux-gnu- gcc 13.1+

安装方法很简单,以 Ubuntu 为例:

# RISC-V 工具链
sudo apt install gcc-riscv64-linux-gnu

# LoongArch 工具链(需要添加龙芯源)
sudo apt install gcc-loongarch64-linux-gnu

装完后记得验证一下:

riscv64-linux-gnu-gcc --version
# 输出应该显示 gcc 版本信息

避坑指南:我曾经遇到过工具链版本太老,编译出来的内核在启动时崩溃。后来发现是 gcc 的原子操作实现有 bug。所以我的建议是:用最新稳定版,别用太旧的。

1.4 配置 TFTP/NFS 网络启动环境

做内核移植,你不可能每次都把内核烧写到 Flash 里。太慢了。我一般用 TFTP 加载内核,NFS 挂载根文件系统。这样改完代码,编译、重启、测试,几分钟一轮。

先搭 TFTP 服务器:

sudo apt install tftpd-hpa
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
# 把编译好的内核 Image 放到 /srv/tftp 下

再配 NFS:

sudo apt install nfs-kernel-server
sudo mkdir -p /srv/nfs/rootfs
# 把根文件系统解压到 /srv/nfs/rootfs
# 编辑 /etc/exports,添加:
/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
sudo exportfs -a

然后在 U-Boot 里设置启动参数:

setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.10
setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.10:/srv/nfs/rootfs rw ip=192.168.1.100'
tftp 0x80200000 Image
booti 0x80200000

注意:网络启动时,开发板和电脑必须在同一个网段。我见过有人配了三天没通,最后发现是网线插错了口。嗯,这种低级错误我也犯过。

本章知识体系

下面这张图,是我做移植前必看的路线图。你照着走,基本不会迷路:

移植前准备工作流程图 了解芯片架构 获取芯片手册 搭建交叉编译环境 配置网络启动 RISC-V / LoongArch 指令集 Datasheet / Reference Manual gcc / binutils / glibc TFTP 加载内核 + NFS 根文件系统 准备工作完成标志 内核能编译通过 + 网络启动能进入 Shell

这四步走完,你的移植环境就算搭好了。接下来就可以开始真正的内核移植工作了。记住,准备工作做得越细,后面调试时流的汗就越少。


公众号:蓝海资料掘金营,微信deep3321