Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

DDR 内存 SPD 读写 API

快速开始

主控板通过串口与上位机通信,使用 9 字节定长二进制帧协议,可读写 DDR3 / DDR4 / DDR5 内存 SPD,并支持写保护的设置与解除。

  • 串口参数:115200 8-N-1,无流控,上电后即可通信。
  • 每次交互:上位机发送 1 帧 9 字节请求,设备返回 ASCII 文本,所有响应以 \n 结尾。
  • 请求帧字段为二进制字节;响应为 ASCII 十六进制字符或 1 / 0。

通信参数

项目值
串口UART0
波特率115200
数据位8
校验位无
停止位1
流控无
SPD 总线I2C(GPIO18 / GPIO19)

API 格式(帧结构)

每帧固定 9 字节:

偏移字段取值说明
0HEAD10xAA帧头第 1 字节
1HEAD20x55帧头第 2 字节
2CMD0x01 ~ 0x07操作命令
3TYPE0x03 / 0x04 / 0x05内存类型
4ADDR_H0x00 ~ 0xFF地址高字节
5ADDR_L0x00 ~ 0xFF地址低字节
6DATA_H0x00 ~ 0xFF数据高字节
7DATA_L0x00 ~ 0xFF数据低字节
8CRC0x00 ~ 0xFFCRC8 校验值
  • 地址为 16 位:ADDR_H << 8 | ADDR_L。
  • CRC 的计算范围为第 2 ~ 7 字节(CMD、TYPE、ADDR_H、ADDR_L、DATA_H、DATA_L 共 6 字节),帧头与 CRC 自身不参与计算,详见 CRC-8 校验。
  • 设备以帧头 AA 55 作为同步标志,收到完整 9 字节后立即执行命令并返回响应。
  • 命令中未使用的字段统一填 0x00。

参数说明

内存类型 TYPE

TYPE内存类型0x05 整片读取长度
0x03DDR3256 字节
0x04DDR4512 字节
0x05DDR51024 字节

0x06 / 0x07(寄存器操作)仅支持 TYPE = 0x05(DDR5),其他类型不返回任何数据。

命令一览

CMD功能需填写的字段响应
0x01读取 SPD 单个字节TYPE、ADDR2 位大写十六进制 + \n
0x02写入 SPD 单个字节TYPE、ADDR、DATA_L1\n 成功 / 0\n 失败
0x03设置写保护TYPE、DATA_H:DATA_L1\n 回读一致 / 0\n 不一致
0x05整片读取 SPDTYPE整片十六进制数据 + \n
0x06读取 DDR5 全部寄存器TYPE = 0x05256 位十六进制 + \n
0x07写入 DDR5 单个寄存器TYPE = 0x05、ADDR、DATA_L1\n 成功 / 0\n 失败
其他未知命令-Unknown command\n

0x04 为保留值,未实现。0x01 一次只读 1 字节,批量读取请使用 0x05。

响应格式

响应内容含义
XX\n十六进制数据(大写,每字节 2 字符)
1\n操作成功(写类命令)
0\n操作失败(写类命令)
Invalid command format\n帧头不是 AA 55
CRC check failed\nCRC 校验不通过
Unknown command\n命令字不支持
无响应参数不满足命令要求(如 0x05 的 TYPE 非 3/4/5、0x06/0x07 的 TYPE 非 5)

命令详解

0x01 读取 SPD 单个字节

读取指定地址的 1 字节 SPD 数据,返回值为该字节的 2 位大写十六进制。

字段是否使用
TYPE、ADDR✅
DATA_H、DATA_L忽略(填 0x00)

示例(DDR5,地址 0x0000)

请求:AA 55 01 05 00 00 00 00 0D
响应:5A

示例中 5A 为示意数据,实际返回该地址的真实值(后跟 \n)。


0x02 写入 SPD 单个字节

向指定地址写入 1 字节,DATA_L 为写入值。

字段是否使用
TYPE、ADDR、DATA_L✅
DATA_H忽略(填 0x00)

示例(DDR5,地址 0x0000 写入 0x12)

请求:AA 55 02 05 00 00 00 12 AB
响应:1

写入失败(目标区域写保护、SPD 无应答等)返回 0。


0x03 设置写保护

DATA_H:DATA_L 组成 16 位写保护掩码;写入后设备会回读当前保护状态,回读值与下发掩码完全一致才返回 1,否则返回 0。

字段是否使用
TYPE、DATA_H、DATA_L✅
ADDR忽略(填 0x00)

位定义:掩码 BIT0 → Block 0、BIT1 → Block 1 …… BIT15 → Block 15,1 = 开启写保护,0 = 解除写保护。

内存类型可用 Block典型掩码
DDR5Block 0 ~ Block 15FFFF 全部保护 / 0000 全部解除
DDR4Block 0 ~ Block 3000F Block 0~3 保护 / 0000 全部解除
DDR3仅支持解除0000

由于判定条件是「下发掩码 == 回读状态」,掩码必须一次性给出全部 Block 的目标状态;只想修改某一个 Block 时,也要把其它位按当前状态一起下发,否则会返回 0(此时保护可能已生效,请重新读取状态后再次下发)。

示例

场景请求帧响应
DDR5 全部写保护AA 55 03 05 00 00 FF FF 471
DDR4 Block 0~3 写保护AA 55 03 04 00 00 00 0F F11
DDR3 解除写保护AA 55 03 03 00 00 00 00 561

0x05 整片读取 SPD

