B02 —— 内存条的身份证:SPD 芯片里到底存了什么

金句:没有 SPD 的内存,就像一个没有身份的人——系统不知道它是谁。


SPD 芯片的基本信息

每根 DDR 内存条都有一个 SPD(Serial Presence Detect)芯片,是一个 256 字节(或 DDR5 512 字节)的 EEPROM。

Bash
SPD 芯片规格:

容量:256 Bytes(DDR4)、512 Bytes(DDR5)
封装:8-pin SOIC,3mm × 5mm
位置:内存条金手指靠近右侧(缺口旁边)
通信:I2C 总线,地址 0x50/0x51/0x52(Channel 0/1/ECC)

I2C 总线特性:
  - 时钟频率:400kHz(Fast Mode)
  - 数据格式:MSB first
  - 每个字节后需要 ACK

SPD 字节分布(DDR4 256 字节详解)

Bash
DDR4 SPD 结构(256 Bytes):

Byte 0~1:   厂商标识(0x80=Samsung, 0xAD=SK Hynix, 0x98=Micron, 0x9E=Crucial)
Byte 2:     厂商特定(具体型号编码)
Byte 3:     颗粒类型(x4/x8/x16,0x0C=8Gb)
Byte 4:     颗粒组织(0x0A=8Gb x8 = 1GB per颗粒)
Byte 5~6:   密度(0x10=8GB, 0x20=16GB, 0x40=32GB)
Byte 7:     Ranks(1=单 rank, 2=双 rank, 4=四 rank)
Byte 8:     排数(1=单面, 2=双面)
Byte 9:     电压(0x06=1.2V,D9=1.35V DDR4L)
Byte 12~13: JEDEC 标准频率(0x0C=1600, 0x14=2133, 0x18=2666, 0x1E=3200)
Byte 16~17: JEDEC CL-tRCD-tRP-tRAS
Byte 20~21: XMP 频率(如果有 XMP)
Byte 22~23: XMP 时序(CL-tRCD-tRP-tRAS)
Byte 24~25: XMP 电压
Byte 30:    内存条类型(0x02=DIMM, 0x01=SODIMM)
Byte 32~33: 模块高度(mm)
Byte 118~119:序列号(厂商流水号)
Byte 122~123:Manufacturing Date(年/周)
Byte 127:    Checksum(所有前 127 字节的 CRC/校验和)

从 SPD 数据重建内存信息

Bash
Linux 读取 SPD 示例(decode-dimms):

$ sudo decode-dimms

Handle 0x0027, DMI type 5, 24 bytes
Memory Array Handle: 0x0029
Error Information Handle: Not Provided
Total Width: 64 bits
Data Width: 64 bits
Size: 8192 MB
Form Factor: DIMM
Set: None
Locator: ChannelA-DIMM0
Bank Locator: BANK 0
Type: DDR4
Type Detail: Synchronous
Speed: 2666 MT/s
Manufacturer: Samsung
Part Number: M378A1K43BB2-CRC
Rank: 2
Configured Clock Speed: 2666 MT/s

SPD 时序参数(DDR4-2666 CL18):
  CL=18, tRCD=18, tRP=18, tRAS=36
  → CL(ns) = 18/2666×2000 = 13.5ns

XMP 和 EXPO 的 SPD 扩展

Bash
XMP/EXPO 实际上存在 SPD 的扩展区域(Byte 176~255):

Byte 176~191:XMP Header
  - XMP 签名("XMP""EXPO")
  - 版本号(XMP 2.0 / XMP 3.0)
  - Profile 数量

Byte 192~255:XMP/EXPO Profile 数据
  - Profile 1:DDR4-3600 CL18 1.35V
  - Profile 2:DDR4-3200 CL16 1.35V(如果两个都支持)

BIOS 读取 SPD 时:
  1. 先读取 Byte 12~13 的 JEDEC 频率(安全值)
  2. 如果有 XMP,尝试读取 XMP Profile
  3. 如果 CPU/主板支持 XMP 频率,使用 XMP 配置
  4. 如果 XMP 超频失败(不稳定),回退到 JEDEC

SPD 在开机时的作用

Bash
BIOS 读取 SPD 的时机(POST 阶段):

1. 内存初始化第一步:读取 SPD
   BIOS 通过 I2C 总线读取每个 DIMM 的 SPD

2. 解析 SPD:获取容量和速度
   - 读 Byte 5~6 得到容量(如 16GB)
   - 读 Byte 12~13 得到 JEDEC 频率(如 2666 MT/s)
   - 读 Byte 20~21 得到 XMP 频率(如 3600 MT/s)

3. 选择频率和时序
   - 如果启用 XMP,使用 XMP 配置(高频率+紧时序)
   - 如果禁用 XMP,使用 JEDEC 配置

4. 内存 Training
   - 基于 SPD 的时序参数,进行 Write Leveling 等校准
   - 如果 SPD 数据损坏(checksum 错误),BIOS 可能忽略该 DIMM

5. 写入 ACPI 表
   - 操作系统通过 ACPI SRAT(Static Resource Affinity Table)获取内存节点信息

手动读取 SPD 的方法

Bash
Linux 下读取 SPD:

1. 安装 i2c-tools:
   $ sudo apt install i2c-tools

2. 加载 EEPROM 模块:
   $ sudo modprobe eeprom

3. 探测 I2C 总线:
   $ sudo i2cdetect -l
   i2c-1   808622C1                 i2c             <- 可能是内存 I2C 总线

4. 读取 SPD(假设在 0x50):
   $ sudo i2cdump -y 1 0x50
   0000: 80 8c 0c 0a 10 00 02 01 06 00 00 00 00 00 00 00
   0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   ...

5. 直接用 decode-dimms(更易读):
   $ sudo decode-dimms

SPD 数据损坏和 ECC

Bash
SPD 数据损坏的症状:

1. Checksum 错误(Byte 127):
   → BIOS 忽略该 DIMM,不使用
   → 系统只能识别其他 DIMM

2. SPD 数据全为 0xFF:
   → EEPROM 损坏
   → BIOS 检测到并报错

SPD 损坏的原因:
  - 静电放电(ESD)
  - 电压冲击(开关机时的浪涌)
  - 长时间高温(加速 EEPROM 老化)

ECC 内存的 SPD:
  - ECC DIMM 有两个 SPD 芯片(0x50 和 0x52)
  - 0x52 是给 ECC 控制器用的(单独校验)
  - 如果 0x52 损坏,只有 ECC 功能失效,内存本身可能仍可用

总结

  • SPD 芯片:256B(DDR4)或 512B(DDR5)EEPROM,存储内存配置信息
  • 关键字段:厂商/容量/频率/时序/电压/XMP profile/序列号/校验和
  • XMP/EXPO:存在 SPD 扩展区域(Byte 176~255),多个 Profile 可选
  • 开机流程:BIOS 读 SPD → 解析配置 → Training → 写入 ACPI 表
  • Checksum:Byte 127 存储校验和,损坏会导致 BIOS 忽略该 DIMM

下篇预告(B03):计算机是怎么从按下电源键开始,一步一步把控制权交给操作系统的?Bootloader 的完整启动流程——从 BIOS/UEFI 到 GRUB 到 Kernel。


关注公众号「AI不着急」,回复”资料”获取内存学习路线图。

最后修改: 2024年12月14日

作者

评论

发表评论

您的邮箱地址不会被公开。