DDR/SDRAM 训练余量与量产测试实战:样机千挑万测没问题,量产第一批就”随机死机”,我把训练余量和测试覆盖从头捋了一遍

2026年9月27日 0 By admin

上一期聊 MQTT 证书的时候提过一嘴,这期来还债:DDR/SDRAM 的训练余量管理与量产测试。

事情是这样的。我们的一个工控板(i.MX6 + DDR3L,双颗粒 2GB),样机阶段三块板子来回跑了两个多月,高低温箱也过了一遍,稳如老狗。结果量产第一批 200 块板子,装机到现场不到两周,陆续回来了 7 台”随机死机 / 偶发启动失败”的反馈,而且有个诡异规律:出问题的机器集中在南方现场的夏季高温环境,换到同一批次的北方机器就没事。

工程上的巧合都不算巧合。最后查下来,这 7 台里 5 台是 DDR3 训练余量不足,在高温下写眼图闭合,读数据出错——但错误率低到固件的内存自检根本抓不住,表现为”莫名其妙死机”。这次把训练余量和量产测试的坑从头捋了一遍,记录如下。

先补课:训练余量到底是个什么东西

DDR3/DDR4 控制器在上电初始化时会做 read/write training(读/写训练):通过逐级延迟读写校准序列(write leveling、read gate training、read data eye training 等),为每根数据线找到采样窗口中心,弥补 PCB 走线长度差异、颗粒个体差异和温度漂移。

训练完成后,控制器内部其实有一组校准参数(延迟/相位),而每个参数离”出错边界”的距离,就是 训练余量(training margin)。

关键认知:训练结果不是二值的”成功/失败”,而是一个连续的眼图窗口。大部分控制器的训练算法只要找到窗口就停,不管这个窗口有多窄——窗口哪怕只有理想情况 10% 的宽度,训练也算”成功”,设备也”能跑”。

所以”训练通过”和”训练良好”是两码事。我当年就是没搞清这一点,才让余量不足的板子流了出去。

为什么样机阶段测不出来

复盘时我把原因列了张表,供自查:

差异维度 样机阶段 量产/现场
样本量 3~10 块,且常挑”好板”测试 成百上千,颗粒批次混合
颗粒批次 通常同一批 DRAM 不同批次、不同封装厂混用
温度覆盖 实验室 25°C 为主,高低温箱时间有限 车间、户外、密闭机柜,长时间极限温度
电压 实验室电源稳 现场电源波动、线损压降
焊接质量 手工/小批量重点盯 回流焊批次波动,虚焊/枕Head 随机出现
时间 几天~几周 数月到数年,老化漂移

这里最大的坑是颗粒批次差异:同一型号的 DDR3 颗粒,不同批次/不同晶圆厂的 $t_{DQSQ}$、输出驱动强度、输入电容都有分散。样机用的那一批恰好居中,训练余量漂亮;量产混进偏快或偏慢的批次,余量就被吃掉一截。你的 PCB 是按”典型参数”设计的,而大自然会给你寄来”边缘参数”的料。

第一步:把训练余量”看见”

要管理余量,前提是能读到它。不同平台差异很大:

  • NXP i.MX6/7/8(DDRC):通过 MMDC 寄存器可以读到读写延迟校准值,官方有 DDR Stress Test 工具能扫出完整的读写眼图并给出余量百分比;
  • TI AM335x/AM57x:DDR PHY 的 IO 配置寄存器里有各 byte lane 的 delay 值,SBL/u-boot 日志会打印;
  • STM32MP1:DDR 控制器训练由 TF-A 在启动早期完成,日志里有训练结果;
  • 全志/瑞芯微: bootloader 阶段打印训练结果,部分平台有官方压测工具。

行动建议很直接:每个用 DDR 的平台,接手第一件事就是把”训练结果日志”和”余量读数方法”找出来记到项目 wiki 里。看不到余量的项目,等于闭着眼睛开DDR 的车。

