双线接口:地址、页面、存储组与时序
每个可插拔模块都通过同样的两根线(一根串行时钟线,一根串行数据线)来管理,使用规范中称为双线接口(TWI)的 I²C 协议。SFP、QSFP、XFP 和 CMIS 模块的区别在于地址空间在其之上是如何组织的:独立器件、分页存储器,或是成组的页(存储体)。本文是编程器、主机和 CodingBox 都依赖的协议层视角。
物理层
- 两根开漏线路,SCL 和 SDA,由主机侧上拉;3.3 V 逻辑电平。
- 模块始终是从设备;主机(或编程器)是主设备,负责产生时钟。
- 模块可能会拉伸时钟(将 SCL 拉低),以便微控制器取数据,规范允许最长 500 µs。
- 在位检测和选择是独立的引脚,而不是总线事务:MOD_ABS(SFP)、ModPrsL 和 ModSelL(QSFP 类和 CMIS)。ModSelL 让多个模块可以共享一条总线;SFP 没有选择引脚,因此主机会为每个笼子配备独立总线或使用多路复用器。
按规范划分的地址空间
| 系列 | 器件地址(8 位写入/7 位) | 组织方式 | 页选择 |
|---|---|---|---|
| SFP、SFP+、SFP28(SFF-8472) | A0h/50h 身份信息,A2h/51h 诊断 | A0h:256 字节平坦地址;A2h:128 字节平坦地址 + 可选分页上半部分 | A2h 字节 127,若 A0h 字节 64 位 4 置位 |
| XFP(INF-8077i) | A0h | 128 字节平坦地址 + 分页上层“表格” | 字节 127 |
| QSFP+、QSFP28(SFF-8636) | A0h | 128 字节平坦地址 + 分页上层 128 字节 | 字节 127 |
| QSFP-DD、OSFP、SFP-DD…(CMIS) | A0h | 128 字节平坦地址 + 上层 128 字节的存储体 × 页 | 字节 126 为存储体,字节 127 为页 |
因此 SFP 的基本功能需要两个器件地址,且不涉及分页;XFP 之后的所有形态都使用一个地址并配合分页。部分老旧 SFP 会置位 A0h 字节 92 位 2(“需要地址切换”),需要先执行厂商定义的序列,A2h 才会响应。
事务
| 操作 | 序列 | 说明 |
|---|---|---|
| 随机读取 | START · 器件地址+W · 字节偏移 · START · 器件地址+R · 数据…… · STOP | 日常读取方式;偏移量自动递增 |
| 顺序读取 | 第一个字节之后继续提供时钟 | 在当前器件/页视图内从 255 → 0 回绕 |
| 当前地址读取 | START · 器件地址+R · 数据 | 从上次的偏移量继续;如果有其他主设备介入则不可靠 |
| 字节写入 | START · 地址+W · 偏移 · 数据 · STOP | 之后等待 t_WR |
| 页写入 | START · 地址+W · 偏移 · 数据 × n · STOP | 受限于存储器件本身(通常 4–16 字节),且不得跨越其内部页边界 |
| 应答轮询 | 反复发出 START + 地址+W,直到模块应答(ACK) | 判断写入周期是否完成的最快方法 |
读取上层页始终需要两次事务:先写入页选择字节(127,CMIS 存储体还需 126),再读取 128–255。该选择会一直保持,直到被更改,因此过时的页选择是导致读到 “内容错误”的典型原因。
速率
| 规范 | 时钟 |
|---|---|
| SFF-8472(SFP) | 基准 100 kHz;部分模块可容忍 400 kHz |
| INF-8077i(XFP) | 100 kHz |
| SFF-8636 rev 2.x(QSFP) | 最高 400 kHz |
| CMIS/QSFP-DD/OSFP 硬件规范 | 最高 400 kHz |
更低的速率总是允许的。对于写入,大多数编程器会把时钟降到远低于标称值,降到几千赫兹的范围,因为 EEPROM 写入周期以及由微控制器中转的模块,对时序的敏感程度远高于读取。
需要关注的时序
| 参数 | 典型限值 | 含义 |
|---|---|---|
| t_init(SFP) | 300 ms | 从上电/TX_DISABLE 撤销开始,到模块完全可工作且总线开始响应为止 |
| t_init(QSFP) | 2 s | 到初始化完成、Data_Not_Ready 清除为止 |
| MgmtInit(CMIS) | 按硬件规范 ≤ 2 s | 到模块离开 MgmtInit 状态、身份信息有效为止 |
| t_WR | 40 ms | 单字节或顺序写入的最长写入周期;轮询 ACK 或直接等待 |
| t_clock_hold | 500 µs | 模块允许的最长时钟拉伸时间 |
| ton_IntL | 200 ms | 从标志事件发生到 IntL 置位为止 |
| 数据就绪 | 字节 110 位 0(SFP),字节 2 位 0(QSFP) | 该位置位期间不要相信监测值 |
常见问题及解决方法
| 现象 | 协议原因 | 解决方法 |
|---|---|---|
| 全部为 FFh | 无应答(ACK):器件地址错误、页未实现、模块不在位 | 检查 A0h 与 A2h、页选择位、插接是否到位 |
| 内容错误 | 页/存储体选择过时 | 每次访问上层页前都写入 127(以及 126) |
| 字节损坏 | 时钟过快、线缆过长、与主机轮询 DDM 产生争用 | 降低速率、缩短线缆、在工作台而非在运行中的交换机上读取 |
| 写入“成功”,但回读为旧值 | 写入过快、忽略 t_WR、跨越了页写入边界 | 采用单字节或小块写入并等待;使用 ACK 轮询 |
| 总线挂起,SCL 或 SDA 被拉低卡死 | 事务被中断 | 输出 9 个 SCL 脉冲,然后发出 STOP;对模块重新上电 |
| 在交换机中正常,在编程器上无响应 | 模块需要释放 LPMode 或某个选择引脚 | 遵守 ModSelL/LPMode 要求;预留 t_init 时间 |
这些问题在工作台一侧的诊断方法汇总于 EEPROM 读写错误;建立在总线之上的保护机制(密码、硬件写保护、保存命令)见 写保护类型。
在运行中的系统里读取
主机每隔几秒轮询一次 DDM 并对标志做出反应;同一总线上的第二个主设备(编程器夹具、带内工具)会造成冲突、错误地址的写入,最坏情况下还会因为页写入落在错误偏移量上而使模块变砖。如果必须在原位读取也可以;但写入请在工作台上进行。
在 CodingBox 中
CodingBox 会按封装形式自动处理地址模型(SFP 用 A0h/A2h,QSFP 和 XFP 用分页, CMIS 用存储体加页),允许你按编程器配置文件设置总线速率和写入时序,并通过回读来验证每次写入(编程模块)。