描述符在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协商基本是“发→收→匹配→确认”的套路,每次交互的核心就是描述符。你看下面的流程:
- Source广播:发送Source_Capabilities描述符,里面塞了一组PDO。
- Sink解析:读描述符,看哪些PDO自己满足。
- Sink请求:发Request消息,引用选中的PDO编号。
- Source确认:回Accept或者Reject,Accept里包含选中的PDO信息。
- 双方切换:基于描述符里的参数执行电压/电流切换。
关键点:如果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. 核心知识图谱
下面这张图展示了设备、描述符和协商消息之间的关系,你看了就能明白描述符在整个流程中的位置。
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重试机制也能缓解。