我们板子上,i.MX6 的 DDR Stress Test 扫出来的结论是:常温写眼图余量 42%(健康),把温度抬到 70°C 颗粒结温时跌到 11%——这就是那 7 台机器的病根。

第二步:定余量红线,别让它裸奔

看到余量之后要定一条工程红线。我们的标准(参考了不少大厂惯例):

  • 常温余量 < 25%:设计有风险,回头查 PCB(阻抗、走线、参考平面)和端接;
  • 全温区(最低温度~最高结温)+ 电压 ±5% 摆动下,余量最低点 ≥ 15%:量产可接受的底线;
  • 训练算法支持”窗口中心化”的,必须打开——很多控制器有”继续训练直到窗口对称”或”加大训练遍数取最优”的选项,默认关着。

红线落在流程上就是:设计定型前必须做一次全温区眼图扫描,把余量-温度曲线归档。这条曲线就是你的设计余量凭证,量产测试的判定阈值也从这里来。

第三步:固件侧的余量防线

光靠生产测试把关还不够,固件要有三道防线:

1. 启动时检查训练结果。 很多平台训练失败的直接表现是启动挂死或 DDR 初始化超时,但有些控制器训练”勉强通过”时会有 warning 状态位或校准值越限标志。启动代码里要显式读出来,越限就记录到日志/上报云端,别闷头继续跑。

2. 温度触发重训练。 DDR3 有一组温度传感器寄存器(MR4 读温度),部分控制器支持温度漂移后自动重训练。不支持自动的,就要软件轮询颗粒温度(通过 MR4 或板上的温度传感器),越限后触发控制器重训练。我们板子上一版固件没有这逻辑,高温下校准参数漂出窗口也不会自我修正——补上之后,高温复测的出错率直接归零。

3. 后台周期性内存巡检。 挑一块”安全的”未用内存区域(别巡检自己正在用的栈和堆),周期性写入 walking pattern 再回读。这不是替代生产测试,是给现场运行加一个”错误计数器”——真出问题,至少日志里有”DDR ECC/巡检错误 N 次”这种实锤,而不是一句”死机原因不明”。

有条件上带 inline ECC 的平台(如 i.MX8 的 DDRC 支持)就直接开 ECC,单 bit 错误自动纠正 + 双 bit 错误触发上报,是更彻底的方案。

量产测试:测什么、测多久

生产测试的目标是用最短时间覆盖”焊接质量 + 颗粒个体 + 余量底线”三个风险。我们最终的测试项:

测试项 覆盖目标 单板耗时
启动训练结果检查(校准值/越限标志) 颗粒个体差异、焊接 < 1 s(并入启动)
Memtest 模式全量扫(march 类算法) 焊接开短路、颗粒坏点 40~90 s(视容量)
眼图余量抽读(平台支持时) 余量底线 5~10 s
高温仓 60°C 复测(抽检 + NG 板全测) 温度相关边缘品 按批次

几个实践经验:

march 算法比”写全 0 读全 0 / 写全 1 读全 1″强得多。 简单的 0/1 图样对相邻位短路、data line 串扰几乎无感。业界常用 March C-、March SS,覆盖率有理论依据。u-boot 的 mtest 太糙,我们最后是移植了一份开源的 march C- 实现,2GB 全量约 70 秒。

全量扫和抽样扫要搭配。 全量 march 保证每块板都过一遍基本盘;对温度余量的验证太耗时,只能抽检 + 侧重测 NG 板。但首批量产必须 100% 全项,等批次余量统计稳定了再放宽抽检比例。

测试失败要分级,别一刀切判 NG 报废。 我们把 NG 分三类:硬故障(开短路/坏位)→ 返修;余量型(训练越限但功能正常)→ 复测 + 热测试定位;偶发型 → 重跑两遍再判。第一周按这个流程,7 类失败里 5 类其实是回流焊温度曲线没调好导致的焊接问题,换曲线后 NG 率从 3.5% 降到 0.4%。

生产治具与测试固件的工程细节

