3. 开发环境搭建(下):RK SDK 源码获取与编译工具链配置

上一节我们把 Ubuntu 虚拟机跑起来了,也装好了基础工具。但说实话,那只是热身。真正的开发工作,是从拿到 RK SDK 源码开始的。

我记得第一次接触 RK 的 SDK 时,光是 repo sync 就等了快两个小时。那时候心里直打鼓——是不是我网络有问题?是不是哪里配错了?后来才发现,这很正常。RK 的 SDK 包含了从底层引导到上层应用的全部代码,体量确实不小。

好,我们一步步来。

3.1 获取 RK SDK 源码:repo init / sync

RK 的 SDK 用 Google 的 repo 工具管理。它本质上是对 Git 的封装,让你能一次性拉取几十个 Git 仓库。你想想看,一个完整的嵌入式 Linux 系统,内核是一个仓库,U-Boot 是一个仓库,Buildroot 又是一个仓库……手动一个个 clone 会疯掉的。

3.1.1 安装 repo 工具

先确认 repo 是否已安装:

which repo

如果没找到,按下面步骤装:

mkdir -p ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=$PATH:~/bin

我个人习惯把 export PATH=$PATH:~/bin 加到 ~/.bashrc 里,这样每次打开终端就不用重新 export 了。

小提示: 如果 curl 下载慢,可以用国内镜像源。把上面的 URL 换成 https://mirrors.tuna.tsinghua.edu.cn/git/git-repo,速度会快不少。

3.1.2 repo init:初始化工作目录

假设你从芯微官方拿到了 SDK 的 manifest 仓库地址(通常是一个 XML 文件,描述了所有子仓库的路径和分支)。执行:

mkdir rk_sdk && cd rk_sdk
repo init -u <manifest仓库地址> -b <分支名> --depth=1

--depth=1 这个参数我强烈建议加上。它只拉取最新一次提交的历史,能省下大量时间和磁盘空间。我在项目中遇到过有人没加这个参数,结果 SDK 占了 40 多 G,而加了之后只有 15G 左右。

3.1.3 repo sync:拉取全部代码

初始化完成后,执行:

repo sync -c -j4 --no-tags

解释一下这几个参数:

  • -c:只同步当前分支,不拉取所有分支的引用
  • -j4:4 个任务并行拉取。网络好的话可以调成 -j8 甚至 -j16
  • --no-tags:不拉取标签,进一步减少数据量

这个过程会持续 20 分钟到 2 小时不等,取决于你的网速。期间如果中断了,重新执行 repo sync 会断点续传,不用担心。

注意: 不要用 root 用户执行 repo init/sync。repo 工具会在仓库目录下创建 .repo 目录,如果用 root 执行,后续普通用户操作会碰到权限问题。我曾经因为这个重拉过一次,教训深刻。

3.2 SDK 目录结构解析

sync 完成后,我们来看看 SDK 里到底有什么。我以 RK3566/RK3568 的 SDK 为例,其他型号大同小异。

先放一张整体结构图,让你有个全局印象:

RK SDK 顶层目录结构 rk_sdk/ kernel/ u-boot/ buildroot/ app/ drivers/ arch/ dts/ board/ configs/ drivers/ package/ configs/ output/ qt/ camera/ npu/ device/ & rockdev/ device/rockchip/ 芯片级配置 rockdev/ 打包脚本与分区表 说明:不同芯片型号的 SDK 目录结构基本一致 差异主要在 kernel 版本、buildroot 配置和 device 目录下的 dts 文件

下面逐个说明每个核心目录的作用:

目录 作用 我常用的关注点
kernel/ Linux 内核源码,RK 基于主线内核做了大量芯片适配 关注 arch/arm64/boot/dts/rockchip/ 下的设备树文件
u-boot/ 引导加载程序,负责初始化硬件并加载内核 修改 board/rockchip/ 下的板级文件来适配新硬件
buildroot/ 构建根文件系统,生成你最终的 rootfs.img 在 package/ 里添加自己的应用包
app/ 上层应用,比如 QT 界面、摄像头预览、NPU 示例 快速验证硬件功能时,直接跑这里的 demo
device/ 芯片级配置,包括 dts、分区表、参数文件 改分区大小、调 DDR 参数都在这里
rockdev/ 打包脚本,把各个镜像拼成烧录包 量产时用的 mkupdate.sh 就在这里

核心理解: RK SDK 的目录设计遵循了「分层解耦」的思想。内核、引导、文件系统、应用各自独立,但又通过统一的构建脚本串联起来。你改内核不会影响文件系统,改应用不需要重新编译内核。这种结构在项目迭代中非常舒服。

3.3 编译工具链安装与配置

源码有了,目录结构也清楚了。但要让代码变成能在 RK 芯片上跑的二进制文件,还需要交叉编译工具链。

所谓交叉编译,就是在 x86 的 PC 上编译出 ARM 架构的可执行文件。你想想看,RK 芯片是 ARM 核的,而你的电脑是 x86 的,不用交叉编译的话,难道把编译器装到开发板上跑?那速度会慢到让你怀疑人生。

3.3.1 获取工具链

RK 官方推荐使用 ARM GCC 工具链。在 SDK 的 prebuilts/gcc/linux-x86/aarch64/ 目录下通常已经自带了一份。如果没有,可以从 ARM 官网下载:

wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz
tar -xf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz
sudo mv gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu /opt/

我个人习惯把工具链放在 /opt/ 下,这样所有用户都能用,也方便在多个项目间共享。

3.3.2 配置环境变量

把工具链的 bin 目录加到 PATH 里:

export PATH=/opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin:$PATH
export ARCH=arm64
export CROSS_COMPILE=aarch64-none-linux-gnu-

同样,建议把这 3 行加到 ~/.bashrc 里。不然每次打开终端都要 export 一遍,很烦。

验证是否配置成功:
aarch64-none-linux-gnu-gcc --version
如果能正常显示版本号,说明工具链已经就绪。

3.3.3 验证编译:编译一个最小内核

工具链配好了,我们来验证一下。进入 kernel 目录,编译一个最小配置的内核:

cd ~/rk_sdk/kernel
make ARCH=arm64 rockchip_linux_defconfig
make ARCH=arm64 rk3568-evb1-ddr4-v10.img -j4

如果一切顺利,你会在 arch/arm64/boot/ 下看到 Image 和 dtb 文件。看到它们,就说明你的开发环境已经彻底搭好了。

常见坑: 编译时如果报错 arm-linux-gnueabihf-gcc: not found,别慌。这通常是因为 SDK 里某些脚本硬编码了 32 位工具链路径。检查一下 Makefile 或 build.sh 里的 CROSS_COMPILE 变量,改成 aarch64-none-linux-gnu- 就行。我在 RK3399 项目上就踩过这个坑,折腾了半小时才发现是脚本里写死了 32 位工具链。

3.4 本章小结

到这步,你的开发环境算是真正「立」起来了。我们做了三件事:

  • 用 repo init/sync 拉取了完整的 RK SDK 源码
  • 理清了 SDK 的核心目录结构——kernel、u-boot、buildroot、app 各司其职
  • 安装并验证了交叉编译工具链,成功编译了内核

环境搭建是嵌入式开发里最枯燥但也是最关键的一步。环境没搭好,后面所有工作都无从谈起。好在 RK 的 SDK 体系比较成熟,只要按部就班来,基本不会出大问题。

嗯,环境准备好了。接下来就可以真正开始写代码、改驱动、调系统了。