USB端点的共享接收缓冲区?

Shared receive buffer for USB endpoints?

我正在为微控制器开发 USB 设备驱动程序(Atmel/Microchip SAMD21,但我认为问题是一般性问题)。我需要多个端点来控制和数据,USB 硬件使用每个端点描述符来(除其他外)定位输入和输出数据的缓冲区。

由于 IN 数据由主机自行决定轮询,因此每个端点都有自己的 IN 缓冲区是有意义的,因此任何端点的数据(如果有任何要发送的数据)在被轮询时立即可用。

但就来自 SETUP & OUT 事务的传入数据而言,我想到可以通过将所有端点配置为使用共享缓冲区来节省内存。每个端点都有自己的缓冲区似乎很浪费,因为考虑到 USB 事务的性质,一次只能发生一个这样的事务。

显然,这种方法需要足够快地处理事务中断,以便释放共享缓冲区并及时为新事务做好准备,无论下一个事务是什么——但这已经是控制端点的要求,其中某些 SETUP 事务紧随 OUT。

那么,假设时机可行,还有其他原因导致这种方法行不通吗?

可能不会。

通常,微控制器上的 USB 模块通过跟踪它已将数据写入哪个数据包缓冲区来处理 OUT 数据包,并等待您的固件说它已完成缓冲区处理,然后再从计算机接受更多数据并覆盖缓冲区。如果端点没有可用于接收更多数据的缓冲区,但计算机向端点发送了一个 OUT 数据包,则 USB 模块通常会用一个 NAK 数据包响应计算机,告诉计算机它应该稍后重试。在这种情况下,您的固件可能需要很长时间才能处理 OUT 数据包。

通过将多个端点配置为使用相同的缓冲区,您会搞砸这个系统。当您在任何端点上收到 OUT 数据包时,USB 模块(可能)不知道多个端点使用相同的缓冲区,因此它不会在您的其他 OUT 端点上发出 NAK 数据包。如果它立即收到另一个 OUT 数据包,它将把它写入同一个缓冲区,覆盖之前的数据包。因此,无论何时您收到一个数据包,您的代码都必须尽可能快地执行某些操作,例如将数据复制出该缓冲区、禁用其他 OUT 端点或重新分配缓冲区。

即使你真的能让它工作,这也意味着你节省一点内存的方案将 USB 事件的服务变成了一个实时任务(即一个需要你的代码响应的任务几微秒)。如果你以后想在你的系统中添加另一个实时任务,那将是非常困难的,因为你总是必须准备好被你的 USB 处理代码打断。

SAMD21 拥有大量内存 (32 KB),因此您可能无需担心优化这部分内容。

我同意 。您没有提到您正在创建的设备的速度。低速只需要几个 8 字节缓冲区。全速,几个 64 字节缓冲区。高速,可能是八个 64 字节缓冲区,具体取决于您的用途。一个超高速的设备,你仍然只谈论几个 512 字节的缓冲区。

我会为每个端点创建一个环形缓冲区。这样你就不会四处移动数据。您只是使用一个指向内存环内条目的指针。具有控制端点、中断端点和两个批量端点的全速设备,每个端点每个环有 16 个 64 字节条目,总共仍然只有 4k RAM,占总 RAM 的 1/8。

但是,我对 SAMD21 不熟悉,所以请检查规范以确保它能正常工作。