USB CDC ACM 串口调试:Line Coding、控制线状态与无数据

通过 SET_LINE_CODING、SET_CONTROL_LINE_STATE、Bulk 端点传输和固件行为排查 USB CDC ACM 虚拟串口设备不通的问题。

CDC ACM, USB 串口, SET_LINE_CODING, SET_CONTROL_LINE_STATE, 固件调试, 虚拟 COM 口, Bulk 端点

USB CDC ACM 设备被广泛用于虚拟串口、设备控制台、固件烧录工具、遥测通道、测试夹具和嵌入式诊断。从应用层看很简单:打开一个 COM 口或 /dev/ttyACM*,设个波特率,读写字节。但在底层,主机和设备还是要交换类特定 USB 请求和 Bulk 传输。

一台 CDC 设备枚举成功却不出数据的时候,抓包可以告诉你问题出在描述符布局、Line Coding、控制线状态、端点流量,还是固件缓冲上。

CDC ACM 有 Communication 和 Data 两个接口

一个标准的 CDC ACM 设备暴露一个 Communication Interface 和一个 Data Interface。主机在数据开始之前可能会先发一些类特定请求。

重要的证据:

  • Communication Interface 描述符
  • Data Interface 描述符
  • CDC Functional Descriptor
  • Notification Endpoint
  • Bulk IN Endpoint
  • Bulk OUT Endpoint
  • SET_LINE_CODING
  • GET_LINE_CODING
  • SET_CONTROL_LINE_STATE

如果这些请求根本没到,HOST 大概率没装上预期的 CDC 驱动。

波特率常常只是信号,不是真正的物理 UART

对很多 USB CDC 设备来说,波特率不再像 UART 那样有真正的物理意义。但主机还是会发 Line Coding。固件可以用它来配置桥接芯片、忽略它、或者校验它。

抓包要回答:

  • 主机有没有发 SET_LINE_CODING
  • 请求的波特率、校验位、停止位、数据位分别是多少?
  • 固件有没有接受这个请求?
  • 主机有没有通过 SET_CONTROL_LINE_STATE 拉高 DTR 或 RTS?
  • 固件是不是在等 DTR 才往外发?

"串口没输出"的问题里,很大一部分其实是"固件在等 DTR,但主机从来没拉过",或者"应用打开了端口但没按预期配置"。

Bulk 端点才能证明数据真在走

初始化完成之后,CDC 数据通常走 Bulk 端点。如果主机的写操作出现在 Bulk OUT 上,但 Bulk IN 上看不到任何回包,那就是固件没在往外发。如果 Bulk IN 数据出来了但应用不显示,问题可能在主机应用那一侧。

要查的:

  • Endpoint 方向
  • 传输长度
  • 反复 NAK / 超时的模式
  • 实际的 payload 字节
  • 传输状态
  • 与 Line State 请求之间的先后顺序

这就是 USB 抓包为什么比终端截图更有用的原因。

Bus Scope 在这个场景里做什么

Bus Scope 应该帮固件团队把描述符、类请求、原始端点数据放在同一个会话里。对 CDC ACM 调试来说,它需要回答:

  • 主机有没有装上 CDC?
  • 它发的 Line Coding 是什么?
  • DTR/RTS 状态有没有变化?
  • Bulk OUT 有没有带命令?
  • Bulk IN 有没有带响应?
  • 问题是出在类串口流量开始之前,还是开始之后?

你搜 "USB CDC ACM 没数据"、"虚拟 COM 口没输出"、"SET_CONTROL_LINE_STATE DTR" 的时候,证据不只在终端里——它在 USB 的类请求和端点传输里。