第一章:移植前的准备工作
做内核移植这事儿,我干了快十年了。每次拿到一块新芯片,第一步不是急着敲代码,而是先把准备工作做扎实。说白了,移植就像盖房子,地基没打好,后面全是坑。
这一章,我就把移植前必须搞定的四件事,掰开揉碎了讲给你听。
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
注意:网络启动时,开发板和电脑必须在同一个网段。我见过有人配了三天没通,最后发现是网线插错了口。嗯,这种低级错误我也犯过。
本章知识体系
下面这张图,是我做移植前必看的路线图。你照着走,基本不会迷路:
这四步走完,你的移植环境就算搭好了。接下来就可以开始真正的内核移植工作了。记住,准备工作做得越细,后面调试时流的汗就越少。
公众号:蓝海资料掘金营,微信deep3321