按 TYPE 连续读取整片 SPD,每字节输出 2 位大写十六进制,末尾追加 \n。ADDR、DATA_H、DATA_L 均忽略。

TYPE读取长度响应长度(含 \n)
0x03256 字节513
0x04512 字节1025
0x051024 字节2049
其他-无响应

示例(DDR5 整片读取)

请求:AA 55 05 05 00 00 00 00 D1
响应:4A0C...(2048 个十六进制字符,末尾 \n)

0x05 固定从地址 0 开始整片读取,不支持指定起始地址与长度;按地址读取请使用 0x01。


0x06 读取 DDR5 寄存器

仅 TYPE = 0x05 有效,固定读取 128 个寄存器字节(索引 0 ~ 127),每字节 2 位大写十六进制,共 256 字符,末尾追加 \n。ADDR、DATA_H、DATA_L 均忽略。

示例

请求:AA 55 06 05 00 00 00 00 88
响应:0000...(256 个十六进制字符,末尾 \n)

其他 TYPE 无任何响应。


0x07 写入 DDR5 寄存器

仅 TYPE = 0x05 有效,ADDR 为寄存器索引(0 ~ 127),DATA_L 为写入值。

字段是否使用
TYPE(必须为 5)、ADDR、DATA_L✅
DATA_H忽略(填 0x00)

示例(写寄存器 0 = 0x10)

请求:AA 55 07 05 00 00 00 10 A3
响应:1

成功返回 1,失败返回 0;TYPE 非 5 时无任何响应。


CRC-8 校验

算法参数

项目值
宽度8 位
多项式0x07
初值0xFF
输入反转是
输出反转是
结果异或0x00
标准校验值CRC("123456789") = 0xD0

该算法即常见的 CRC-8/ROHC(Robust Header Compression,见 RFC 3095 附录 B)。

计算范围

帧第 2 ~ 7 字节,共 6 字节:CMD、TYPE、ADDR_H、ADDR_L、DATA_H、DATA_L。帧头 AA 55 与 CRC 字节本身不参与计算。

计算步骤

以 0xFF 为初始值,按顺序对上述 6 字节逐字节处理,每个字节执行:

  1. 校验值 = 校验值 XOR 当前字节;
  2. 重复 8 次:若校验值最低位为 1,则右移 1 位后 XOR 0xE0;否则仅右移 1 位(结果保持 8 位)。

6 字节处理完毕后的值即为该帧的 CRC 字节(十六进制大写写入帧第 9 字节)。

校验失败

CRC 不匹配时设备返回 CRC check failed,且不执行该命令。

常用帧速查表

以下请求帧(HEX)中最后一字节为 CRC:

功能请求帧
DDR5 读 0x0000AA 55 01 05 00 00 00 00 0D
DDR4 读 0x0010AA 55 01 04 00 10 00 00 6E
DDR5 写 0x0000 = 0x12AA 55 02 05 00 00 00 12 AB
DDR5 全部写保护AA 55 03 05 00 00 FF FF 47
DDR4 Block0~3 写保护AA 55 03 04 00 00 00 0F F1
DDR3 解除写保护AA 55 03 03 00 00 00 00 56
DDR3 整片读取AA 55 05 03 00 00 00 00 E4
DDR4 整片读取AA 55 05 04 00 00 00 00 38
DDR5 整片读取AA 55 05 05 00 00 00 00 D1
DDR5 读全部寄存器AA 55 06 05 00 00 00 00 88
DDR5 写寄存器 0 = 0x10AA 55 07 05 00 00 00 10 A3

收发流程

  1. 组装请求帧:按 帧结构 填写 CMD、TYPE、ADDR、DATA,并对第 2 ~ 7 字节计算 CRC 填入第 9 字节。 例如读取 DDR5 地址 0x0000:AA 55 01 05 00 00 00 00 0D。

  2. 发送:一次性将 9 字节通过串口发出。

  3. 接收:按下表按固定长度读取响应(\n 计入长度):

    命令响应长度
    0x013 字节(2 位十六进制 + \n)
    0x02 / 0x03 / 0x072 字节(1/0 + \n)
    0x06257 字节(256 位十六进制 + \n)
    0x05(DDR3)513 字节
    0x05(DDR4)1025 字节
    0x05(DDR5)2049 字节
  4. 解析:十六进制响应按每 2 个字符还原 1 字节;1 / 0 分别表示写类命令成功 / 失败。


使用注意事项

  • 设备按帧逐条处理命令,建议收到完整响应后再发送下一帧。
  • 0x05 / 0x06 响应较长,请按固定长度读取,不要依赖行缓冲。
  • 整片读取 DDR5(1024 字节)在 115200 波特率下传输约需 0.2 s,串口读超时建议不小于 1 s。
  • 参数不满足要求(如 0x05 的 TYPE 非 3/4/5、0x06/0x07 的 TYPE 非 5)时设备不返回任何数据,上位机需自行做超时处理。
  • 帧头 AA 55 是同步标志;帧同步完成后,后续字节按位置依次填充,凑满 9 字节即执行,因此帧内不要插入分隔符或额外字节。
  • 本协议 CRC 固定为 CRC-8/ROHC(多项式 0x07、初值 0xFF,输入 / 输出均反转);使用其它 CRC-8 变体(如 CRC-8/MAXIM、CRC-8 标准型)计算出的请求帧会被判为 CRC check failed。
  • 写类命令返回 0 只代表本次操作失败,不建议在上位机侧做自动重发。