ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

DRAM刷新机制详解:从电容漏电到时序参数与Row Hammer

DRAM刷新机制详解:从电容漏电到时序参数与Row Hammer 不知道你有没有过这种经历读芯片手册看到 refresh 相关时序参数时直接跳过觉得那是 DRAM 控制器该操心的事直到自己写内存控制器、调嵌入式内存时序或者被行锤击Row Hammer的安全公告砸到头才被迫回头补课。我开发过几轮 DDR 控制器也在小系统里纠结过 PSRAM 到底是不是真的“不需要刷新”现在可以把这些散落的知识整理成一份清单式笔记。刷新的本质很简单DRAM 里的电容会漏电必须定时“重写”一次否则数据就没了。但刷新牵扯到的时序参数、模式选择、温度影响、与不同内存类型的对比每一条都有坑。这篇基础小知识三适合刚接触内存底层原理的硬件工程师、嵌入式开发者也适合面试前想快速理清 DRAM 刷新知识体系的朋友。1. 为什么 DRAM 必须刷新SRAM 和 PSRAM 为什么不用1.1 一个存储单元就是一个“水桶”DRAM 的存储单元是“1T1C”结构一个晶体管加一个电容。电容里存的是电荷存 1 就是有电荷存 0 就是没电荷。问题在于电容不是理想的它无时无刻不在漏电。哪怕晶体管已经断开电容里的电荷也会通过介质、衬底慢慢跑掉。你可以把每个存储单元想象成一个底部有微小漏水孔的桶如果不去管它过一阵子桶里的水电荷就漏到看不清是满的还是空的。这个“漏到看不清”的时间就是保留时间Retention Time。行业内一般按 64 毫秒作为目标值也就是 0 到 85 摄氏度范围内每一行数据必须至少被重写一次才能保证不丢。温度越高漏电越快所以 85 度以上工作的一般会把刷新周期收紧到 32 毫秒。SRAM 则是用双稳态电路保存数据说白了就是两个交叉耦合的反相器只要供电不断它的状态就能一直维持不需要刷。这也是 SRAM 接口简单、随机访问更快的原因。但你只要对比一下两者的单元面积就会发现DRAM 单元面积小得多内存密度高、价格低才能在内存条上堆出几十 GB 容量。SRAM 单元要用 6 个晶体管一样工艺下做出来的容量差着数量级所以 SRAM 只能用来做 cache、寄存器堆这种容量小但对延迟极敏感的地方。1.2 PSRAM 是“披着 SRAM 外衣的 DRAM”很多人一开始会觉得 PSRAM 带个 SRAM 字样就不需要刷新了。这是最常见的误区。PSRAM 翻译过来是伪静态随机存储器Pseudo SRAM它内部的核心存储阵列其实就是 DRAM 单元同样需要刷新。区别在于PSRAM 在封装里集成了一个刷新控制器你通过 SRAM 接口去读它写它时控制器会悄悄地在后台帮你完成刷新。对于外部使用者来说它表现得像 SRAM 一样不需要考虑 tREFI、tRFC 这些东西只要按普通的 SRAM 时序读写就行。所以更准确的说法是PSRAM 不需要“你”去刷新但存储单元仍然在拼命漏电。这个特性让 PSRAM 很适合嵌入式应用比如 MCU 外扩内存、显示缓冲、音频缓冲这类场景。它的接口简单引脚和时序跟 SRAM 完全兼容省掉了 DDR 控制器那一套复杂逻辑。代价就是它的容量通常做不大读写性能也比不了真正的 DDR而且背后隐藏的刷新操作在某些突发场景下会增加延迟比如正在读一个地址正好赶上内部刷新等待时间可能就明显变长。这一点我在后面第 5 节会专门对比。2. Refresh 到底执行了什么操作2.1 不是“全盘重写”而是“一行一行充电”刚开始学 DRAM 时我误以为 refresh 是像磁盘整理一样把整块内存从头到尾读一遍再写回去。实际上 DRAM 的刷新是“按行”进行的。DRAM 的存储阵列是二维矩阵由行Row和列Column组成。刷新一个行就是把这一行的所有存储单元的电荷读取出来通过灵敏放大器Sense Amplifier放大再写回去。这个动作本质上就是一次“读”加一次“写回”。之所以要借助灵敏放大器是因为电容里存的电荷实在太微弱了单个电容的电荷量根本不够驱动数据线形成有效的电平。灵敏放大器的作用像一个小喇叭先把微弱的信号放大成完整的高/低电平同时这个放大的过程也就完成了“重写”。所以 DRAM 的读操作天生是破坏性的读一次就必须把数据写回去。内部刷新其实就是执行了几千次类似的行激活Activate 预充电Precharge操作。2.2 刷新命令和正常读写的区别在 DDR 协议里刷新是由控制器发出的 REF 命令完成的。一次 REF 命令会刷新一行或者按照芯片内部规定的刷新粒度刷新若干行。具体刷新哪一行不是控制器指定的而是 DRAM 芯片内部有一个刷新计数器每次 REF 命令到来就递增一次。控制器只管按时发出足够多的 REF 命令剩下的地址选择完全交给芯片内部逻辑。这个“内部计数器”设计非常巧妙它让刷新操作不需要外部提供地址大大简化了控制器的状态机。也正因为如此控制器必须知道芯片一共需要刷新多少行才能算出多长时间发一次 REF 命令。比如一颗 1Gbit 的 DDR3 芯片典型参数是 8192 行每 64ms 必须把 8192 行都刷一遍那么平均每 7.8125us 就要发一次 REF。这个时间间隔在手册里叫 tREFIRefresh Interval。单次 REF 命令持续的时间叫 tRFCRefresh Cycle Time也就是完成一次刷新动作需要多长总线时间。2.3 预充电和行有效的关系如果你去看 DRAM 的操作流程会发现 refresh 和普通的激活Active操作很像。激活一行时先把行地址发送出去然后拉低片选和行地址选通RAS这一行的数据被读取到灵敏放大器里。如果不进行列访问接下来直接执行预充电Precharge关闭当前行为下一次行访问做准备。Refresh 就是“激活一行 立即预充电”只是不加列地址也不需要数据总线参与。这个过程在内部就把数据重新放大写回了。理解这一点特别重要因为它解释了为什么刷新会有性能损耗。刷新期间DRAM 芯片不能响应正常的读写请求至少在那段时间内内存系统要么等待 tRFC 结束要么分发到其他 bank 去操作。如果你做过系统级性能调优就会发现当内存访问频繁触发刷新时延迟会呈现一种周期性跳动这正是那一行行 refresh 在捣乱。3. 刷新时序参数解析手动算一遍就懂3.1 关键参数tREFI、tRFC、tREFW刷新手册参数常见的有三个tREFI两次刷新命令之间的平均时间间隔DDR 兼容颗粒通常在 7.8us 左右64ms / 8192 行高温工况下可能是 3.9us。tRFC一次完整刷新命令需要的持续时间DDR3 一般是 90ns 到 110nsDDR4 里常见的 350nsDDR5 更是随着容量增大变得更长可到几百纳秒甚至更高。tREFW整个刷新窗口时间也就是 64ms 或者 32ms这是所有行都刷新一遍的总时长限制。如果你看过内存颗粒的 datasheet还会看到厂家根据环境温度给出不同的刷新窗口。多数消费级 DDR4 在 0°C 到 85°C 用 64ms超过 85°C 到 95°C 之间要求 32ms。这个必须从芯片手册里确认不是通用不变的。3.2 刷新开销的计算示例拿一颗常见的 8Gbit DDR4 来算。芯片内部有 8192 行刷新窗口 64ms所以 tREFI 是 64ms / 8192 7.8125us。假设 tRFC 是 350ns那么平均有多少时间在刷新就是 350ns / 7812.5ns约等于 4.48%。也就是说纯理论情况下内存控制器至少有 4.48% 的带宽是拿不出来做正常读写的。这个数看着不大但在高并发内存访问时会让实际的延迟抖动变得很明显。再考虑一个场景如果温度高刷新窗口变成 32ms那么 tREFI 就变成 3.90625us刷新开销翻倍接近 9%。所以很多人会抱怨内存超频或者高温环境下系统总感觉卡顿刷新开销翻倍也是其中一个因素。3.3 多粒度刷新模式All-bank vs Per-bankDDR4 开始引入多种刷新模式除了传统的 All-bank Refresh一次刷所有 bank 的一行还支持 Per-bank Refresh。Per-bank 的好处是刷新某个 bank 时其他 bank 还能继续读写降低了对正常访问的阻塞。实现起来稍微复杂控制器需要去管理每个 bank 的刷新状态避免对处于刷新中的 bank 发读写命令。对 DDR5 来说刷新粒度做得更细出现了 Same-bank refresh 之类的模式本质上都是想减少刷新带来的访问阻塞。写控制器时如果要支持这些模式状态机就比 DDR3 复杂不少。很多人觉得 DDR5 难调难点之一其实就是刷新调度。调不好性能跑不满或者某一行刷新超时造成数据丢失。4. 刷新模式与控制器策略4.1 Auto Refresh 和 Self RefreshDDR SDRAM 里有两种大的刷新模式。正常使用时控制器根据 tREFI 周期性地发出 REF 命令这种叫 Auto Refresh。芯片每次收到 REF内部计数器自动递增一行。另外一种叫 Self Refresh使用场景主要是休眠、待机、低功耗状态。控制器发给芯片一条 SELF REFRESH 命令芯片就停止对外通信自己定时刷新所有行直到控制器发退出命令。Self Refresh 的刷新间隔可以比 Auto Refresh 长很多因为芯片在低功耗模式下可以降低内部时钟频率再用一个温度传感器来自适应调节刷新频率。温度低的时候间隔拉长进一步省电。这一点对手机、笔电这类设备至关重要因为内存常驻电源保持数据必须持续耗电如果不能用 Self Refresh 把刷新功耗压下来待机功耗会很难看。PC 上的 BIOS 里有时能设置 DRAM 的 self-refresh 模式其实就是在控制这个。4.2 控制器怎么调度刷新设计内存控制器时刷新调度是个躲不开的话题。最简单粗暴的方式就是搞一个计数器每过 tREFI 时间就强制插入一次 REF插进去的同时把所有 bank 都暂停。这种实现简单但性能损失明显。稍微好一点的做法是利用 bank 空闲时间插入刷新哪个 bank 不在使用中就刷哪个 bank。还有一种做法是“推后刷新”允许刷新时机稍微延后把多个延迟的刷新合并处理减少中断次数但代价是避免超过 tREFW 的总时间窗口。我当年调试一个视频输出系统时就遇到了刷新毛刺问题。视频 DMA 每帧要从 DDR 读大量数据如果控制器在某个固定时间点插入整段刷新画面就会出现周期性的卡顿。最后是通过把刷新散开到不同 slot并且用乒乓缓冲把可能出现的等待藏起来解决的。现在主流的 SoC 控制器里都会有刷新遮蔽Refresh Masking或预先刷新Refresh Ahead的机制本质都是让刷新发生时数据通路有足够缓冲兜底。4.3 刷新与温度传感器的联动有些 DRAM 芯片内部自带温度传感器TS比如移动端 LPDDR 系列很常见。控制器可以读取这个温度动态调整 tREFI从而在性能和功耗之间找平衡。温度高就刷勤快一点温度低就刷慢一点能省不少电。注意这里指的是控制器的策略不是说芯片会自动更改对外宣称的刷新参数。如果控制器不支持读取温度传感器就只能按最差工况来固定刷新比如统一用 32ms 窗口安全性没问题但功耗会白白多出不少。在嵌入式领域如果你用的裸 DRAM 或者 PSRAM 不支持温度反馈我建议按产品最高工作温度来配置刷新间隔。尤其做过车规项目的朋友应该知道工作温度到 105°C 时刷新窗口可能得缩到 15ms 甚至更短这些都是血泪经验。5. DRAM、DDR、PSRAM 的区别以及热词里容易踩的坑5.1 DRAM 和 DDR 不是一回事很多入门朋友会把 DRAM 和 DDR 混着说。DRAM 是动态随机存储器的统称包括传统的 SDRAM也包括后来的 DDR1、DDR2、DDR3、DDR4、DDR5以及移动端的 LPDDR 系列。DDR 是 Double Data Rate 的缩写重点在“传输速率翻倍”即时钟上升沿和下降沿都能传数据。所以严格来说DDR 是 DRAM 的一种同步接口标准不是存储单元结构的改变。从存储原理上讲DDR 内部仍然是电容阵列加灵敏放大器仍然要周期性地刷新。DDR 只是把对外接口从单沿变成了双沿同时通过预取Prefetch技术提升了带宽。所以千万别以为买了 DDR5 就不用刷新了它只是刷新的控制方式更先进、时序参数更短但需要刷新的本质没变。5.2 PSRAM 和普通 DRAM 怎么选选 PSRAM 还是选外接 DDR 或者传统异步 SRAM要看场景。如果你的系统 MCU 没有 DDR 控制器又嫌外接 SRAM 容量太小、价格太贵PSRAM 是很好的折中。它不需要复杂的初始化Power On 之后直接读写刷新在内部完成软件开发成本低。但如果你的产品要做高清视频、高性能计算这类高带宽场景PSRAM 的带宽和延迟都会成为瓶颈。我试过在一颗低主频 MCU 外扩 PSRAM 做 320×240 的帧缓冲直接读写还行但一旦做图形叠加和局部刷新延迟波动就很明显因为它内部刷新会打断访问。这时候还不如用带 DDR 控制器的 SoC 接 LPDDR4虽然软件要管初始化、训练、刷新调度但性能上限高一大截。5.3 关于“refresh token”的那个热词我注意到相关搜索里出现了 failed to refresh token: 400 bad request: invalid refresh_token...这个其实是 Web 开发里 OAuth 认证接口返回的 JSON 错误跟芯片刷新是两个世界里的“refresh”。可能是有朋友在搜内存刷新资料时被推荐进了这个坑。这里提一句web 里的 refresh token 是客户端用来换取新访问令牌的凭证报 invalid refresh_token 通常代表服务端已经丢弃了该 token比如过期、被重置或者客户端传了空字符串。这个跟硬件 refresh 没关系别搞混。6. 温度、数据保持与可靠性被忽略的隐藏风险6.1 数据保持时间为什么这么玄DRAM 的数据保持时间不是每一个 bit 都一样的。不同单元的电容制造偏差、缺陷、漏电路径不同会导致某些单元的保持时间明显短于典型值。芯片出厂时会做筛选保证在规格书规定的时间内绝大多数单元的保持时间都达标。但工程上不可能做到 100%所以有些内存芯片在接近极端温度工作时或者老化之后会出现偶发的“电性软错误”。有点像区分低不良率的过程你没法一眼看出哪个电容会漏得快只能靠刷新频率来兜底。在做长期可靠性测试时我见过常温下一切正常跑到高温老化箱里就出现数据翻转的例子。排查到最后就是刷新间隔不够短。后来把电源时序、温度反馈、刷新间隔三项都重新按其规格校准问题才消失。这提醒我们把刷新参数看得太“理论”是危险的必须结合实际温度、供电电压和电流噪声来整体评估。6.2 行锤击与刷新频率的博弈现在只要提刷新就绕不开 Row Hammer。如果同一行被反复激活会导致临近行电容上的电荷加速流失最终造成数据翻转。这是一类靠“频繁访问”堆出来的安全隐患。为了缓解现在很多控制器和 DRAM 芯片本身都加入了 Target Row RefreshTRR机制也就是在普通刷新之外额外增加对受干扰行的刷新。对这一块的关注不能停留在“跑一个 Row Hammer 测试看看”。如果你做的是高安全等级的设备比如金融终端、车载系统就要在选型时确认芯片是否支持 TRR控制器是否能识别并追踪疑似受害行。刷新的本质从“防自然漏电”扩展到了“防人为扰动”这是近十年来刷新知识里最大的变化。6.3 ECC 不能替代刷新ECC 能纠正单比特错误能检测双比特错误但不能代替刷新。它解决的是数据读出来时已经错了怎么办而刷新做的是让数据尽量别错。如果你用 ECC 就放松对刷新参数的检查那在某些情况下比如高温、长刷新间隔加上 Row Hammer单比特错误率会高到 ECC 都应付不来。实际做法是先用 ECC 兜底同时老老实实把刷新窗口按最坏工况配置好。7. 实际调试中的几个问题与排查思路7.1 刷新参数配错会怎样最常见的问题是 tRFC 设置过小或者刷新间隔过长。前者会导致芯片还没完成上一次刷新就收到新命令可能直接命令违约后者会让某些行超过最大刷新窗口出现偶发性数据错误。这两个问题都非常阴险系统跑起来不一定立刻崩可能运行很久之后才冒出一次校验失败或者图像花屏。排查方式其实不复杂。先用测试软件对 DDR 做连续读写扫描同时把系统负载拉高观察是否有周期性错误。如果错误周期与 tREFI 存在某种倍数关系基本可以怀疑刷新参数配置有问题。再就是把温度拉起来做高温测试错误出现的概率会显著增高方便辅助定位。7.2 自刷新的低功耗坑嵌入式产品做低功耗时经常把 DRAM 切到 Self Refresh 模式。但这里有个容易出错的地方和设计 SRAM 完全不同。 SRAM 随时可以睡随时可以醒不用管数据丢不丢。DRAM 进入和退出 Self Refresh 都需要满足特定的时序要求退出时往往还要重新做一次片选、命令同步并且有些控制器会漏掉退出后的初始化序列。如果退出 Self Refresh 后立刻访问 DDR轻则读取到不确定数据重则总线挂死只能复位。我记得有次调试一块低功耗板卡发现设备休眠唤醒后偶尔卡死。最后定位到是唤醒流程里少了等待自刷新退出完成的延时导致片选和命令竞争。修复方式就是严格按照芯片手册的 tXSDLL、tXS 之类的参数加等待。这类细节用户手册通常写得特别隐晦只有出问题时你才会注意到。7.3 性能测试里如何观测刷新的影响如果你开发内核驱动或做性能分析想观察刷新对访问延迟的影响可以在驱动里不停读取某个固定地址的内存记录每次读的耗时。你会发现正常情况下延迟很稳定但每到一个刷新点延迟会猛地跳一下。这个跳动不是噪声而是刷新命令插进来了。如果控制器做了提前刷新或者遮蔽抖动幅度会小很多。更进一步你可以统计一个完整刷新窗口内延迟超过某个阈值的读请求次数。如果这个数字和行数、刷新粒度吻合说明抖动就是刷新引起的。这也是判断控制器刷新调度做得好不好的一个简单方法比单纯看总带宽更直观。8. 一个容易上手的实测方法如果你真想把刷新这件事学透我建议你找一块带 DDR3 或 DDR4 的开发板亲手改一改 tREFI 和 tRFC 参数观察系统行为。比如在 BIOS 里或者固件序列里把 tRFC 调高、调低然后跑 memtest86 之类工具。把 tRFC 调太小时测试通常会很快报错把 tREFI 调大时错误则比较难复现可能在高负载或者高温下才会出现。对这种“靠时间积累才出错”的故障初学者往往很摸不着头脑而亲手触发一次记忆就非常深刻。还有一个小技巧如果手边有逻辑分析仪可以抓取 CKE、CS、RAS、CAS 这些信号的组合观察刷新命令的波形。不过现代 DDR 频率越来越高普通逻辑分析仪可能跟不上那就只能从控制器寄存器里读刷新计数了。调实时操作系统或者嵌入式系统时给一个定时器预留一个调试变量每发一次刷新就递增配合实际时间可以非常直观地算出刷新频率是否和预期一致这个方法我至今还在用。刷新的核心就一句话电荷会漏必须补。看似基础到不行但把刷新搞透之后很多内存领域的高级话题比如延迟抖动、低功耗设计、Row Hammer 安全防护都有了一条清晰的逻辑主线。希望大家看完这篇基础小知识三能带着“刷新其实是在跟时间和温度赛跑”的思路去读芯片手册很多参数就不再是死数字了。我个人在这些年调过的最深刻的一个教训是无论手上的内存控制器多么智能最终还是要对每条刷新时序参数的物理含义有数否则出了问题你连排查方向都没有。
返回列表