我们有一个带有一些FPGA和一个FTDI USB控制器的硬件系统。通过USB的硬件流数据以大约5MB / s的速度传输到PC,软件的任务是保持同步,检查CRC并将数据写入文件。
FTDI芯片有一个“忙”的引脚,当它等待PC开展业务时它会变高。 FTDI和其他硬件上的缓冲量有限。
忙线的持续时间比硬件缓冲时间长(50-100ms),所以我们正在丢失数据。为了避免我们重新设计硬件,我被要求“修复”这个问题!
我认为我的代码足够快,因为我们的代码运行速度高达15MB / s,因此在某个地方留下了IO瓶颈。我们只是期望PC / OS过多吗?
这是我的数据录入点。偶尔我们会得到一个丢弃的位或字节。如果校验和不计算,我会一直移动直到它完成。 byte []数据几乎总是4k。
void ftdi_OnData(byte[] data)
{
List<byte> buffer = new List<byte>(data.Length);
int index = 0;
while ((index + rawFile.Header.PacketLength + 1) < data.Length)
{
if (CheckSum.CRC16(data, index, rawFile.Header.PacketLength + 2)) // <- packet length + 2 for 16bit checksum
{
buffer.AddRange(data.SubArray<byte>(index, rawFile.Header.PacketLength));
index += rawFile.Header.PacketLength + 2; // <- skip the two checksums, we dont want to save them...
}
else
{
index++; // shift through
}
}
rawFile.AddData(buffer.ToArray(), 0, buffer.Count);
}
答案 0 :(得分:4)
提示:不要写入文件....队列。
现代计算机有多个处理器。如果您想尽可能快地使用某些东西,请使用多个处理器。
完成;)
100ms是体面操作的大量时间。我已经成功地使用C#每秒管理大约250,000个IO数据包(财务数据),而且不费吹灰之力。
基本上,确保您的IO线程仅执行此操作并将内部存储器用作缓冲区。特别是在一端处理硬件时,执行此操作的线程应该只执行此操作,如果需要,则可能以高优先级运行。
答案 1 :(得分:2)
要在USB上获得良好的Windows读取吞吐量,通常需要将多个异步读取(或非常大的读取,这通常不太方便)排队到USB设备堆栈上。我不太确定FTDI驱动程序/库在这方面做了什么。
传统上我编写了一系列OVERLAPPED结构和一系列缓冲区的机制,并且只要它们空闲就一直将它们拖入ReadFile。大约5 - 6年前,我在USB2上做了40 + MB / s的读取,因此现代PC应该能够应付。
非常重要的是你(或你的驱动程序/库)没有进入“开始读取,完成读取,处理数据,开始另一个读取”循环,因为你会发现总线是闲逛了很长一段时间。 USB分析仪会显示是否发生这种情况。
我同意其他人的意见,你应该尽快找到正在进行读取的线程 - 不要阻塞FTDI事件处理程序超过将缓冲区放入另一个队列的时间。
我预先分配一个循环的缓冲区队列,选择下一个空闲缓冲区并将接收到的数据放入其中,然后尽快完成事件处理。
所有校验和连接与其伴随的内存分配,垃圾收集等,可以在PC上可能100个MB的缓冲时间/空间的另一侧完成。目前,您可能会有效地要求您的FPGA /硬件缓冲区适应您所需的时间来完成各种笨重的PC工作,这些工作可以在以后完成。
我很乐观 - 如果你真的可以在硬件上缓冲100ms的数据,你应该能够可靠地工作。我希望我能说服我的所有客户这么多......
答案 2 :(得分:0)
那么您的接收代码是什么样的?您是否有一个以高优先级运行的线程,仅负责捕获数据并以非阻塞方式将其传递到内存中的另一个线程?您是否以更高的优先级运行流程?
您是否设计了其余代码以避免更昂贵的第二代垃圾收集?缓冲区有多大,它们是否在大对象堆上?你有效地重复使用它们吗?