4、DSI数据包格式:长包与短包结构、Packet Header/Footer、ECC与Checksum计算

MIPI DSI协议在高速模式下通过差分信号线(Data Lane)传输串行化数据包。理解数据包格式是驱动开发中解析初始化序列、配置寄存器以及调试链路稳定性的基础。DSI数据包分为短包和长包两种类型,它们在结构、用途和错误检测机制上存在显著差异。

4.1 短包结构(Short Packet)

短包用于传输控制信息或少量数据,其总长度为4字节(32位),不包含数据负载。短包由Packet Header(数据包头)组成,没有Packet Footer(数据包尾)。

字节偏移 字段名称 位宽(bit) 描述
0 Data ID (DI) 8 包含虚拟通道标识(VC, 高2位)和数据类型(DT, 低6位)
1 Data Byte 0 8 短包数据低字节(或命令参数)
2 Data Byte 1 8 短包数据高字节(或命令参数)
3 ECC 8 错误校正码,覆盖前3个字节

短包典型应用场景包括:

  • 命令模式(Command Mode):发送DCS短包写命令(如0x05、0x15)配置显示寄存器。
  • 同步信号:V-Sync、H-Sync等事件触发包。
  • 读取响应:从外设读取状态或数据。
驱动开发提示: 在初始化序列中,绝大多数寄存器配置命令(如进入Sleep Out、设置Pixel Format)都通过短包发送。短包结构简单,但ECC校验必须正确,否则接收端会丢弃该包。

4.2 长包结构(Long Packet)

长包用于传输大量数据负载,例如图像帧数据、初始化参数块或Gamma校正表。长包由三部分组成:Packet Header(4字节)、Data Payload(可变长度,0~65535字节)和Packet Footer(2字节Checksum)。

长包格式总览: Header (4B) + Payload (WC × 1B) + Footer (2B)
部分 字段 位宽 说明
Header Data ID (DI) 8 bit VC + DT,标识包类型和虚拟通道
Word Count (WC) 16 bit Payload字节数(低字节在前)
ECC 8 bit 覆盖Header的3个字节(DI + WC)
Header总长4字节
Payload Data Bytes WC × 8 bit 实际传输的数据内容
Footer Checksum 16 bit 对Payload进行16位CRC校验

长包的关键特性:

  • Word Count (WC):指示Payload的字节数,最大值为65535。WC为0时表示空负载长包,此时Footer仍存在。
  • Payload对齐:协议要求Payload字节数必须为偶数,若WC为奇数,接收端需做填充处理(通常忽略最后一个字节)。
  • Footer:仅保护Payload数据,不保护Header。

4.3 Packet Header与ECC计算

Packet Header是DSI数据包的“身份证”,包含路由信息(VC)、类型标识(DT)以及长度/参数。ECC(Error Correction Code)采用汉明码(Hamming Code),能够检测并纠正1位错误,检测2位错误。

ECC计算覆盖Header的前3个字节(24位),生成8位校验码。其生成多项式基于(12,8)汉明码扩展。驱动开发中通常不需要手动计算ECC,但理解其原理有助于调试链路错误。

常见调试陷阱: 如果初始化序列中短包频繁被外设NACK(No Acknowledge),首先检查ECC字段是否正确。部分桥接芯片或外设对ECC计算有特定字节序要求(Little-Endian vs Big-Endian)。

ECC校验码的生成规则(简化):

// 伪代码:ECC生成(基于24位输入)
// 输入:byte[0] (DI), byte[1] (WC_Low), byte[2] (WC_High)
// 输出:ecc_byte (8位)

uint8_t calculate_ecc(uint8_t b0, uint8_t b1, uint8_t b2) {
    uint32_t data = (b2 << 16) | (b1 << 8) | b0;
    uint8_t ecc = 0;
    // 位交织奇偶计算(具体位映射参考MIPI DSI规范v1.3.2第8.2节)
    // 实际驱动中可使用查表法或硬件CRC单元加速
    // ...
    return ecc;
}

4.4 Packet Footer与Checksum计算

长包的Footer包含一个16位的Checksum,用于验证Payload数据的完整性。Checksum算法采用CRC-16-CCITT,生成多项式为:

G(x) = x¹⁶ + x¹² + x⁵ + 1 (0x1021)

