第三章 瑞芯微SDK架构解析

好,咱们今天聊聊瑞芯微的SDK。说实话,我第一次拿到这个SDK的时候,第一反应是——目录怎么这么多?别慌,我带你捋一遍,其实结构很清晰。

3.1 SDK目录结构概览

瑞芯微的SDK,说白了就是一个大杂烩。它把Linux内核、U-Boot、Buildroot、文档、设备树什么的都塞到一个仓库里。你解压之后,大概会看到这样的结构:

rk3588_sdk/
├── kernel/          # Linux内核源码
├── u-boot/          # U-Boot引导程序
├── buildroot/       # 根文件系统构建工具
├── device/          # 设备树、板级配置
├── docs/            # 文档
├── external/        # 第三方库
├── prebuilts/       # 预编译工具链
├── tools/           # 辅助工具
└── Makefile         # 顶层编译脚本

嗯,这里要注意:device目录是瑞芯微的特色。我刚开始做移植时,总以为设备树都在kernel里,结果发现瑞芯微把板级相关的配置单独拎出来了。这个设计其实挺聪明的——你换一块板子,只需要改device目录下的东西,内核源码基本不动。

3.2 关键目录功能详解

3.2.1 kernel/ —— 心脏地带

这个不用多说,Linux内核源码。瑞芯微用的是长期支持版(LTS)内核,比如5.10、6.1这些。我个人习惯先看arch/arm64/boot/dts/rockchip/目录,里面全是设备树文件。

避坑指南:我曾经在移植时,直接修改了kernel里的公共设备树文件,结果编译通过,但启动就挂。后来才发现,瑞芯微的device目录会覆盖kernel里的设备树。所以,改设备树优先去device目录

3.2.2 u-boot/ —— 启动的守门人

U-Boot负责初始化硬件、加载内核。瑞芯微的U-Boot做了不少定制,比如支持Rockchip miniloaderSPL(Secondary Program Loader)

你想想看,为什么需要SPL?因为瑞芯微的芯片启动时,内部SRAM只有几十KB,装不下完整的U-Boot。所以分两步走:

  1. SPL(很小,几十KB)初始化DDR
  2. SPL加载完整的U-Boot到DDR

我在项目中遇到过一个问题:SPL编译出来太大,超过了SRAM限制。后来发现是开启了太多调试信息。解决办法很简单——关闭SPL的DEBUG选项

3.2.3 buildroot/ —— 文件系统的工厂

Buildroot用来构建根文件系统。瑞芯微的SDK里,Buildroot已经预置了rockchip_defconfig。你直接make rockchip_defconfig就能用。

但说实话,我建议你不要直接用默认配置。为什么呢?因为默认配置会编译很多你用不到的包,比如X11、Qt这些。我一般会手动裁剪,只保留必要的:

  • busybox(基础命令)
  • dropbear(SSH服务)
  • alsa-utils(音频调试)
  • i2c-tools(I2C调试)

小技巧:Buildroot的make menuconfig可以图形化配置。我个人习惯先make savedefconfig保存最小配置,下次直接复用。

3.2.4 device/ —— 板级配置的集中营

这个目录是瑞芯微SDK的精华所在。它包含了:

  • 设备树文件(.dts、.dtsi)
  • 分区表配置(parameter.txt)
  • 固件打包脚本(mkimage.sh)
  • 板级配置文件(BoardConfig.mk)

举个例子,你拿到一块新板子,需要修改什么?

device/rockchip/rk3588/
├── rk3588-evb1.dts      # 设备树
├── rk3588-evb1.dtsi     # 设备树头文件
├── parameter.txt         # 分区表
├── BoardConfig.mk        # 板级配置
└── mkimage.sh            # 打包脚本

嗯,这里要注意:BoardConfig.mk定义了芯片型号、DDR类型、固件大小等关键参数。我刚开始做移植时,忘了改DDR类型,结果固件刷进去,板子直接不启动。后来花了半天才排查出来。

3.2.5 docs/ —— 被忽视的宝藏

