CDB (Command Data Block,命令数据块)是一种在主机(Host)和光模块(Module)之间进行可选的、基于消息的命令-回复式通信机制。
其核心目标是提供一种比传统寄存器读写更强大、更灵活的交互方式,用于执行复杂的操作,如固件管理、性能监控、安全功能等。
1. CDB 是什么?
CDB 是 CMIS(Common Management Interface Specification)标准中定义的一个可选功能。它允许主机向模块发送结构化的"命令消息"(Command Message),模块处理该命令后,再返回一个"回复消息"(Reply Message)。
- 物理载体:CDB 消息通过 I²C 接口,在特定的内存映射页面(Pages)上进行读写操作来实现。
- 主要页面 :
- Page 9Fh :CDB 消息主页面 。包含命令/回复的头部 (Header)和一个较小的本地有效载荷(Local Payload, LPL,120字节)。
- Pages A0h-AFh :CDB 扩展有效载荷页面(Extended Payload, EPL)。当命令或回复的数据量超过 LPL 的容量时,可以使用这最多16个页面(共2048字节)来存储额外的数据。
- 实例化 :一个模块可以支持多个独立的 CDB 实例(通过 Bank 地址区分),允许多个命令通道并行工作(如果模块支持后台处理模式)。

2. CDB 有哪些主要功能?
CDB 功能被组织成不同的命令组 (Command Groups),每个命令由唯一的 CMD ID (16位)标识。主要功能包括:

