
刚拿到这款定制的RV1126B板卡时我差点被一行启动日志劝退板载DDR3 1GB颗粒的组合让官方SDK默认的DDR配置完全失效串口只打印一半就黑屏整个系统连U-Boot都进不去。换了内存颗粒、改了DTS、重编SDK都试过之后最后发现根子其实在DDR初始化序列和USB烧写路径上。这篇文章主要整理我从DDR配置异常一路排查到USB固件烧写的完整过程适合正在做RV1126B或类似瑞芯微平台定制板卡、又刚好卡在内存初始化或固件下载环节的朋友参考。1. 项目起点为什么要在这块“非标”RV1126B板卡上较真DDR1.1 板卡硬件底细与烧录环境搭建这次拿到的核心板主控是RV1126B。这颗芯片在IPC、智能摄像头、边缘视觉盒子领域用得非常多四核Cortex-A7配上自研NPU算力做轻量级视觉任务绰绰有余。官方评估板大多搭配DDR4或LPDDR3而我手里这块为了控制BOM成本用了两颗DDR3 512Mx16颗粒拼出1GB容量供电1.5V封装是标准的96ball FBGA。问题在于SDK里默认的DDR配置是按DDR4或者单颗2Gb颗粒来的拿到手直接烧官方固件内存初始化大概率会翻车。烧录环境我建议从一开始就统一好不然后面全是冤枉路。主机我用的是Ubuntu 20.04 LTSSDK编译和烧写都在同一台机器上做。Windows侧除了备用主要用来装瑞芯微的DriverAssistant驱动和RKDevTool烧录工具。串口调试必须准备一个USB转TTL模块FT232R、CP2102N、FT231X这些芯片方案的模块我都试过稳定性都够用。接线就是开发板UART调试口的TX、RX、GND分别对应模块的RX、TX、GND核心板如果是3.3V电平模块也选3.3V避免电平不匹配。1.2 SDK整体结构与拿到手后的整理动作瑞芯微的SDK是一套典型的多仓库组合核心包括u-boot、kernel、buildroot或者Debian/Android、以及一个叫rkbin的二进制仓库。rkbin里装的是芯片厂商闭源编译好的DDR初始化代码、ATF、Miniloader等关键二进制。很多人第一次看到这个目录会觉得“既然DDR初始化是闭源的那我改不了”这是最大的误解。DDR初始化的代码虽然以二进制形式存在但它的工作参数完全可以通过配置工具提取和修改包括DDR类型、频率、时序项、驱动强度等后面第3节会详细讲。SDK首次下载后建议做两件事。第一把device/rockchip/rv1126b目录下的板级配置文件整体对比一遍找到BoardConfig*.mk看清楚默认选择的是哪个DTS、哪种内存配置、哪种固件打包方案第二提前安装编译依赖包括repo工具、gcc-arm-8.3交叉工具链、以及Python2/3环境。我在新机器上装SDK时最容易漏的是libssl-dev、lz4、pkg-config这类基础包缺了会在编译到一半时莫名报错。还有一个很多人忽略的点RK SDK的编译脚本有时候会依赖/bin/bash而非/bin/dashUbuntu默认sh指向dash最好用sudo dpkg-reconfigure dash改成bash能省掉一些诡异问题。2. DDR配置异常启动日志里的“死亡线索”2.1 串口终端只留三行字的现场第一次上电时串口输出停在U-Boot SPL阶段。具体日志大概长这样DDR Version 1.11 20210918 In Channel a: DDR3 0MB OutDDR3 0MB这个结果翻译成人话就是DDR初始化代码检测到了DDR3颗粒但是读容量时拿到了0。原因通常有两个方向颗粒和SoC之间的数据线或地址线连接有问题或者DDR配置里面选择的“内存密度/位宽/列地址数”和实际颗粒对不上。如果是PCB硬件问题一般伴随的是所有DDR访问全部异常但如果板子是照参考设计画的大概率是软件配置问题。我当时先量了关键的电源和参考电压VDDQ 1.5V和VTT 0.75V都正常于是把怀疑对象锁定到DDR配置参数上。这里建议经验不足的朋友先做一个快速验证把bootloader的串口波特率降到1500000抓完整启动日志很多DDR报错信息是会被后续乱码冲掉的日志完整度直接决定排查速度。2.2 Rockchip DDR初始化到底做了什么瑞芯微SoC的DDR初始化流程简单说就是BootROM把rkbin里的DDR初始化代码加载到内部SRAM执行这段代码负责完成内存颗粒的上电初始化、ZQ校准、PHY训练、控制器参数配置最后把检测到的DDR容量和类型传给U-Boot主程序。整个过程中最影响成败的是两部分PHY Training物理层训练通过读写DDR颗粒的MRS寄存器、执行读写DQS门限训练找到采样窗口的最佳位置。如果RL读延迟和WL写延迟设置不对容量检测都可能停留在0MB。控制器时序参数包括CL、tRCD、tRP、tRAS、tRFC等。DDR3的时序参数可以在颗粒手册里查到但SDK配置工具里经常为了兼容不同颗粒给了一个“通用兼容档”这个档位放在DDR4上没事放在某些DDR3颗粒上就会触发初始化失败。从搜索经验看很多人问“RV1126B可用的DDR3内存1GB的有哪些”其实就是想绕开这种摸黑调参的烦恼。如果你用的是常见的1Gb x16 DDR3比如三星K4B1G1646E、海力士H5TQ1G63EFR、美光MT41K256M16、南亚NT5CB256M16DP这类配置上抓大方向就行密度选1Gb位宽选x16bank数8行地址15列地址10。这几个参数只要有一个错后续就是灾难。颗粒型号制造商组织速率等级常见应用K4B1G1646E-BCF8三星64Mbx16DDR3-16001GB双片方案H5TQ1G63EFR-RDC海力士64Mbx16DDR3-16001GB双片方案MT41K256M16TW-107美光64Mbx16DDR3-16001GB双片方案NT5CB256M16DP-DI南亚64Mbx16DDR3-16001GB双片方案2.3 从芯片数据手册提取有效参数很多做应用层开发的工程师第一次接触DDR调参会直接跑到U-Boot源码里搜“CONFIG_NR_DRAM_BANKS”发现改了没效果。这是因为瑞芯微平台的内存参数大头不在U-Boot源码里而在rkbin的DDR二进制配置中。你可以用瑞芯微提供的DDR配置工具在SDK里通常叫ddrbin_tool或类似名称打开原始的ddrbin二进制直接查看和修改DDR类型、工作频率、颗粒密度等参数。从数据手册里最需要抄出来的几个参数是tCK周期时间决定支持的最高频率。DDR3-1600的tCK为1.25nsDDR3L-1600同样。CL-tRCD-tRP例如11-11-11这组数字决定了CAS Latency、RAS到CAS延迟、Row Precharge时间直接写进配置工具的时序表。tRFC刷新周期。DDR3的tRFC一般在110ns到350ns之间1Gb密度普遍在110ns附近配置太大会降低性能太小会刷不亮内存。我当时做的事很简单把SDK默认的ddrbin导出来备份一份然后用配置工具把DDR类型改成DDR3密度改成1Gbx16位宽再手动填入数据手册里拿到的时序参数。注意不同SDK版本的工具界面差异巨大有些是文本配置文件有些是图形界面但核心字段是通用的。改完以后重新生成ddrbin放回rkbin对应目录重编U-Boot即可。3. 调整DDR配置并重建固件3.1 修改DDR初始化序列的两种路线调整RV1126B的DDR初始化实践中我用通的有两条路线。路线一通过ddrbin工具改rkbin二进制。这是最正统的方式。把原始ddrbin_*文件复制出来用工具打开修改内存类型和时序参数后保存覆盖回rkbin。编译U-Boot时会把这个新的ddrbin打包进SPL里。改动最小风险最低适合只是密度或时序不匹配的情况。路线二修改U-Boot DTS里的DDR时序节点。U-Boot的DTS里会有一个类似ddr_timing或ddr_params的节点里面包含不同频率档的时序数据。你可以按官方注释的标准格式填入和ddrbin匹配的时序。要特别留意DTS改动只影响U-Boot阶段可见的时序配置真正决定SPL能否初始化成功的还是ddrbin。两条路线的结果需要保持一致否则系统能启动但运行不稳定。我当时的时间线是这样的先用工具确认DDR3参数再检查DTS时序是否匹配最后重新生成固件。整个过程最怕的是“只改一处”因为两处参数打架导致的症状非常具有迷惑性比如平时正常、高负载就死机。3.2 固件编译与打包的具体流程在瑞芯微SDK中编译完整镜像一般路径是cd u-boot ./make.sh rv1126b cd ../kernel make ARCHarm rv1126b_defconfig make ARCHarm rv1126b.img -j$(nproc) cd .. ./build.sh第一次编译建议加./build.sh -U跳过Ubuntu根文件系统构建单独验证U-Boot和内核能起来。我当时为了省时间把rootfs用了buildroot的预编译版本这样可以更快进入DDR验证阶段。编译完成后的输出目录中最关键的固件组合包括MiniLoaderAll.bin包含DDR初始化和MiniLoader的烧录引导文件。parameter.txt分区表文件烧写时规定了每个分区地址和大小。uboot.img、boot.img、rootfs.img各分区镜像。官方SDK还提供了自动打包脚本会把上述文件打包成单个update.img方便直接用完整固件烧写。如果只是验证DDR稳定性没必要做完整包直接烧MiniLoaderAll.bin加uboot.img就行。3.3 稳定性验证从memtester到跑应用内存能初始化不代表稳定这一条必须强调。我当时按照正确参数重编固件后U-Boot能进菜单了内核也能起但跑人脸检测模型时偶尔会崩。后来用内存压力测试才发现一个时序参数还是偏紧。U-Boot阶段可以先用内置的mw、md命令做简单读写测试mw.b 0x200000 0x5a 0x100000 md.b 0x200000 0x100000这是纯内存读写能快速发现地址线或数据线的固定错位但对时序问题不敏感。更可靠的做法是进入Linux后用memtester跑大块压力测试memtester 800M 5memtester会对内存做伪随机序列的写入回读、位翻转测试能暴露大多数时序边界问题。跑了三轮没报错后我又在板子上跑了openCV的连续帧处理任务让NPU和CPU同时大量访问DDR模拟真实负载。这一步非常关键很多在idle下看不到的问题一到高带宽访问场景就现原形。4. USB固件烧写准备、接线与常见坑4.1 串口控制台与USB烧录的区别DDR配置修好之后另一个容易劝退新人的环节是USB固件烧写。这里首先要厘清概念串口控制台调试和USB烧录是两条完全独立的路径。串口控制台走的是UART作用是看日志、进命令行USB烧录走的是SoC内置的USB下载模式由BootROM或Loader固件提供USB枚举服务主机端用专用工具把镜像写到eMMC或SPI Flash。很多朋友在调试阶段只插了USB转串口线就以为能烧录固件结果RKDevTool一直报“设备未连接”。原因就是没有让板子进入Loader模式主机的USB口上根本看不到设备。RV1126B这类芯片一般有两种方式进入Loader模式一是按住板上的RECOVERY键再上电BootROM检测到按键状态后进入下载模式二是U-Boot命令行执行rbrom或相关命令软重启进入。不同板卡进Loader的方式略有区别但原理相同。4.2 进入Loader模式与主机驱动准备正确进入Loader模式后Linux主机用lsusb可以看到瑞芯微的USB设备描述符一般显示2207:350a这类ID。Windows下第一次插入会提示发现未知设备此时需要安装瑞芯微官方DriverAssistant驱动安装完能在设备管理器里看到“Rockchip USB Device”或类似名称。主机侧的USB转串口芯片驱动也要提前装好。FT232R、FT231X走的是FTDI的VCP驱动Linux内核自带ftdi_sio模块基本插上就能识别CP2102N走的是Silicon Labs的驱动Windows下需要单独的CP210x驱动包Linux下也有cp210x内核模块。当时我在Windows下折腾了快半小时结果发现是CP2102N驱动版本太老导致串口号分配异常换新驱动后瞬间解决。4.3 烧写工具的操作细节Windows下最常用的是RKDevToolLinux下则是upgrade_tool。两者的烧写逻辑一样只是工具形态不同。简单流程如下打开RKDevTool点击“升级固件”页签。选择完整的update.img工具会自动解析镜像和分区。确认设备已经枚举为Loader设备点击“升级”。等待擦除、写入、校验全部完成后拔线重启。如果只需要单独烧某个分区可以在“烧录镜像”页签里指定起始扇区和镜像文件比如只更新uboot.img。这里务必注意分区表parameter.txt要和你烧写的镜像一一对应分区表错位会导致系统起不来或者文件系统挂载失败。补充一句烧写过程中如果提示“下载Boot失败”大概率是Loader版本和工具版本不匹配比如SDK很新但用了老版本的RKDevTool换用SDK配套的upgrade_tool或新版工具即可。4.4 USB枚举失败时的排查手段USB烧录最常见的故障就是设备插上去没反应。排查顺序我建议按下面来确认USB线是数据线。很多USB线只能充电不能传输数据插上去当然没反应。换一根已知能传数据的线再试。确认进入了Loader模式。串口能看到Loding...或Loader相关输出主机的lsusb能看到设备。确认USB接口的DP/DM没有接反。这是硬件设计问题板厂打样时如果USB座子DP/DM接反系统内Linux可能不受影响但Loader枚举会失败。用USB抓包工具确认枚举过程。如果是协议层面的问题能看到主机发出的SET_ADDRESS请求没有得到设备应答这时候更可能是USB PHY或者晶振电路的问题。另外一个高频坑是用5V电源供电不足。RV1126B在USB烧写时同时驱动eMMC和USB如果供电能力弱USB枚举会不稳定表现为时好时坏。我给板子换成5V/3A的电源之后这一类问题基本消失。5. 让我少走弯路的几条经验5.1 画板阶段就要想清DDR的“潜规则”这次踩坑虽然是软件配置问题但我在排查过程中把硬件约束也想了一遍。DDR的地址线等长、DQS/DQ走线分组、VREF参考电压走线这些在PCB设计阶段就要严格按瑞芯微硬件设计指南做。网上关于“AD18 DDR地址线等长设置”的问题很多其实核心就一条同一组信号线的长度差要控制在几十mil以内跨层换孔要成对补偿而不是单纯追求线长相等。如果你买的是现成核心板这些硬件问题基本不用操心但如果是自己画板强烈建议打样前让后端工程师把DDR部分的阻抗、等长、参考平面逐项过一遍。DDR这类高速信号稳定工作是设计出来的不是调试出来的后期软件再怎么调时序都救不回一个布线工艺稀烂的板子。5.2 备份原始固件的优先级最高我在调DDR配置时一开始就忘了把SDK下载的官方固件完整备份结果改坏了ddrbin后想回退发现原始文件已经被覆盖只能重新下载SDK白白浪费了一晚上。后来我形成习惯每次拿到开发环境第一步就是把rkbin目录、原始update.img、parameter.txt、板级DTS全部归档到另一个目录修改任何文件前先做diff修改后记录改动项。这个习惯在调试USB烧写时帮了我大忙。因为只要烧写过程中把Loader搞坏板子就可能进不了Loader模式只剩MaskRom模式能救。在MaskRom模式下RKDevTool同样可以烧写但需要手动指定Loader文件。有备份在手恢复就是几分钟的事没备份就只能苦等重新下载。5.3 交叉验证永远是解决玄学问题的钥匙当DDR问题和USB问题撞在一起时很容易陷入“改了A影响B”的混乱。我的做法是建立一套稳定的交叉验证流程硬件上用万用表确认DDR供电和时钟软件上用串口完整抓日志固件上每次只改一个配置变量。这三个维度至少有两个指向同一个结论时我才会把它当成根因。比如这次DDR容量为0的问题如果只看串口日志会怀疑是物理连接故障但结合DDR配置工具里读出来的参数值发现颗粒密度填错就能确定是软件问题。再比如USB烧写失败如果只看RKDevTool报错会以为主机驱动没装好但当lsusb能看到设备但协议层失败时就要转向检查硬件和电源。这套交叉验证思路远比单独死磕某一个工具管用。写在最后的一块“补丁”如果你也在做RV1126B或者类似的瑞芯微平台移植我的建议很直接先确认DDR配置与颗粒参数一致再谈固件烧写先把串口日志完整抓下来再谈定位问题先把原始固件备份好再谈修改SDK。DDR配置异常和USB烧写这两座大山说到底都是“配置与硬件匹配”的问题只要参照数据手册用对工具保持日志完整它们都是可以系统解决的事。至于我那块板子最终在修正DDR配置后稳定跑了大半个月后续我还在继续调DDR频率档试图找一个性能和温升的平衡点。如果你在RK平台移植上也有类似经历欢迎一起交流排坑思路。