计算步骤:

  1. 初始化CRC寄存器为0xFFFF。
  2. 对Payload的每个字节(从第一个到最后一个)进行CRC计算。
  3. 计算完成后,对结果取反(One's Complement),得到最终的Checksum值。
  4. Checksum以低字节在前(Little-Endian)的顺序放入Footer。
// C语言示例:DSI CRC-16计算
#include <stdint.h>

uint16_t dsi_crc16(const uint8_t *data, uint16_t len) {
    uint16_t crc = 0xFFFF;
    for (uint16_t i = 0; i < len; i++) {
        crc ^= (uint16_t)data[i] << 8;
        for (int j = 0; j < 8; j++) {
            if (crc & 0x8000)
                crc = (crc << 1) ^ 0x1021;
            else
                crc <<= 1;
        }
    }
    return ~crc; // 取反
}
性能优化: 在嵌入式驱动中,如果Payload长度固定(如初始化序列块),可以预计算Checksum并固化在代码中,避免运行时重复计算。对于图像数据流,建议使用硬件CRC引擎。

4.5 长包与短包对比总结

特性 短包 长包
总长度 4字节(固定) 6 + WC 字节(可变)
数据负载 最多2字节(Data Byte 0/1) 0 ~ 65535字节
错误检测 ECC(1位纠错,2位检错) Header: ECC;Payload: CRC-16
典型用途 命令、同步、读取 图像数据、大块参数
传输效率 高(无负载开销) 低(有Footer开销)

4.6 DSI数据包结构总览图

下图展示了DSI短包与长包在数据通道上的完整结构,以及ECC和Checksum的保护范围。

DSI数据包结构:短包 vs 长包 短包 (Short Packet) — 4 Bytes Data ID (8b) Data Byte 0 (8b) Data Byte 1 (8b) ECC (8b) ECC 保护范围 (3 Bytes) 长包 (Long Packet) — 6 + WC Bytes Data ID (8b) WC Low (8b) WC High (8b) ECC (8b) Packet Header (4 Bytes) Data Payload (WC Bytes, 0 ~ 65535) 由 Word Count 字段指定长度 Checksum Low (8b) Checksum High (8b) Packet Footer (2 Bytes) — CRC-16 CRC-16 保护范围 (Payload 全部字节) Header 数据字段 ECC 校验字段 Payload 数据 Checksum 字段

4.7 驱动开发中的实际应用

在初始化序列配置中,驱动工程师需要将显示控制器的寄存器配置命令封装为DSI数据包。以下是一个典型的初始化序列片段,展示了短包和长包的使用:

// 伪代码:DSI初始化序列发送
void dsi_send_init_sequence(DSI_Handle *dsi) {
    // 1. 短包:发送 Software Reset (0x01)
    dsi_send_short_packet(dsi, VC_0, DT_DCS_SHORT_WRITE, 0x01, 0x00);

    // 2. 短包:发送 Sleep Out (0x11)
    dsi_send_short_packet(dsi, VC_0, DT_DCS_SHORT_WRITE, 0x11, 0x00);

    // 3. 长包:发送 Pixel Format (0x3A) 带参数 0x77
    uint8_t payload[] = {0x3A, 0x77};
    dsi_send_long_packet(dsi, VC_0, DT_DCS_LONG_WRITE, payload, 2);

    // 4. 长包:发送 Gamma 校正表 (128字节)
    uint8_t gamma_table[128];
    // ... 填充 gamma 表数据
    dsi_send_long_packet(dsi, VC_0, DT_GAMMA_LONG_WRITE, gamma_table, 128);

    // 5. 短包:发送 Display On (0x29)
    dsi_send_short_packet(dsi, VC_0, DT_DCS_SHORT_WRITE, 0x29, 0x00);
}
关键调试点: 当外设无响应时,使用逻辑分析仪或DSI协议分析仪抓取数据包,检查Header中的ECC和Footer中的Checksum是否正确。常见错误包括:WC字节序错误、ECC计算未包含正确的字节范围、CRC初始值未设置为0xFFFF。

理解DSI数据包格式是驱动开发的基础。短包用于高效的控制命令,长包用于大块数据传输。ECC和Checksum提供了链路层的错误检测能力,驱动工程师需要确保这些校验字段的正确性,以保证初始化序列的可靠执行。