| CMD ID 范围 | 功能组 | 描述 |
|---|---|---|
| 0000h - 003Fh | 模块命令 (Module Commands) | 基础操作,如 Query Status(查询状态)、Enter Password(输入密码)、Change Password(修改密码)、Abort Processing(中止当前操作)。 |
| 0040h - 005Fh | 能力查询 (Capabilities Inquiry) | 关键功能 。用于查询模块支持哪些 CDB 命令。例如 Module Features(查询模块级命令支持情况)、Firmware Management Features(查询固件管理能力)、Security Features(查询安全功能)等。 |
| 0100h - 011Fh | 固件管理 (Firmware Management) | 完整的固件升级/回读流程,包括 Start Firmware Download(开始下载)、Write Firmware Block(写入固件块)、Complete Firmware Download(完成下载)、Run Firmware Image(运行固件)、Commit Firmware Image(提交固件)等。 |
| 0200h - 027Fh | 性能监控 (Performance Monitoring) | 查询和配置模块的性能监控参数。 |
| 0280h - 02FFh | 数据记录 (Data Recording) | 访问非易失性数据记录。 |
| 0380h - 03FFh | 诊断与调试 (Diagnostics and Debug) | 高级诊断和调试命令。 |
| 0400h - 04FFh | 安全特性 (Security Features) | 如获取设备证书、生成数字签名等安全相关操作。 |
| 4000h - 40FFh | 多功能控制集 (Versatile Control Set) | 由 CMIS-VCS 补充标准定义的、可能与应用相关的自定义控制参数。 |
| 8000h - FFFFh | 自定义 (Custom) | 供应商自定义命令。 |
3. CDB 的具体实现过程
一次完整的 CDB 交互遵循严格的命令-回复协议,主要包括以下步骤:
A. 主机准备并发送命令 (Host Sends Command)
- 选择 CDB 实例: 主机确定要使用的 CDB 实例(Bank)。
- 写入有效载荷 (Payload) 主机将命令所需的参数(如果有)写入 Page 9Fh 的 LPL 区域(字节 136-255)和/或 Pages A0h-AFh 的 EPL 区域。
- 填充命令头 (Command Header) 主机在 Page 9Fh 的头部区域(字节 128-133)填入以下信息:
EPLLength(130-131):EPL 中使用的字节数(0-2048)。LPLLength(132):LPL 中使用的字节数(0-120)。CdbChkCode(133):校验码 。它是对从字节 128 到(136 + LPLLength - 1)(不包括 133-135 字节)所有字节的算术和取反计算得出的,用于保证命令消息的完整性。
- 触发命令执行 (Trigger Execution) 主机写入 **
CMDID(128-129),这是最关键的一步。写入CMDID的动作会"发送"消息并触发模块开始处理命令。- 触发方式有两种,由模块在
01h:165.7位广告:- 方式1 (
01h:165.7=0b):推荐分两步写。先写好所有参数和长度,最后单独写CMDID。 - 方式2 (
01h:165.7=1b):可以在一次多字节写操作中,一次性写入从 128 开始的所有命令数据(包括CMDID),在 I2C STOP 条件后触发。
- 方式1 (
- 触发方式有两种,由模块在
B. 模块处理命令 (Module Processes Command)
- 状态更新 :模块在处理命令期间,会通过状态寄存器(
CdbStatus1/2at00h:37/38)报告进度(如"忙于捕获命令"、"忙于执行命令")。 - 后台/前台模式:如果模块支持后台处理,它可以在处理 CDB 命令的同时响应其他 MCI (Module Control Interface 模块控制接口)请求。
C. 模块返回回复 (Module Returns Reply)
- 填充回复头 (Reply Header) 命令处理完成后,模块在 Page 9Fh 的回复头区域(字节 134-135)填入:
- RPLLength(R EPLY P ayl oad Length ) (134):指示回复数据的长度和位置(LPL 或 EPL)。
- RPLChkCode (135):回复校验码 。根据 RPLLength 指示的数据位置(LPL 或 EPL)计算出的校验和取反值。
- 写入回复数据 (Reply Data) 模块将回复的具体内容写入 LPL 和/或 EPL 区域,可能会覆盖之前主机写入的命令数据。
- 设置完成标志 :模块设置相应的 CdbCmdCompleteFlag(00h:8.6 或 8.7)为 1,通知主机命令已完成。
D. 主机读取回复 (Host Reads Reply)
- 轮询完成标志 :主机通过轮询 CdbCmdCompleteFlag 来判断命令是否完成。
- 读取状态和数据 :主机读取 CdbStatus 寄存器以确认命令是成功还是失败,并读取 Page 9Fh 的回复头和 LPL/EPL 区域以获取具体的回复数据。
- 验证完整性 :主机可以使用 RPLChkCode 来验证收到的回复数据是否完整无误。
总结来说,CDB 通过一套严谨的消息格式(包含头部、有效载荷、校验码)和状态机(通过完成标志和状态寄存器同步),在传统的寄存器接口之上构建了一个可靠的、面向复杂任务的通信通道。
4.CDB流程中如何处理错误情况
在CDB(Command Data Block)流程中,错误处理是一个重要的方面,它确保了命令和回复的正确性和可靠性。以下是根据提供的文档内容总结的关于如何处理错误情况的一些关键点:
命令完整性检查:
- 在发送命令之前,主机需要计算并填充
CdbChkCode字段(9Fh:133),这是一个基于命令消息体部分的一补数校验码。模块接收到命令时会重新计算这个校验码,并与接收值比较以验证消息的完整性。- 如果校验失败(即计算出的
CdbChkCode与接收到的不同),则认为命令无效。状态报告:
- 模块完成命令处理后会设置
CdbCmdCompleteFlag(00h:8.6 或 8.7),并且更新CdbStatus(00h:37 或 38)来反映命令执行的结果。例如,在成功情况下,CdbStatus会被设置为00 000001b;如果出现错误,则可能会有不同的错误代码,比如01 000000b表示未指定的失败,或01 000101b表示CdbChkCode错误等。回复数据完整性检查:
- 对于包含回复负载的情况,模块也会计算并提供一个
RPLChkCode(9Fh:135)。主机可以使用这个校验码来验证回复消息体的完整性。如果校验失败,说明回复可能已损坏或被篡改。特定CMD错误处理:
- 对于某些特定的CMDID,比如更改密码(CMD 0002h),如果新密码未能接受或者存在权限不足等问题,模块会在
CdbStatus中返回相应的错误代码。例如,01 000110b代表密码错误-未接受,而01 000010b则可能是参数范围错误。未来扩展兼容性:
- 预见到未来CMIS修订版可能会增加可选参数到现有的CDB命令中,因此建议模块不要严格依赖长度字段进行检查。对于接收到的消息长度超出预期的情况,模块应该只处理已知长度的部分,并忽略其余部分,同时保证对整个接收到的数据长度计算
RPLChkCode。
LPL 和 EPL 的支持主要由光模块(Module),而非 Host。
Host 只需具备通过 I²C 访问 Page 9Fh(LPL)和 Pages A0h--AFh(EPL)的能力即可。
5.查询模块的 CDB 能力
Host 应该先通过 CDB 能力查询命令(Capabilities Inquiry)来确定模块支持哪些传输方式。
5.1. 查询模块是否支持 CDB

5.2. 查询模块对 EPL 的支持能力
-
关键字段 :
Page 01h, Byte 163的低 4 位(CdbMaxPagesEPL)CdbMaxPagesEPL = 0→ 不支持 EPL,只能用 LPL(≤120 字节命令)。CdbMaxPagesEPL = N (1~16)→ 支持最多 N 个 EPL 页面(即最多 128×N 字节扩展负载)。

5.3. 查询 Auto Paging 和最大写长度(影响 Host 实现)
Page 01h, Byte 164:CdbReadWriteLengthExtension
→ 告知 Host 单次 I²C 写操作最多可写多少字节(影响是否能一次性写完 LPL+EPL 头部)。Page 01h, Byte 163.4:CdbAutoPagingSupported
→ 若为 1,Host 可连续写跨页 EPL 数据而无需手动切换页面和换行。
6.测试 LPL
以 固件升级(Firmware Management, CMD ID 0100h--011Fh)为例
注意:固件镜像通常远大于 120 字节,因此必须使用 EPL 。
但可以通过以下方式模拟或验证不同路径:
场景 1:测试 LPL(非固件升级)
由于固件数据太大,无法仅用 LPL。但可以测试其他小参数命令来验证 LPL 路径:
示例:测试 CMD 0000h: Query Status

LPLLength = 2(仅传递ResponseDelay)EPLLength = 0- 所有数据在 Page 9Fh:136--137
✅ 测试方法:
- 主机写入 LPL 参数(136--137)

- 写入头部(130--133)和 CMDID(128--129)


- 等待完成标志,读取回复(也在 LPL)

6.1.LPL举个栗子
第一步:主机写入 LPL 参数(Page 9Fh:136--137)
这里写入的是
ResponseDelay字段,类型为 U16 (无符号 16 位整数),单位是 毫秒 (ms)。
字节地址 内容 说明 9Fh:136 Delay_Lo延迟时间的低字节(LSB) 9Fh:137 Delay_Hi延迟时间的高字节(MSB) 例如 :
如果希望模块延迟 500 ms 后再响应,则:
500 = 0x01F4
9Fh:136 = 0xF4
9Fh:137 = 0x01
如果希望立即响应,则设为 0:9Fh:136 = 0x00
9Fh:137 = 0x00
第二步:主机写入命令头部(Page 9Fh:128--133)
按顺序或按模块要求的方式(见触发机制)写入以下字段:
字节地址 字段名 值(Query Status 示例) 说明 9Fh:128--129 CMDID0x0000 命令 ID = 0000h(低位在前:128=0x00, 129=0x00) 9Fh:130--131 EPLLength0x0000 未使用 EPL(130=0x00, 131=0x00) 9Fh:132 LPLLength0x02 LPL 使用了 2 字节(即 136--137) 9Fh:133 CdbChkCode需计算 校验码(见下方计算方法)
如何计算
CdbChkCode(9Fh:133)?根据 Page 282, Table 8-178 的定义:
CdbChkCode = One's complement of the arithmetic sum of Bytes 9Fh:128 to 9Fh:(136 + LPLLength - 1), excluding Bytes 133--135.
对于本例:
- 起始:128
- 结束:136 + 2 - 1 = 137
- 排除:133, 134, 135(但 134--135 本就不在范围内)
- 所以参与计算的字节是:128, 129, 130, 131, 132, 136, 137
示例计算(Delay = 500 ms = 0x01F4):
地址 值(Hex) 128 0x00 (CMDID LSB) 129 0x00 (CMDID MSB) 130 0x00 (EPLLength LSB) 131 0x00 (EPLLength MSB) 132 0x02 (LPLLength) 136 0xF4 (Delay LSB) 137 0x01 (Delay MSB) 求和 :
0x00 + 0x00 + 0x00 + 0x00 + 0x02 + 0xF4 + 0x01 = 0xF7
取一补码 (One's Complement)
→
CdbChkCode = ~0xF7 = 0x08(因为 0xF7 + 0x08 = 0xFF)所以:9Fh:133 = 0x08
注意:校验和是 8 位加法(溢出丢弃),结果取反。
第三步:触发命令执行
根据模块广告的触发方式(
01h:165.7):
方式 A(推荐分步写)
- 先写 136--137(参数)
- 再写 130--133(头部,不含 CMDID)
- 最后写 128--129 = 0x00, 0x00 → 触发执行
方式 B (单次写)
一次性写入 128--137 共 10 字节,I²C STOP 后触发
134 和 135 在发送命令时可以写任意值(通常写 0x00),因为它们是 Reply Header(回复头),由模块在返回时覆盖,主机在发命令时无需关心其内容。
第四步:等待并读取光模块的回复内容(也在 LPL: 136--137)
模块处理完成后:
- 置位
CdbCmdCompleteFlag(00h:8.6 或 8.7 = 1)- 设置
CdbStatus(00h:37/38)为00 000001b(Success)- 在 Page 9Fh 写入回复数据:
地址 值(示例) 含义 9Fh:134 0x02 RPLLength = 2(回复用了 2 字节 LPL)9Fh:135 计算值 RPLChkCode(对 136--137 求和取反)9Fh:136 0x02 回复负载长度(含自身) 9Fh:137 0x01 状态: 0x01 = Host Password Accepted(下面解释为啥有这个)LPL功能验证根据 OIF-CMIS-05.3, Page 290, Table 9-3 ,
CMD 0000h: Query Status的标准回复负载 是:
特性 主机密码(Host Password) 模块密码(Module Password) 用途 日常管理、配置 高权限操作(固件、安全、恢复) 密码范围 0x00000000--0x7FFFFFFF0x80000000--0xFFFFFFFF识别方式 Bit 31 = 0 Bit 31 = 1(最高位为 1) 状态回复 Status Byte = 0x01(bit 0 置 1)Status Byte = 0x80或更高(bit 7=1,即1xxx xxxxb)谁设置 系统管理员 / 主机 模块厂商(或授权人员) CDB 命令支持 CMD 0001h(Enter)、0002h(Change)同样使用 CMD 0001h,但密码值需带 Bit 31"Query Status"这个命令的本意就是查询模块当前状态,包括:
- 密码是否已接受(安全状态)
- 是否支持后台处理
- 其他未来扩展状态位
ResponseDelay只是用来控制模块延迟多久再返回这个状态,不影响状态本身。模块行为:
- 等待 500 ms;
- 检查自身状态:主机密码已被接受(Host Password Accepted = 1);
- 返回:
- 134: RPLLength = 0x02
- 135: RPLChkCode = ~(0x02 + 0x01) = ~0x03 = 0xFC
- 136: 0x02 (回复长度)
- 137: 0x01 (状态:bit0=1)
如果您从未输入密码,模块可能返回:
- 137: 0x00 (bit0=0,仅上电,未输入主机密码)
6.2.LPL 的核心作用
LPL 是 CDB 命令/回复中存放短小参数或控制信息的区域。它适用于:
- 参数总长度 ≤ 120 字节的命令;
- 即使使用 EPL 传输大数据,控制元数据(metadata)也常放在 LPL。
使用 LPL 的典型 CDB 命令
- 模块安全与密码管理
CMD ID 命令 LPL 用途 0001hEnter Password LPL[0--3] = 4字节密码(见 Page 291, Table 9-4) 0002hChange Password LPL[0--3] = 新密码(见 Page 292, Table 9-5) 🔒 这些命令完全依赖 LPL,因为密码就是 4 字节,远小于 120B。
- 固件管理(Firmware Management)
虽然固件数据走 EPL,但控制指令全在 LPL:
CMD ID 命令 LPL 内容示例 0100hStart Firmware Download LPL[0--3] = 固件镜像大小(U32) LPL[4] = 镜像选择(A/B) 0101hCancel Firmware Download LPL 为空(LPLLength=0) 0103hComplete Firmware Download LPL 可能包含校验和或标志 0104hRun Firmware Image LPL[0] = 镜像ID(0=A, 1=B) 0105hCommit Firmware Image LPL[0] = 确认标志 关键点 :固件二进制数据通过 EPL 传输(CMD
0102h),但所有流程控制命令都用 LPL。
- 能力与特性查询(Capabilities Inquiry)
这些命令用于发现模块支持哪些功能:
CMD ID 命令 LPL 用途 0040hModule Features LPL 可指定要查询的功能组 0041hFirmware Management Features LPL 可选子功能查询 0044hSecurity Features 查询安全能力 回复通常也在 LPL(≤120B 足够描述能力位图)。
- 性能监控与诊断
CMD ID 范围 功能 LPL 用途 0200h--027FhPerformance Monitoring LPL 传递监控参数 ID、时间窗口等 0380h--03FFhDiagnostics & Debug LPL 指定诊断项(如寄存器地址、测试模式) 例如:
- "读取某 PM 参数的历史最小值" → LPL 传参数 ID + 时间戳;
- "启动眼图测试" → LPL 传测试配置。
- 安全功能(Security Features)
CMD ID 命令 LPL 用途 0400h+Get Device Certificate LPL 指定证书类型 Generate Signature LPL 传待签名数据的哈希值(若 ≤120B)
LPL 在"组合模式"中的角色(LPL + EPL)
这是最常见的情况:LPL 传控制信息,EPL 传大数据。
场景 LPL 内容 EPL 内容 写固件块(0102h) 块序号、偏移、长度 实际固件二进制数据(128~256B) 读日志记录 日志ID、起始地址 返回的日志内容 批量写寄存器 寄存器起始地址、数量 要写入的值 设计哲学:LPL 是"信封上的地址和说明",EPL 是"包裹里的货物"。
纯 LPL vs 纯 EPL vs 组合
类型 是否常见 示例 纯 LPL(LPL>0, EPL=0) ✅ 非常常见 密码、状态查询、控制命令 纯 EPL(LPL=0, EPL>0) ⚠️ 较少见 某些厂商自定义大数据命令 LPL+EPL ✅ 最常见于大数据操作 固件升级、日志读取
总结:LPL 的主要功能类别
功能大类 具体用途 🔐 安全控制 输入/修改密码 ⚙️ 流程控制 固件升级启停、提交、切换 ❓ 能力查询 查询模块支持哪些 CDB 命令 📊 参数配置 设置 PM 门限、诊断选项 📥 小数据交互 传输 ≤120B 的命令参数或回复 💡 一句话总结 :
LPL 是 CDB 的"控制通道" ,负责传递命令意图和元数据;
EPL 是"数据通道" ,负责搬运大块负载。绝大多数 CDB 命令都会用到 LPL,即使同时使用 EPL。
6.3.LPL升级firmware
LPL 最大仅 120 字节 (Page 9Fh:136--255),而固件镜像通常为 几百 KB 到几 MB,不可能通过单次或多次纯 LPL 传输完成完整升级。
因此,我们需要澄清几种可能的情况:
可能情况 1:执行的是 "固件激活/提交"类命令(非数据写入)
某些 CDB 固件命令本身不携带固件数据,仅传递控制指令,完全可走 LPL:
CMD ID 命令名称 是否需 EPL 说明 0100hStart Firmware Download 否 仅通知模块准备接收,参数极小(如 image size) 0103hComplete Firmware Download 否 通知模块校验已完成的下载 0104hRun Firmware Image 否 指定运行哪个镜像(A/B) 0105hCommit Firmware Image 否 提交当前运行镜像为默认 这些命令确实可以"纯 LPL"完成 ,但它们不传输固件二进制数据,只是控制流程。
🔍 请您确认 :您说的"升级"是否指执行了上述某条控制命令,而非实际写入固件内容?
可能情况 2:模块实现了 非标准/厂商私有协议
- 某些厂商可能在 CMD ID ≥ 8000h(自定义范围)中定义了自己的微型固件更新机制;
- 或者通过多次小块写入 + 内部拼接,每次用 LPL 传 ≤120 字节,循环数百次完成升级;
- 这种方式效率极低、不符合 CMIS 推荐实践,但技术上可行。
注意:CMIS 标准固件命令(如
0102h: Write Firmware Block)明确设计为使用 EPL 传输数据块(见 OIF-CMIS-05.3 Table 9-1)。
不可能情况:用标准
Write Firmware Block(0102h)纯 LPL 升级
CMD 0102h的典型 payload 是 128~256 字节固件数据 + 少量元数据;- 若强制将固件数据塞入 LPL(≤120B),则:
- 数据长度受限;
- 无法通过标准兼容性测试;
- 大多数模块会返回
CdbStatus = Parameter Out of Range(01 000010b)。
建议验证步骤
确认使用的 CMD ID:
- 如果是
0100h/0103h/0104h/0105h→ 属于正常 LPL 控制命令;- 如果是
0102h且无 EPL → 极可能是非标实现。读取模块能力:
1Read Page 01h, Byte 163 → CdbMaxPagesEPL
- 若值为 0,说明模块根本不支持 EPL,那它只能通过私有方式做小规模升级(如 Bootloader 更新)。
检查固件大小:
如果升级的"固件"只有几十字节(如配置 patch、密钥),那 LPL 足够;
如果是完整 DSP/ARM 固件(>10KB),则几乎肯定用了 EPL(即使您没显式操作,驱动或 SDK 可能自动处理了)。
您的说法 是否合理 解释 "用纯 LPL 执行了固件控制命令" ✅ 合理 如 Commit、Run 等命令无需 EPL "用纯 LPL 传输了完整固件镜像" ❌ 极不可能 违背 CMIS 设计,LPL 容量不足 "用纯 LPL 传输了微型 patch/配置" ⚠️ 可能(非标) 仅适用于极小更新,非标准固件升级 如果是在开发或测试环境中操作,也可能是底层驱动自动将数据拆分到 EPL,而您只看到 LPL 的控制部分------这种"透明封装"也很常见。
7. 标准固件升级流程:LPL + EPL 组合升级

LPL 用途 :传递控制信息(如块序号、偏移、长度等元数据)
例如:LPL[0--3] = block_index, LPL[4--5] = block_size
LPLLength = 6EPL 用途 :存放实际的固件二进制数据块(如 256 字节)
EPLLength = 256数据写入 Pages A0h--A1h(若每页 128 字节)
主机操作:
写 LPL 控制参数到 9Fh:136--141
写固件块数据到 A0h:128--255, A1h:128--...(根据长度)
设置
LPLLength=6,EPLLength=256计算
CdbChkCode(覆盖 128--132 + LPL 136--141)写 CMDID(如
0102hfor Write Firmware Block)模块处理:
验证
CdbChkCode从 LPL 读取控制信息
从 EPL 读取固件数据
写入内部 Flash
回复成功(通常 RPLLength=0)
总结
Host 不需要"支持 LPL/EPL",只需能访问对应 CMIS 页面;
模块是否支持 EPL 由
01h:163(CdbMaxPagesEPL)决定;纯 LPL 测试:用小参数命令(如 Query Status);
纯 EPL 测试:需模块支持且命令设计如此(较少见);
组合升级 :固件升级的标准模式------LPL 传控制信息,EPL 传数据。

