简介:RK3229软件开发指南V1.03是瑞芯微官方发布的技术文档,面向嵌入式软件开发与技术支持工程师,帮助他们围绕RK3229芯片在Linux 3.10内核及Android 6.0.1/7.1.2平台下完成开发、编译与调试。压缩包内为1个PDF文件,大小1.61MB,目录结构清晰,适合按章节快速查找,目前已有623人学习下载。文档首先给出DDR、NAND、EMMC、WiFi/BT等硬件支持列表,以及SDK软件包适用硬件和多媒体编解码、Kodi支持程度列表;随后梳理SDK获取、编译烧写、固件烧写和工具索引流程。开发者相关部分还覆盖system分区大小配置、ODEX预编译、禁用SELinux、Box产测工具、Jack-server配置、USB默认开启ADB、Android 7.1开机视频与低内存优化、DRM Widevine L1配置等实用说明,并补充开机logo限制、序列号/Mac烧写工具更新等注意事项。对正在评估RK3229方案或需要快速排查问题的工程师,这份指南可提供从硬件选型到系统定制的完整参考。
1. 一份 2017 年的芯片指南,为什么现在还要翻出来读
我第一次接触《Rockchip RK3229 软件开发指南 V1.03-201711241》是在一个电视盒子方案的项目里。供应商丢过来一个 SDK 压缩包,外加这份 PDF,说“照着做就行”。当时我心里是犯嘀咕的:2017 年的文档,现在平台都换了好几代,还有参考价值吗?结果恰恰相反——RK3229 至今仍大量出货在入门级盒子、带屏设备和一些工业终端上,而这版 V1.03 的指南把启动流程、DDR 配置、烧录分区、调试手段讲得足够清楚,是整条 BSP 开发线的骨架。它解决的不是“能不能跑”,而是“跑起来之后怎么改、怎么调、怎么救砖”的问题。适合谁读?拿到 RK3229 方案却不知道从哪下手的嵌入式工程师,以及被老 SDK 折腾到想放弃的新手。
2. 先搞清楚 RK3229 的软件骨架:从仓库目录到编译产物
拿到指南先别急着敲命令。这类软件开发指南的章节顺序本身就是开发主线:先讲芯片特性与地址映射,再讲 DDR 初始化、U-Boot、内核与文件系统构建,最后是烧录和调试。照着这个顺序走一遍,你对整个 SDK 的结构就有数了。RK3229 的 SDK 体量不小,但没有一个目录是白给的,每一步都有对应的产物和烧录位置。
2.1 拿到文档先看哪几页:主线藏在章节顺序里
我一般拿到这类指南,先不细读,花半小时把目录和图表扫一遍,标记出四块内容:启动流程图、内存布局图、分区表、烧录工具说明。这四块决定了你后面所有操作的上限。启动流程图告诉你上电后芯片先跑什么、再跑什么;内存布局图决定了你在 U-Boot 里改 DDR 频率和地址时要小心什么;分区表告诉你固件里的每个镜像该往哪放;烧录工具说明则决定你出了问题还能不能救回来。
RK3229 的启动链路大致是:MaskROM → Loader(DDR 初始化与存储初始化)→ U-Boot → kernel → rootfs。指南里的章节也基本按这个顺序铺开。你在后续看源码时,只要记住这条链,就不会在 kernel 启动失败时跑去改 DDR 参数——那是 Loader 阶段的事。
2.2 把源码目录和编译产物对上号
SDK 解压出来之后,目录结构有固定的规律。通常会有 kernel、u-boot、buildroot、device/rockchip、rockdev、RKDocs 这一层。RKDocs 放的是芯片参考手册和硬件笔记,device/rockchip 下面是板级配置与分区脚本,rockdev 是编译脚本和产物输出目录。指南里的“软件结构”章节,实际上就是把每个源码目录对应到一个编译产物上。
我先用一张表说明常见的对应关系,不同 SDK 版本目录名会有出入,但职责基本不变:
| 指南中的模块 | SDK 对应目录 | 产出的镜像 | 烧录/使用位置 |
|---|---|---|---|
| DDR/安全启动 | rkbin、u-boot | uboot.img、trust.img | 启动最前段 |
| 内核与设备树 | kernel | kernel.img、resource.img | boot 分区 |
| 根文件系统 | buildroot | rootfs.img | rootfs 分区 |
| 系统打包 | rockdev | update.img | 整包烧录 |
resource.img 里装的是设备树 DTB 和内核 logo,kernel.img 是压缩后的内核镜像。改完 dts 编译后,这两个文件都要重新生成。很多人只烧 kernel.img 不烧 resource.img,结果设备树还是旧的,启动行为没变化,还以为自己没改对。这类问题在指南里通常不会正面写,但“镜像与分区对应关系”那张表里能推理出来。
2.3 先编译一个能跑的默认固件:把基线建立起来
在改任何代码之前,我强烈建议先按 SDK 默认配置完整编译一遍,烧进去确认能开机。这一步不是为了省事,而是给你建立一个“干净基线”。此后任何改动出了问题,都可以刷回基线对比,排查效率高很多。RK 平台的编译大多通过 SDK 根目录的 build.sh 或 mk 脚本驱动,但底层仍然是 make 和交叉工具链。
# 以内核编译为例,先在 SDK 根目录加载环境变量 source build/envsetup.sh # 选择板型,这里以盒子公板为例 lunch rk3229_box-userdebug # 编译内核,-j 后面的数字根据 CPU 核数调整 make kernel -j8这段命令里,envsetup.sh是 SDK 里统一的环境初始化脚本,它会把交叉编译器路径、输出目录、打包工具都导好;lunch选择一个具体的板级配置,不同板型的 defconfig 和 dtb 列表不一样;make kernel只编内核部分,产物会输出到rockdev/Image-对应目录。先跑通这一步,确认工具链没问题,再继续往下走。第一次全量编译时间比较长,建议用-j8或更高并行度,但别超过 CPU 线程数的两倍,否则容易 OOM。
3. 搭建 RK3229 开发环境:版本搭配是头等大事
老 SDK 最折磨人的地方不是代码难懂,而是编译环境搭不起来。RK3229 的这套 SDK 年代摆在那里,设计时主要针对的是 Ubuntu 14.04/16.04 这类系统。到了现在,很多人手头是新版 Ubuntu,一编译就报错。这时候不要马上怀疑代码坏了,先检查三样东西:系统位数、32 位兼容库、交叉工具链版本。
3.1 主机系统、工具链与 SDK 的版本矩阵
RK3229 的 SDK 内部自带工具链的情况很常见,比如 buildroot 里会自己下载或内置 arm 交叉编译器。但 U-Boot 和 kernel 部分有时会用到宿主机的工具,例如 mkimage、dtc、lz4 这类。这些工具在老 SDK 里可能是按 32 位编译的,跑在新版 64 位系统上,缺了 32 位运行库就直接报错。
我整理了一个粗略的版本搭配参考表,按踩坑概率从低到高排列:
| 宿主机系统 | 工具链来源 | 常见问题 | 评级 |
|---|---|---|---|
| Ubuntu 16.04 64 位 | SDK 内置 | 基本顺利 | 推荐 |
| Ubuntu 18.04 64 位 | SDK 内置 + 补 32 位库 | 偶发 dtc 报错 | 可用 |
| Ubuntu 20.04 及以上 | SDK 内置 | Python 版本、glibc 相关报错 | 需处理 |
| Windows 下虚拟机 | 任意 | USB 烧录透传麻烦 | 不推荐 |
如果你手头只有新版 Ubuntu,也先别急着折腾系统重装。常见做法是安装 32 位兼容库,再给一些老工具打补丁,能覆盖大部分问题。真正麻烦的是 glibc 版本过新导致某些预编译工具无法运行,这种情况优先考虑在 SDK 源码里重新编译工具,而不是去改系统库。
3.2 从零到能编译:最小环境搭建步骤
我通常拿到一台新机器,第一件事就是装编译依赖。RK 平台 SDK 的依赖和大多数嵌入式 Linux 项目差别不大,核心是编解码库、文件系统制作工具、设备树编译工具和网络相关的库。
# Ubuntu 系安装基础依赖,老版本系统不需要全部,多装无害 sudo apt-get install git wget make gcc g++ \ device-tree-compiler lz4 liblz4-tool \ libncurses5-dev libncursesw5-dev \ libssl-dev bc bison flex \ lib32z1 lib32ncurses5 lib32stdc++6这里重点说三个参数的意义。device-tree-compiler提供 dtc 命令,编译内核和 resource.img 时依赖它;libncurses5-dev是 menuconfig 的界面库,缺了它打开内核配置界面就直接报错;lib32z1和lib32ncurses5是 32 位兼容库,专门给那些老 SDK 里预编译的 32 位工具用的。装完之后,可以用file命令检查一个可疑工具是否链接了 32 位库,再决定要不要补齐。
装完依赖,把 SDK 解压在磁盘空间充足的目录,路径里不要带中文和空格。RK 的编译脚本有时对路径比较敏感,空格会导致打包脚本解析错误。我一般放在/home/用户名/work/rk3229_sdk这类路径下,避免放在/opt这类需要 root 权限的目录里,省得每次编译都遇到权限问题。
3.3 编译失败的常见信号与处理
环境问题导致的编译失败,报错信号其实挺有规律。最常见的是“cannot execute binary file: Exec format error”,这表示你运行了一个架构不匹配的程序,多半是 64 位系统跑 32 位工具,或者宿主工具链被无效的预编译二进制干扰。
第二种常见的是找不到libncurses.so.5、libz.so.1这类动态库。这种直接安装对应 32 位包就能解决。第三种是 Python 脚本报ModuleNotFoundError,老 SDK 里不少打包脚本依赖 Python 2,新版系统默认没有,需要装 python2 或者改用 SDK 提供的替代脚本。不要一看到报错就疯狂百度,先file、ldd两个命令定位文件类型和库依赖,能省大半时间。
4. 按指南走一遍固件烧录与启动调试
环境搭好、默认固件能跑之后,真正的工作才开始。RK3229 开发中绕不开的两个基本操作:烧录和看日志。烧录模式进不对,设备就变砖头;日志不会看,出了问题就只能靠猜。
4.1 烧录模式:Loader 与 MaskROM 的进入方式
RK 平台的烧录模式主要有两种:Loader 模式和 MaskROM 模式。Loader 模式是设备已经运行了 Loader 程序,通过 USB 与 PC 烧录工具通信;MaskROM 模式则是芯片内部 ROM 程序直接接管 USB,通常用于救砖或者烧写 Loader 本身。两者的进入方式不同,用途也不同,我用一张表来说明。
| 模式 | 进入方式 | 用途 | 风险 |
|---|---|---|---|
| Loader | 按住设备上的恢复键再上电 | 常规烧录固件 | 低 |
| MaskROM | 短接 eMMC 的 CLK 或根据板卡短接点,再上电 | 刷写损坏的 Loader/U-Boot | 高,操作需谨慎 |
在实际操作中,Loader 模式最常用。开发板或盒子主板上一般预留了恢复按键,或者有对应的测试点。按住恢复键后插上 USB,烧录工具里能看到一个设备节点。MaskROM 模式是最后的手段:如果 U-Boot 被刷坏了,Loader 模式进不去,就只能用镊子短接板子上标注的 MaskROM 焊盘或 eMMC 时钟信号线,强制芯片从 ROM 启动。
烧录工具在 Windows 和 Linux 下都有,Windows 下是图形界面的工具,Linux 下是命令行工具 upgrade_tool。命令行工具适合在编译服务器上批量烧录,也方便写进脚本做产测。典型的一键烧录命令如下:
# 下载整包固件 update.img 后,用 upgrade_tool 烧录 sudo upgrade_tool db rk322x_loader.bin sudo upgrade_tool uf update.img第一条命令里的db参数表示先下载并执行 Loader,第二步才会进入可通信状态;uf表示烧录整个 update.img 到存储设备。这个命令组合在 RK3229、RK3288 等老平台上一脉相承。如果你手里的工具版本偏老,参数名可能会有细微差别,以你手头工具的--help输出为准。烧录过程中不要断电,否则很容易把 Loader 区写坏,被迫进入 MaskROM 流程。
4.2 串口日志的检查点:从 DDR 到 kernel
RK3229 的调试串口默认是 UART2,波特率在多数 SDK 里设置为 1500000,也就是 1.5 Mbps。很多人第一次接串口什么都看不到,是因为用了 115200 的常规波特率。连接好 USB 转串口模块,在设备上电的瞬间,日志会从芯片内部 ROM 阶段开始打印。RK 平台的串口日志有几个关键检查点,我按启动顺序整理成表:
| 阶段 | 日志关键字 | 异常特征 |
|---|---|---|
| ROM/Loader | DDR Version、Loader version | 无打印或乱码,先查串口连接与波特率 |
| DDR 初始化 | DDR Training、ddr_init | 卡住或报 training failed |
| U-Boot | U-Boot 2017.xx、Hit any key | 停留在“Hit any key”说明进入了 U-Boot 命令行 |
| Kernel | Booting Linux、Machine model: | 无输出则查设备树匹配 |
这里最关键的一个习惯是:拿到日志先看“Machine model”那一行。它会直接打印出设备树里设置的板级型号,如果和你实际板卡不符,后面所有外设配置都可能错位。很多“内核崩了”的假象,其实都是设备树加载了错误的板型导致的。另外,开机时按回车键可以停在 U-Boot 命令行,从这里可以手动敲命令验证内存、存储、网络等硬件状态,是排查启动问题的重要入口。
在开发阶段,我倾向于把完整启动日志保存成文件再分析。直接用终端滚动查看很容易漏掉关键信息,尤其是指针式阅读容易忽略早期 DDR 初始化的警告。保存日志后,用关键字搜索效率高很多。
5. 避坑:RK3229 开发里最常见的 5 个翻车现场
这一章我专门写 RK3229 开发里容易踩、且网上经常问不清楚的问题。每一条都是我自己或同行真实遇到过的,写出来给你当参考。
5.1 现象:编译 SDK 时报“cannot execute binary file”
在新版 64 位 Linux 下编译 RK3229 SDK,经常在编译到某个小工具时报cannot execute binary file: Exec format error。这个报错的含义不是权限不够,而是当前系统无法执行这个二进制文件。原因通常是 SDK 里某个预编译工具是 32 位的,系统缺少 32 位动态库加载器,或者工具本身的架构与宿主机不兼容。
解决分两步:先file tools/xxx查看工具类型,如果输出里带32-bit,说明它是 32 位程序;再ldd tools/xxx看缺哪个库。然后补齐lib32z1、lib32ncurses5、lib32stdc++6这些 32 位兼容包。如果工具是 x86 架构而宿主机是 ARM 架构(比如你在 ARM 服务器上编译),那就要直接换 x86 的编译机器,或者找 SDK 文档里是否有其他平台的工具链支持。
5.2 现象:烧录工具识别不到设备
插上 USB 后,烧录工具界面上看不到设备,但lsusb里能看到一个2207开头的设备号。这个现象在 Linux 下特别常见。原因不是硬件坏了,而是 udev 规则没生效,普通用户没有访问 USB 设备的权限。
解决方法是给 RK 的 USB 设备写一条 udev 规则,或者直接用 root 权限运行烧录工具。我一般会在/etc/udev/rules.d/下新建一个规则文件,把 Vendor ID 和 Product ID 写进去,然后重载 udev,重新插拔 USB 设备:
# 将 RK 设备权限放开,设备 ID 以实际 lsusb 输出为准 echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="2207", MODE="0666"' | sudo tee /etc/udev/rules.d/51-rockchip.rules sudo udevadm control --reload-rules sudo udevadm trigger这段规则的意思是,当 USB 设备的厂商 ID 为 2207 时,把设备权限改为 0666,即所有用户可读写。udevadm control --reload-rules让新规则生效,udevadm trigger强制系统重新检测一遍设备。在 Windows 下遇到类似问题,一般是驱动没装好,换成 SDK 配套的驱动并重新插拔即可。注意 2207 是瑞芯微常用的 USB Vendor ID,也有个别工具用 0x2207,写规则时保持一致就行。
5.3 现象:改了 DTS 之后系统启动卡在早期阶段
不少人在 kernel 的 dts 里加了新外设节点,重新编译烧录后,设备启动到一半就死了,串口没有任何 kernel panic 信息。反复检查配置看不出问题。我遇到过最典型的原因是:板卡主控是 RK3229,但 dts 里写的是 RK3228 的 compatible 字符串,或者反过来。这两个芯片在 SDK 里共用大量代码,但在设备树匹配阶段是严格区分的。
解决方法是回到串口日志,看Machine model:这一行打印的是哪个板型。如果不是你预期的板型,检查arch/arm/boot/dts/rk3229-xxx.dts里的model字段,以及 Makefile 里是否把这块 dts 编进了resource.img。另外,很多 SDK 里 RK3229 和 RK3228 的 DTS 是通过#include共用rk322x.dtsi的,确认你改的是rk3229专属的那个文件,而不是改到共用头文件里影响了所有板型。
5.4 现象:设备频繁重启,串口反复打印 DDR Training failed
这个现象容易让人误判为软件问题,但其实硬件占比更大。DDR Training 失败通常意味着内存颗粒与控制器之间的时序训练没通过,常见原因有:DDR 供电电压不对、走线纹波偏大、颗粒型号与 SDK 默认配置不符、DDR 频率设置偏高。
我的处理顺序是:先查硬件,用示波器看 DDR 供电纹波,确认电压在颗粒规格书范围内;再进 U-Boot 手动降低 DDR 频率重试;最后才考虑改软件配置。如果换了颗粒型号,必须去 SDK 的 DDR 配置表里找对应的参数文件,RK 的老 SDK 通常有一份 DDR 初始化参数库,按颗粒厂商和型号选择。只改 U-Boot 的 dts 频率字段往往不够,Loaders 阶段的 DDR 初始化参数是单独编译进 Loader 的,需要重新生成 Loader 并烧录。
5.5 现象:刷机后进不了 Loader 模式,系统全砖
这是最让人头疼的情况:固件写坏了 U-Boot 或者 Loader,按住恢复键上电也进不了 Loader 模式。原因基本是烧录过程中断电、写了不完整的 Loader 镜像,或者烧录了带安全启动的固件导致普通 Loader 被拒绝加载。此时唯一的救砖路径是 MaskROM 模式。
找到板卡上的 MaskROM 短接点或 eMMC 的 CLK 测试点,短接后上电,USB 设备会以 MaskROM 设备出现。这时用工具先下载一个完整的 Loader,再重新烧录整包固件:
# 设备进入 MaskROM 后,先加载 Loader,再烧整包 sudo upgrade_tool db rk322x_loader.bin sudo upgrade_tool uf update.img这个过程要特别注意:MaskROM 模式下设备不会自动加载存储里的 Loader,db命令就是手动把 Loader 送到芯片内存里执行,执行成功后设备会切换到 Loader 模式继续后续操作。整个救砖过程不要断开 USB,也不要让设备断电。如果第一次db没反应,检查短接点是否在正确时刻释放,有些板卡要求进入 MaskROM 后立刻断开短接,否则 ROM 阶段无法正常枚举 USB。
6. 把这份指南用活:建立自己的 BSP 版本基线
读指南和用指南是两回事。我的习惯是:看完一章,就把里面跟自己板卡相关的参数抄进一张内部速查表,而不是把 PDF 翻来翻去。这张表一般包含:DDR 频率与电压、串口波特率、分区表各分区偏移、烧录模式进入方式、常用编译命令。等你同时维护两三块 RK3229 板卡时,这份表比任何文档都实用。
进阶一点的用法,是把整个 SDK 纳入 Git 管理,但不要直接在主分支上改代码。我一般把原始 SDK 作为upstream分支,每次适配板卡都在独立分支上做。拿到新版指南或新版 SDK 时,用git diff upstream看差异,能快速知道官方改了什么。这个习惯救过我一次:某次客户反馈 HDMI 无输出,对比后发现是内核提交更新了 HDMI 驱动,而我们的分支还停留在旧版配置。这个“后悔药”就是版本管理给的。
验证方法上,我每次改完编译,都会核对三处:串口日志里Machine model是否匹配、resource.img是否包含最新 DTB、update.img的生成时间戳是否为最新。这三处确认无误,才敢烧录到设备上跑完整用例。RK3229 这类老平台,稳定性的关键往往不在性能,而在可复现——同样的步骤能不能稳定跑通,决定了你在产线上是省心还是煎熬。
做 RK3229 这一年多,我最大的教训是:不要跳过“先编译默认固件”这一步,也不要迷信新版系统“兼容一切”。老平台的开发,尊重它当年的环境约束,反而最快。希望帮到你。
本文还有配套的精品资源,点击获取