量产测试不是”把固件烧进去跑 memtest”这么简单,几个吃过的亏:

  • 测试固件要独立、最小化:单独编一个 boot + DDR 测试 + USB/网口报告的小固件,别用正式固件凑合——正式固件跑到一半挂了,你分不清是 DDR 问题还是业务代码问题;
  • 结果必须结构化上报:每块板输出 JSON(板号、批次、测试项、错误地址、错误图样、训练校准值),存到产线数据库。错误地址分布是金矿:错误集中在某个 byte lane → 查该组走线;随机分布 → 查颗粒或供电;
  • 记录训练校准值作为”出生指纹”:每块板的训练值存档,日后现场返修对比这组数据,能立刻判断是”焊点劣化”(值漂移大)还是”固件/温度问题”(值没变);
  • 治具要注意信号完整性:测试座/探针的寄生电容会改变信号质量,治具上”NG”的板子装到整机上正常,先怀疑治具。

现场返修流程:7 台机器的定位路径

最后复盘那 7 台机器的定位顺序,可以当模板用:

  1. 复现条件确认:现场日志显示死机集中在 14:00–16:00(机柜最热时段)→ 高度怀疑温度相关;
  2. 训练值回读:返修板上电读训练校准值,与产线存档对比,5 台值偏移明显;
  3. 温箱复现:50°C 起步每 10°C 阶梯保载 1 小时跑压测,4 台在 65–70°C 出错,1 台不出了(那台后来确认是现场供电问题);
  4. 眼图扫描:出错板高温写眼图余量 8–12%,正常板同温度 35%+ → 实锤训练余量不足;
  5. 根因归档:其中 3 台是某批次颗粒 + 布局上该数据组回流焊后阻值偏移叠加,1 台是屏蔽罩压到走线区(装配公差);

最终整改三条:改测试固件加高温项抽检、固件加温度重训练、PCB 下版把该组走线挪出屏蔽罩投影区。整改批次至今零反馈。

踩坑清单(血泪浓缩版)

  • “训练通过”不等于”训练良好”,一定要拿余量数字说话;
  • 颗粒批次差异是量产最大的变量,首批量产务必混批次验证;
  • 只测常温 = 没测,DDR 余量对温度极其敏感,全温区曲线必须归档;
  • 简单 0/1 图样的内存测试是心理安慰,上 march 类算法;
  • 训练校准值存档,返修对比数据省一半定位时间;
  • 测试固件与业务固件分开,否则死因永远说不清;
  • 固件要有温度重训练或 ECC,别指望训练一次管一辈子;
  • 产线 NG 分级处理,盲目报废只会掩盖真问题;
  • 治具本身会引入失效,治具 NG、整机 OK 的板子先查治具;
  • 错误地址分布比错误数量有信息量,按 byte lane 归因。

自查清单

最后附上我整理的 DDR/SDRAM 训练余量与量产测试自查清单:

  • ☐ 已找到平台的训练结果/余量读数方法并写入项目文档
  • ☐ 设计定型前完成全温区眼图扫描,余量-温度曲线已归档
  • ☐ 全温区 + 电压 ±5% 下余量最低点 ≥ 15%,不达标已回查 PCB
  • ☐ 控制器的窗口中心化/多次训练选项已评估并启用
  • ☐ 启动代码显式检查训练状态位与校准值越限标志
  • ☐ 固件已实现温度触发重训练或已启用 inline ECC
  • ☐ 固件有后台内存巡检与错误计数上报
  • ☐ 量产测试含 march 类算法全量扫描,测试固件独立于业务固件
  • ☐ 测试结果结构化存档(含训练校准值”出生指纹”)
  • ☐ NG 分级处理流程(硬故障/余量型/偶发型)已定义
  • ☐ 首批量产 100% 全项测试,后续批次按统计数据放宽抽检
  • ☐ 治具信号完整性已验证(治具 NG 整机 OK 的仲裁流程存在)

—

DDR 这条线还有个尾巴:ECC 的具体落地与错误上报策略,等下次展开。如果这篇对你有用,欢迎在评论区聊聊你遇到的”随机死机”最后是怎么定位的。