说实话,很多工程师不看文档,直接上手。但我建议你至少看两个文档

  • Rockchip_Developer_Guide_Linux_Software_CN.pdf(软件开发指南)
  • Rockchip_Developer_Guide_Uboot_CN.pdf(U-Boot开发指南)

为什么?因为瑞芯微的文档写得其实不错,尤其是启动流程DDR初始化部分。我在项目中遇到过一个问题:板子启动到一半卡住,查了三天没结果。最后翻文档才发现,是PMIC(电源管理芯片)的I2C地址配置错了

警告:docs目录下的文档版本可能和SDK版本不一致。我建议你先看文档的修订日期,如果太旧,直接去瑞芯微官网下载最新版。

3.3 SDK编译流程概览

好,咱们聊聊编译流程。瑞芯微SDK的编译,说白了就是三步走

  1. 编译U-Boot:生成idbloader.img、uboot.img
  2. 编译内核:生成boot.img(包含内核+设备树)
  3. 编译Buildroot:生成rootfs.img(根文件系统)

顶层Makefile把这些步骤串起来了。你只需要执行:

./build.sh lunch    # 选择板型
./build.sh          # 一键编译

但说实话,我很少用一键编译。为什么?因为调试时只需要编译某个模块。比如我只改了设备树,那就只编译内核:

cd kernel
make ARCH=arm64 rockchip_linux_defconfig
make ARCH=arm64 rk3588-evb1.dtb
cp arch/arm64/boot/dts/rockchip/rk3588-evb1.dtb ../

这样快很多。你想想看,每次改个设备树都要全编译,那得等到什么时候?

3.3.1 编译流程的细节

瑞芯微的编译流程,其实隐藏了一些关键步骤

步骤 生成文件 说明
1. 编译U-Boot SPL idbloader.img 初始化DDR,加载U-Boot
2. 编译U-Boot uboot.img 完整的U-Boot
3. 编译内核 boot.img 内核+设备树+ramdisk
4. 编译Buildroot rootfs.img 根文件系统
5. 打包固件 update.img 最终烧录文件

嗯,这里要注意:idbloader.img是瑞芯微特有的。它包含了SPL和DDR初始化代码。我刚开始做移植时,以为直接用U-Boot的SPL就行,结果发现瑞芯微的SPL里还嵌了DDR训练参数。这个参数不对,板子根本起不来。

避坑指南:我曾经在换DDR颗粒时,忘了更新DDR训练参数。结果板子能启动,但运行一段时间就随机死机。后来用瑞芯微的DDR工具重新训练,才解决问题。所以,换DDR一定要重新训练

3.3.2 编译脚本的解读

顶层Makefile其实是个包装脚本。它调用了各个子目录的编译脚本。我建议你读一下device/rockchip/common/mkimage.sh,这个脚本负责打包固件。

举个例子,打包脚本里有一段:

# 生成boot.img
mkbootimg --kernel kernel/arch/arm64/boot/Image \
          --ramdisk buildroot/output/images/rootfs.cpio.gz \
          --dtb kernel/arch/arm64/boot/dts/rockchip/rk3588-evb1.dtb \
          -o boot.img

看到了吗?boot.img包含了内核、ramdisk和设备树。如果你改了设备树,但没更新boot.img,那刷进去还是旧设备树。我刚开始就犯过这个错,改了半天设备树,刷进去没效果,还以为自己改错了。

3.4 小结

好,咱们总结一下:

  • kernel/:内核源码,设备树优先去device目录改
  • u-boot/:引导程序,注意SPL大小限制
  • buildroot/:文件系统,建议裁剪不必要的包
  • device/:板级配置,移植的核心
  • docs/:文档,先看启动流程和DDR初始化

说实话,瑞芯微的SDK虽然目录多,但设计得挺合理的。你只要理解了device目录是板级配置的中心,其他目录就很好理解了。下一章,咱们聊聊如何搭建开发环境,包括工具链安装、串口调试这些实战内容。

嗯,今天就到这儿。有问题随时问我。