USB:具有中断传输和原始 HID 的低延迟 (< 1ms)

USB: low latency (< 1ms) with interrupt transfer and raw HID

我有一个项目需要定期读取外部 IMU 陀螺仪数据并将数据发送到 Android phone。

我正在使用 teensy 2.0 板通过 I2C 查询 IMU 并使用原始 HID 通过 USB 发送它。我正在使用在 teensyduino 的 usb_rawhid 的 usb_api.h 中声明的 RawHID 变量。

我读到使用中断传输的全速 USB 最大延迟为 1 毫秒,我想达到这个 1 毫秒的最大延迟。我不确定要寻找什么来实现这个最大延迟,并希望了解有关指针的信息。我的最终目标是每 2 毫秒(500 赫兹)接收一次陀螺仪数据。

我知道的一些可能有问题的事情:

1) 我已经将 RAWHID_TX_SIZE 更改为 6 个字节(陀螺仪值我只需要 6 个字节),并且 RAWHID_TX_INTERVAL 设置为 1 毫秒(最快)。 目前在接口中指定了一个我不需要的 OUT 端点,我不确定删除它是否可以改善延迟。

2) Android 将 teensy 识别为 "hiddev USB HID v1.11 Device"。我不确定这是完整的原始 HID 还是它正在尝试解析它。 Teensy 正在使用上面指定的原始 HID。

3) 在 Android 中,一个特定的线程正在尝试对 UsbRequest 进行 queue(),然后是 requestWait()。数据到达时的处理非常快(即:将其存储在全局变量中),但我受线程调度程序的摆布。

所以这些是我知道的一些指示(但不完全确定它们如何影响最大延迟)。我很想听听人们的反馈,并可能指出如何改进我的最大 USB 延迟的新方向。很难找到有关减少中断传输的 USB 延迟的信息。

对于USB,都是轮询。每 1 毫秒你就有一个 "frame" 由 none 或更多传输描述符组成,其中每个传输描述符告诉 USB 控制器轮询哪个 USB 设备。

通常,USB 控制器以用于中断传输的传输描述符开始帧。这意味着使用单个中断传输描述符,您(几乎)保证每毫秒被轮询一次。如果您的设备有中断发送它 returns 轮询时;所以最坏的情况下你会得到 1 毫秒的延迟。

可以要求 USB 控制器不那么频繁地轮询设备(例如等时传输)。也可以要求 USB 控制器在同一个 1ms 帧内多次轮询设备;但是,因为它通常会首先中断传输描述符,所以您希望几乎同时被轮询两次,并且之间有 "almost 1 ms" 间隔,因此这对最坏情况下的延迟没有帮助。

大多数情况下,据我所知,对于“< 2 ms”的要求,USB specs/protocols、USB 控制器、内核的 USB 控制器驱动程序和内核的 USB HID 驱动程序都不是问题全部。问题是及时从 USB HID 驱动程序获取数据给用户-space process/thread。

不幸的是,Linux/Andriod 不是实时的 OS。它不提供任何保证。您将受制于线程调度程序(也许还有 JVM 的垃圾收集器)。您可能对此无能为力。

我建议您首先找出为什么需要每 2 毫秒接收一次陀螺仪数据。举个简单的例子,你能不能给陀螺仪数据加上一个时间戳,然后让接收线程"reconstruct history"从这些时间戳中获取,这样接收线程就根本不需要低延迟了?