描述符在PD协商中的作用

做过USB PD开发的朋友都知道,整个协商过程说白了就是Source和Sink互相交换描述符、确认能力的过程。描述符一旦出错,轻则协商失败,重则烧设备。我早年就因为这个吃过亏,后面会细说。

1. 描述符是什么

描述符是一组结构化数据,承载着设备的能力信息。在PD协议里,它扮演着“身份证+菜单”的双重角色:既告诉对方我是谁,也列出我能提供/支持哪些电压电流组合。

我个人习惯把描述符分成两层:对象描述符和能力描述符。前者描述设备类型、VID/PID等静态信息,后者描述供电能力、备用模式等动态配置。

2. 描述符的种类与结构

PD 3.1规范里描述符数量不少,但实际查询和解析时,最常打交道的是下面这几种:

描述符类型 结构长度(字节) 关键字段 典型用途
Source_Capabilities 28 PDO数量、电压、电流 供电能力广播
Sink_Capabilities 24 请求电压范围、电流需求 受电能力上报
BIST 4 测试模式 内部环回测试
Device_ID 16 VID、PID、XID 设备识别

特别注意:Source_Capabilities描述符里面每个PDO是有固定格式的——固定PDO(5V/3A)、可调PDO(PPS)、可变PDO。我曾经在一个量产项目里遇到描述符长度计算错误,导致Source多发了两个无效PDO,Sink解析时直接丢弃合法数据,最终停在5V档位。排查了两天才找到原因。

3. 描述符在协商流程中的位置

PD协商基本是“发→收→匹配→确认”的套路,每次交互的核心就是描述符。你看下面的流程:

  1. Source广播:发送Source_Capabilities描述符,里面塞了一组PDO。
  2. Sink解析:读描述符,看哪些PDO自己满足。
  3. Sink请求:发Request消息,引用选中的PDO编号。
  4. Source确认:回Accept或者Reject,Accept里包含选中的PDO信息。
  5. 双方切换:基于描述符里的参数执行电压/电流切换。

关键点:如果Source发的描述符里PDO格式错误(比如电流字段写的是0xFFFF),Sink会认为不可用,于是忽略所有PDO,停在5V。这种情况我在客户现场遇到过,一个千兆网口扩展坞就是因此带不动硬盘。

核心结论:描述符的完整性、顺序、计数器、预留位,任何一个bit错了都可能让协商卡死。所以抓协议分析仪时,第一件事就是检查Source Capabilities描述符的字节数是否和长度字段一致。

4. 常见描述符错误场景

这几年我排查过的PD故障里,描述符相关的占了六成。挑3个典型的说说:

  • PDO数量计数器与实际不符——描述符头里的“Number_of_PDO”写3,后面却只跟了2个PDO。Sink读完第2个PDO后不会继续读,计数器还等着第3个,最终超时。
  • 电压/电流值超出规范范围——比如PPS里电流写成0,Sink认为无效,不再协商。其实有些不合规的Source芯片会输出这些异常值,得在固件里做过滤。
  • 描述符CRC校验错误——传输污染导致描述符内部校验过不了。这时候Sink会发Hard_Reset。我曾经加了一版crc迭代次数补丁才搞定某厂商的MCU。

排查小技巧:如果你没有专用分析仪,可以用带PD抓包的USB-C转接板配合Wireshark,直接看USB PD协议层的描述符内容。我个人习惯是先看描述符头部的长度字段,再看PDO的电压电流是不是合理值。比如5V PDO最小电压应该≥5.0V,如果写成4.5V,八成是描述符里配置错了。

!警告:不要轻易修改描述符里的保留位(Reserved field)。有些工程师觉得“保留位反正不检查,随便填0xAA”,结果某些较真的Sink芯片会拒绝协商。这就是所谓“未定义行为”坑新手的地方。我的原则:凡是规范里写明“Reserved=0”的,就老老实实写0。

5. 核心知识图谱

下面这张图展示了设备、描述符和协商消息之间的关系,你看了就能明白描述符在整个流程中的位置。

描述符在PD协商中的角色 Source(供电端) Sink(受电端) Source Capabilities Sink Capabilities BIST / Device_ID Request Accept/Reject 协商过程是描述符的交换→匹配→确认 任何描述符字段错误都会导致协商中断或误判 排查时优先检查描述符长度、PDO个数、电压电流合法范围

6. 我的排查经验

我们做过一批USB-C笔记本拓展坞,量产10K后发现约2%的机器插上65W充电器只能跑5V/3A,上不了20V。用协议分析仪抓包一看,Source Capabilities描述符里第三个PDO(20V/5A)的电流字段写了0x01C8(单位10mV),换算出来只有45W,但描述符头部写的是3个PDO。Sink解析后发现20V档只有45W,达不到笔记本要求的60W,于是放弃了。你看,一个电流值错误导致整批机器降速——这活儿后来重新烧录固件才解决。

所以我建议:描述符的每个字节最好用状态机做回环检查。比如Source发送之前自己读一遍PDO的电压电流,看是不是在合理范围内;Sink收到后也做一次合法性校验,发现异常立刻报错,不要闷头协商。这样做虽然多花几十微秒,但能避免很多诡异的硬件故障。

当然,如果遇到描述符CRC错误,问题可能出在物理层。我记得有一次客户投诉充电时而断连,换成原装充电器就没事。排查后发现是第三方线缆的CC线阻抗偏大,导致描述符数据位翻转。换一根线就好了,但固件里做CRC重试机制也能缓解。