1

我的应用程序使用基于 USB 的 FTDI 芯片和 D2XX 驱动程序。它使用 OIO(重叠 IO)来读取和写入 USB。我的要求包括 30 秒超时,这是我无法减少的。代码看起来非常健壮和稳定。

一项新要求是克服 USB 电缆的意外断开和重新连接(护士将电缆踢出)。

一旦从 Windows 接收到设备已删除消息并确定它是我们的 FTDI 设备,我发现在前一个 OIO 调用超时(要求的 30 秒超时)之前,我无法从 OIO 重新连接时接收新数据。

一旦我发现断开连接,我会循环执行以下调用,直到所有排队的 OIO 都被收割:

bool CancelOIO()
{
    if (!FtdiRemaining)
        return false;

    FT_SetTimeouts(FtdiHandle, 1, 1);
    FT_W32_PurgeComm(FtdiHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

    while (FtdiRemaining)
    {
        DWORD nBytes = 0;
        if (!FT_W32_GetOverlappedResult(FtdiHandle, &FtdiOverLap[FtdiQindex], &nBytes, FALSE))
        {
            if (FT_W32_GetLastError(FtdiHandle) == ERROR_IO_INCOMPLETE)
                return true;

            if (FT_W32_GetLastError(FtdiHandle) != ERROR_OPERATION_ABORTED)
            {
                CString str;
                str.Format("FT_W32_GetOverlappedResult failed with %d\r\n", FT_W32_GetLastError(FtdiHandle));
                SM_WriteLog(str, RGB_LOG_NORMAL);
            }
        }

        FtdiRemaining--;
        FtdiTodo++;
        FtdiQindex++;
        if (FtdiQindex >= FtdiQueueSize)
            FtdiQindex = 0;
    }

    return !!FtdiRemaining;
}

我将超时时间设置为 1 毫秒。这似乎不会更改先前计划的 OIO 的超时。

我打电话FT_W32_PurgeComm取消一切。这似乎也不会取消 OIO。

我尝试调用CancelIo并返回错误,句柄无效。我的理解是由驱动程序代码来响应它。这可能是由于断开连接。

无论如何,我在循环中调用上面的代码,直到所有预定的 OIO 都被收割。30 秒内没有任何反应。然后所有的 OIO 似乎都在不到 1 毫秒的时间内结束。

作为对这段代码的测试,我在连接 USB 电缆的情况下进行了调用,它在 1 毫秒内返回。

因此,问题似乎出在拔下电缆时。

问题:我错过了什么?我还能打其他电话吗?这是一个错误吗?

我尝试过的其他事情:在调用FT_W32_GetOverlappedResult. 这导致快速返回。但我的应用程序无法再从新句柄接收数据。诡异的。有谁知道为什么?

不调用此代码。应用程序能够从新句柄接收新数据,但只能在这些超时之后。为什么?

循环端口。这不会导致这些 OIO 更快地返回。在这些超时之前,它不会改变 OIO 接收数据的使用。

4

1 回答 1

0

经过反复测试,我发现了两种不同的行为。最快的返回相当快,取消了 OIO。另一个使用了完整的 30 秒超时。

尝试减少超时以减少取消 OIO 的延迟。

于 2017-12-27T19:51:08.330 回答