首页 文章

修复流式USB数据的差距

提问于
浏览
6

我们有一个带有一些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);
    }

3 回答

  • 0

    提示:不要写入文件....队列 .

    现代计算机有多个处理器 . 如果您想尽可能快地使用某些东西,请使用多个处理器 .

    • 在线程处理USB数据,检查校验和等 . 它将结果排队(仅)到线程安全队列 .

    • 另一个线程从队列中读取数据并将其写入文件,可能是缓冲的 .

    完了;)

    100ms是体面操作的大量时间 . 我已经成功地使用C#每秒管理大约250,000个IO数据包(财务数据)而不费吹灰之力 .

    基本上,确保您的IO线程仅执行此操作并使用内部存储器作为缓冲区 . 特别是在一端处理硬件时,执行此操作的线程应该只执行此操作,如果需要以高优先级运行,则可能 .

  • 4

    要在USB上获得良好的Windows读取吞吐量,通常需要将多个异步读取(或非常大的读取,这通常不太方便)排队到USB设备堆栈上 . 我不太确定FTDI驱动程序/库在这方面做了什么 .

    传统上,我已经编写了一系列OVERLAPPED结构和一系列缓冲区的机制,并且一旦它们空闲就立即将它们拖入ReadFile . 大约5 - 6年前,我在USB2上做了40 MB / s的读取,因此现代PC应该能够应付 .

    非常重要的是你(或你的驱动程序/库)没有进入“开始读取,完成读取,处理数据,开始另一个读取”循环,因为你会发现总线空闲大片的时间 . USB分析仪会显示是否发生这种情况 .

    我同意其他人的意见,你应该尽快找到正在进行读取的线程 - 不要阻塞FTDI事件处理程序,而不是将缓冲区放入另一个队列 .

    我预先分配一个循环缓冲区队列,选择下一个空闲队列并将接收到的数据丢入其中,然后尽快完成事件处理 .

    所有校验和连接与其伴随的内存分配,垃圾收集等,可以在PC上可能100个MB的缓冲时间/空间的另一侧完成 . 目前,您可能会有效地要求您的FPGA /硬件缓冲区适应您所需的时间来完成各种笨重的PC工作,这些工作可以在以后完成 .

    我很乐观 - 如果你真的可以在硬件上缓冲100ms的数据,你应该能够可靠地工作 . 我希望我能说服我的所有客户这么多......

  • 2

    那么您的接收代码是什么样的?您是否有一个以高优先级运行的线程,仅负责捕获数据并以非阻塞方式将其传递到内存中的另一个线程?您是否以更高的优先级运行流程?

    您是否设计了其余的代码以避免更昂贵的第二代垃圾收集?缓冲区有多大,它们是否在大对象堆上?你有效地重复使用它们吗?

相关问题