1. 拿到一块RV1126B开发板,先别急着上电
RV1126B这颗芯片最近在边缘视觉和轻量级AI推理圈子里讨论度很高,不少做智能门锁、人脸识别面板、工业相机的团队都在往这个平台上迁移。但说实话,SDK移植这件事从来都不是"下载-编译-烧录"三步走那么简单,尤其是从零开始适配一块新板子的时候,DDR配置和烧写链路这两关能卡掉一大半人。我自己前前后后折腾过好几版RV1126B的板子,从最初对着原理图一根根对线,到后来能比较顺畅地把整套SDK跑通,中间踩的坑足够写一本小册子。这篇内容就是把我整个移植过程的思路、操作细节和那些文档里不会写的经验整理出来,给正在做或者准备做RV1126B SDK移植的朋友一个可参考的路径。
先明确一下这篇内容适合谁看。如果你手里有一块RV1126B的开发板或者自己画的板子,需要把原厂SDK跑起来,并且希望理解每一步背后的逻辑而不是机械地复制命令,那这篇内容会对你有帮助。如果你只是想了解一下RV1126B这个平台的基本情况,也可以从整体设计思路那部分看起,感受一下一个嵌入式SDK移植项目大概是什么样子的。整篇内容会围绕DDR配置、SDK目录结构、编译环境搭建、镜像烧写这几个核心环节展开,每个环节都会说清楚"为什么这么做"和"不这么做会怎样"。
需要提前说明的是,RV1126B的SDK版本迭代比较快,不同版本之间目录结构和配置方式可能有差异。我下面提到的操作路径和文件名是基于我手头比较稳定的一个版本,你在实际操作时需要对照自己拿到的SDK包做适当调整。另外,DDR配置这块和具体使用的DDR颗粒型号强相关,我用的参数只能作为参考,最终一定要以你板子上实际贴的颗粒手册为准。
2. 整体移植思路与方案选型
2.1 为什么SDK移植要从DDR配置开始
很多人拿到SDK之后第一反应是直接编译,编译过了就烧,烧进去发现起不来,然后开始怀疑是内核配置问题、文件系统问题,折腾一圈最后才发现是DDR参数不对。这个顺序其实是反的。DDR是系统启动的第一道门槛,BootROM跑完之后,第一段加载到片内SRAM的代码就要负责初始化DDR,DDR初始化不成功,后面的东西根本加载不进去,你连串口log都看不到完整的启动信息。
RV1126B的启动流程大致是这样的:芯片上电后,BootROM先从启动介质(SPI Flash、eMMC或者通过USB)读取一小段引导代码到片内SRAM,这段代码里包含了DDR控制器的初始化参数,DDR初始化完成后,才会把更大的固件加载到DDR里运行。所以DDR配置是整个移植工作的地基,地基没打好,上面盖什么都是白搭。
我自己的习惯是,拿到新板子之后,先不管SDK里其他东西,集中精力把DDR配置调通,确保串口能打印出完整的DDR容量和初始化信息,然后再往下走。这样做的好处是问题边界清晰,不会把DDR的问题和后面软件的问题混在一起排查。
2.2 DDR配置参数的来源与验证逻辑
DDR配置参数不是拍脑袋写的,它的来源主要有三个:DDR颗粒厂商的数据手册、RV1126B芯片的DDR控制器手册、以及原厂提供的参考配置。这三者需要结合起来看。
DDR颗粒手册里会给出这颗颗粒的关键时序参数,比如tRCD、tRP、tRAS、CL值这些。RV1126B的DDR控制器手册会告诉你这些参数怎么映射到寄存器里,以及控制器本身有哪些约束条件。原厂参考配置则是一个已经验证过的起点,你可以基于它来改,但一定要理解每个参数的含义,不能盲目照搬。
我一般会先确认几个基本信息:DDR颗粒的型号、容量、位宽、频率。比如我手头这块板子用的是两颗16位DDR4颗粒组成32位位宽,单颗容量4Gb,总容量1GB。确认这些信息之后,再去颗粒手册里找对应的时序表。这里有个容易忽略的点:不同频率下的时序参数是不一样的,你要先确定目标运行频率,再去查对应频率下的参数。
验证DDR配置是否正确的办法比较直接:烧录一个只包含DDR初始化和串口打印的最小固件,看串口能不能正常输出DDR容量信息。如果能正常输出,说明DDR基本初始化成功了。更严格的验证可以跑一段DDR读写测试,往DDR里写特定pattern再读回来对比,确认没有位翻转。这个测试在原厂SDK里通常有现成的工具,可以直接用。
2.3 SDK目录结构的理解方式
RV1126B的SDK目录结构乍一看比较庞杂,但理清楚之后其实很有条理。顶层一般会有几个主要目录:device目录存放芯片相关的配置和启动代码,u-boot目录是引导程序,kernel目录是Linux内核,buildroot或者debian目录是根文件系统,app目录是上层应用示例,external目录是一些第三方库和工具。
我建议在动手改任何东西之前,先花半小时把目录结构过一遍,重点看device目录下的配置文件。DDR参数、启动介质选择、串口配置这些关键信息都在这里。不同板子的差异也主要体现在这个目录里,原厂通常会提供几个参考板级的配置,你可以找一个最接近自己板子的配置作为基础来改。
理解目录结构还有一个好处是,当编译出错或者运行异常时,你能快速定位到问题可能出在哪个环节。比如编译阶段报错,大概率是交叉编译工具链或者某个组件的配置问题;烧录后起不来,可能是DDR配置或者启动介质配置的问题;系统起来了但某个外设不工作,那就要去查内核里对应的驱动配置。
3. DDR配置的核心细节与实操要点
3.1 DDR颗粒关键参数解读
DDR配置里最核心的就是那一组时序参数。我拿几个最关键的来说说它们是什么意思,以及调错了会怎样。
CL(CAS Latency)是列地址选通延迟,简单说就是从发出读命令到数据真正出现在数据总线上的时钟周期数。这个值设小了,数据还没准备好就被读走,读出来就是错的;设大了,性能会下降但一般不会出错。所以调的时候宁大勿小,先保证稳定再优化性能。
tRCD(RAS to CAS Delay)是行激活到列地址选通的延迟。DDR的读写操作是先激活一行,然后再对行内的列进行操作,tRCD就是这两步之间需要等待的时间。这个值不够的话,行还没激活完就去操作列,同样会读到错误数据。
tRP(Row Precharge Time)是行预充电时间,关闭当前行并准备打开新行所需的时间。tRAS(Active to Precharge Delay)是行激活到预充电的最小时间,也就是一行最少要保持激活状态多久。这两个参数配合起来决定了行切换的效率。
这些参数在DDR颗粒手册里都有标称值,单位通常是纳秒。你需要根据DDR的工作频率把这些纳秒值换算成时钟周期数。换算公式是:周期数 = 时间(ns) × 频率(MHz) / 1000。比如tRCD标称13.5ns,DDR频率是1600MHz(注意DDR是双沿传输,实际时钟频率是800MHz,但算周期数时要用数据速率对应的频率来算,具体要看控制器手册的要求),算下来大概是21.6个周期,取整到22。
注意:不同控制器对参数取整的规则可能不同,有的要求向上取整,有的要求取最接近的偶数值,一定要看控制器手册里的说明,不能想当然。
3.2 DDR配置文件的修改位置与格式
在RV1126B的SDK里,DDR配置通常在一个单独的配置文件里,可能是一个头文件或者一个文本格式的配置表。我手头这个版本是在device/rockchip/rv1126b目录下的一个DDR配置文件,里面以宏定义或者数组的形式列出了各个参数。
修改的时候有几个原则。第一,只改你需要改的参数,其他保持原厂参考值不动。原厂参考配置是经过验证的,里面可能有一些你看不懂但确实有作用的设置,贸然改动可能引入难以排查的问题。第二,每次只改一个或一组相关的参数,改完就验证,不要一次性改一大堆然后一起测,出了问题你根本不知道是哪个参数导致的。第三,改之前先备份原文件,这个不用多说,但确实有人会忘。
配置文件里除了时序参数,还会有DDR容量、位宽、bank数量这些结构性参数。这些参数必须和实际硬件完全一致,错一个都可能导致DDR识别异常。比如你的板子是32位位宽,配置里写成了16位,那系统可能只能识别一半容量,或者干脆起不来。
3.3 DDR配置验证的实操步骤
验证DDR配置我一般分三步走。
第一步是编译一个最小启动固件。在SDK里通常有对应的编译目标,比如make loader或者类似的命令,具体看SDK的说明。编译出来的固件只包含BootROM之后的第一段引导代码和DDR初始化部分,体积很小,烧录也快。
第二步是烧录并观察串口输出。把固件通过USB或者烧录器写到板子上,打开串口终端,波特率一般是1500000或者115200,具体看配置。上电后如果DDR配置正确,串口会打印出DDR初始化成功的信息,包括识别到的容量、当前频率等。如果没有任何输出,或者输出乱码,那就要检查串口配置和DDR配置。
第三步是跑DDR压力测试。如果串口能正常输出,但你不放心稳定性,可以在u-boot阶段跑一段DDR测试。RV1126B的u-boot里通常有mtest命令,可以指定地址范围进行读写测试。跑个几轮下来没有报错,基本就可以认为DDR配置是稳定的。
实操心得:DDR测试的时候,建议把测试范围覆盖到整个DDR空间,而不仅仅是开头一段。有些DDR问题只在特定地址区域出现,比如高位地址线接触不良或者某个bank有问题,只测开头一段是发现不了的。
4. SDK编译环境搭建与镜像生成
4.1 交叉编译工具链的选择与配置
RV1126B是ARM Cortex-A7架构,需要用到ARM的交叉编译工具链。原厂SDK通常会自带一个预编译好的工具链,放在SDK的prebuilts或者toolchain目录下。我建议优先使用SDK自带的工具链,因为它是和SDK里的各个组件配套验证过的,兼容性最有保障。
如果你要用自己安装的工具链,需要注意几点。首先是版本要匹配,太新或太旧的工具链都可能导致编译错误或者运行时异常。其次是路径要配置正确,SDK的编译脚本通常会从环境变量里找工具链路径,你需要把工具链的bin目录加到PATH里,或者修改SDK的配置文件指定工具链位置。
工具链配置好之后,可以先用一个简单的hello world程序验证一下能不能正常编译出ARM可执行文件。用file命令看一下生成的文件架构是不是ARM,确认无误再开始编译整个SDK。
4.2 SDK整体编译流程与关键配置
RV1126B SDK的编译通常有一个顶层脚本或者Makefile来驱动。常见的命令是./build.sh加上一些参数来指定要编译的组件和目标板型。比如./build.sh lunch会列出所有可选的板级配置,你选一个最接近自己板子的配置,然后./build.sh就会开始完整编译。
完整编译会依次编译u-boot、kernel、根文件系统和上层应用,整个过程根据机器性能不同可能需要几十分钟到几个小时。第一次编译建议用-j参数开多线程加速,比如./build.sh -j8,具体数字根据你编译机的CPU核心数来定。
编译过程中有几个关键配置点需要关注。一个是板型选择,这个决定了用哪套DDR配置、哪个设备树、哪个根文件系统配置。另一个是启动介质选择,是SPI Flash还是eMMC还是SD卡,不同介质对应的镜像打包方式不同。还有一个是根文件系统类型,buildroot和debian的编译流程和产出物不一样,按需选择。
编译完成后,产出物通常在output或者rockdev目录下,里面会有各个分区的镜像文件,比如uboot.img、boot.img、rootfs.img等,以及一个完整的固件包。
4.3 设备树与板级配置的适配
设备树是Linux内核识别硬件的方式,RV1126B的SDK里每个板子对应一个设备树文件。如果你用的是原厂开发板,直接用对应的设备树就行。如果是自己画的板子,就需要基于参考板级的设备树做修改。
设备树里需要改的东西主要包括:串口引脚配置、DDR容量声明、存储介质配置、外设使能状态。比如你的板子用的串口和参考板不是同一个,就要改对应的pinctrl配置和uart节点。DDR容量如果和参考板不同,也要在设备树里更新memory节点。
改设备树的时候有个技巧:先只改最必要的部分,让系统能启动起来,然后再逐步添加和调整外设配置。一次性改太多,启动不了的时候排查起来很痛苦。我一般会保留一份原始设备树作为对照,改的时候用diff工具对比,清楚知道每一处改动的目的。
5. USB烧写全流程与问题排查
5.1 烧写工具的选择与驱动安装
RV1126B支持通过USB进行烧写,这在开发阶段非常方便,不需要额外的烧录器。烧写工具原厂通常会提供,运行在Windows或者Linux上。我一般在Linux环境下操作,工具是一个命令行程序,也有的版本提供图形界面。
在Linux下使用USB烧写,需要确保系统能正确识别芯片的USB设备。RV1126B在烧写模式下会枚举为一个特定的USB设备,你需要确认lsusb能看到它。如果看不到,可能是驱动问题或者USB线缆问题。有些USB线只能充电不能传数据,这个坑我踩过,换根线就好了。
Windows下需要安装对应的USB驱动,驱动安装不成功的话设备管理器里会显示未知设备。驱动安装有时候会遇到签名问题,需要临时禁用驱动签名强制或者用测试签名模式,具体操作看系统版本。
5.2 进入烧写模式的操作方法
RV1126B进入烧写模式通常有两种方式。一种是通过按键组合,板子上一般会有一个recovery按键或者maskrom按键,按住这个键再上电或者复位,芯片就会进入烧写模式。另一种是通过串口命令,如果系统已经能启动到u-boot或者Linux,可以通过命令让系统重启进入烧写模式。
我一般用按键方式,因为最可靠,不依赖系统当前状态。操作顺序是:先按住按键不放,然后给板子上电或者按复位键,保持按住几秒钟后松开。这时候串口应该没有正常启动log输出,因为芯片停在烧写模式了。然后在PC端运行烧写工具,应该能识别到设备。
如果按键方式不生效,检查一下按键是不是接对了,或者按键对应的GPIO在DDR配置里是不是被复用了。有些板子设计的时候没注意,把烧写模式选择引脚和别的功能复用了,导致按键不起作用。这种情况就要查原理图确认。
5.3 烧写过程与常见报错处理
烧写工具识别到设备后,选择要烧写的固件包,点击开始或者执行烧写命令。烧写过程会依次写入各个分区,界面上或者命令行里会显示进度。整个过程几分钟到十几分钟不等,取决于固件大小和USB速度。
烧写过程中常见的报错有这么几类。一类是"设备未找到",这个通常是驱动问题或者USB连接问题,按前面说的排查。另一类是"下载失败"或者"校验错误",可能是固件包不完整或者USB传输不稳定,可以重新生成固件包或者换个USB口试试。还有一类是烧写完成了但系统起不来,这个就要回到DDR配置和启动介质配置去查。
避坑技巧:烧写的时候尽量用主板自带的USB口,不要用前面板的扩展口或者USB Hub,供电和信号质量都更有保障。另外烧写过程中不要拔插其他USB设备,避免干扰。
5.4 烧写后的首次启动验证
烧写完成后,给板子重新上电,观察串口输出。正常的启动流程会先打印BootROM信息,然后是DDR初始化信息,接着是u-boot的启动log,最后是内核启动log和根文件系统挂载信息。如果能看到登录提示符,说明整个链路基本通了。
首次启动可能会遇到根文件系统挂载失败的问题,常见原因是分区表不对或者文件系统类型不匹配。检查一下分区配置和实际烧写的镜像是否一致。另外首次启动可能会比较慢,因为系统要做一些初始化工作,耐心等一会儿,不要急着断电。
如果串口完全没有输出,先确认串口线接对了没有,TX和RX有没有接反,波特率对不对。这些基础问题看似简单,但实际排查中经常是问题所在。我遇到过好几次是串口线松了,折腾半天才发现。
6. 常见问题速查与独家经验
6.1 DDR相关典型问题排查表
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 串口无任何输出 | DDR未初始化成功 | 检查DDR配置参数,确认颗粒型号匹配 |
| 串口输出乱码 | 波特率不对或DDR不稳定 | 确认波特率设置,降低DDR频率测试 |
| 识别容量只有一半 | 位宽配置错误 | 检查DDR位宽配置是否与实际硬件一致 |
| 运行一段时间后死机 | DDR时序余量不足 | 适当放宽时序参数,增加余量 |
| 特定地址读写错误 | 地址线或bank配置问题 | 跑全地址范围DDR测试定位问题区域 |
这张表里的问题我基本都遇到过,其中"识别容量只有一半"这个坑最隐蔽,因为系统能启动,只是内存少了一半,不仔细看log根本发现不了。后来我养成了习惯,每次DDR配置改完,第一件事就是确认串口打印的容量和实际颗粒容量是否一致。
6.2 编译与烧写环节的避坑清单
编译环节最容易出问题的是工具链路径和环境变量。我建议把工具链配置写到一个脚本里,每次编译前source一下,避免手动设置遗漏。另外编译前先make clean一下,尤其是改了配置文件之后,不clean的话可能用的是缓存的旧配置。
烧写环节最容易出问题的是USB连接和固件包完整性。固件包生成后可以用校验工具算一下MD5,和烧写工具显示的校验值对比,确认传输过程中没有损坏。USB线缆尽量用短的、质量好的,长线缆或者劣质线缆是烧写失败的常见原因。
还有一个经验是,烧写工具和SDK版本要匹配。用旧版烧写工具烧新版SDK生成的固件,可能会因为分区格式或者镜像头信息不兼容而失败。尽量用SDK里自带的烧写工具,或者确认版本对应关系。
6.3 从零适配新板子的完整检查清单
如果你是在一块全新的板子上做移植,我整理了一个检查清单,按顺序过一遍能避免大部分低级错误。
- 确认DDR颗粒型号、容量、位宽、频率,和原理图核对
- 确认启动介质类型和启动模式引脚配置
- 确认串口引脚和波特率配置
- 确认电源各路电压正常,尤其是DDR和核心电压
- 确认晶振频率和参考时钟配置
- 确认烧写模式按键或跳线可用
- 准备一份原厂参考配置作为对照
- 准备好串口终端和烧写工具
这个清单看着简单,但每一条都对应着我实际踩过的坑。比如电源电压,有一次板子DDR供电偏低,导致DDR初始化偶尔成功偶尔失败,排查了很久才定位到是电源芯片反馈电阻焊错了。
6.4 性能调优与稳定性验证的进阶思路
当基本功能跑通之后,如果还想进一步优化,可以从几个方向入手。DDR时序参数在保证稳定的前提下可以尝试收紧,提升内存带宽。但每次收紧都要跑完整的压力测试,确认没有引入偶发错误。我一般会用memtester这类工具跑长时间测试,至少跑几个小时,确认稳定后再固化配置。
启动速度优化是另一个方向。可以通过裁剪内核、优化u-boot启动流程、使用更快的启动介质来缩短启动时间。RV1126B的启动速度在优化后可以做到比较理想的水平,具体能到多少取决于你的配置和优化程度。
稳定性验证方面,建议做高低温测试和长时间老化测试。DDR对温度比较敏感,高温下时序余量会变小,如果常温下勉强稳定,高温下可能就出问题了。所以如果产品有温度要求,一定要在温度极限条件下验证DDR稳定性。
7. 一些个人体会
RV1126B这个平台整体来说资料还算比较齐全,原厂SDK的完成度也比较高,但移植过程中的细节问题还是不少。我的体会是,DDR配置这块值得多花时间,把原理搞清楚,把参数调稳,后面的事情会顺很多。很多人急于求成,DDR随便配一下就想跑系统,结果后面各种莫名其妙的问题,回头再查DDR,反而浪费更多时间。
另外就是养成记录的习惯。每次改了什么参数、为什么改、改完什么现象,都记下来。移植过程中会做很多次尝试,不记录的话过两天就忘了当时为什么那么改。我现在的做法是维护一个移植日志,按时间顺序记录每次操作和结果,排查问题的时候翻日志比翻记忆靠谱得多。
最后说一个小的技巧。如果你手头有原厂的开发板,建议先用开发板把整个流程跑通一遍,熟悉每个环节的正常现象是什么样。然后再在自己的板子上做移植,遇到异常的时候,你至少知道正常应该是什么表现,排查起来方向更明确。这个"先跑通再移植"的思路,在嵌入式开发里屡试不爽。