如何处理 UVC 端点收到的 CY_U3P_USB_EVENT_EP_UNDERRUN 错误? 如果我们通过 UVC 端点流式传输视频数据,在 MacOS 上更改分辨率时,有时会出现 UNDERRUN 事件,导致固件崩溃并停止运行。 需要如何处理这一事件? 我附上了一份日志,其中显示 EP 0x83 出现溢出。 下面是我们的事件处理程序。
case CY_U3P_USB_EVENT_EP_UNDERRUN: /* When USB host tries to read from FX3 but no data is found. * Can occur due to unexpected DMA resets and can cause FX3 to get stuck */ CyU3PDebugPrint (4, "UsbEventCB: CY_U3P_USB_EVENT_EP_UNDERRUN on EP 0x%x...rn", evdata); CyU3PUsbResetEndpointMemories(); break;
我在
论坛上发现了一篇关于在处理程序中添加CyU3PUsbResetEndpointMemories() 并确保在重置 DMA 之前添加延迟的帖子。我们刚刚添加了 API 调用,并且已经实现了延迟,但问题仍然存在。我还添加了 CyU3PUsbInitEventLog 和 CyU3PUsbGetEventLogIndex 调用,这些调用可在本帖包含的日志文件中找到。我在 cyu3usb.h 中找到了一些定义,如 CYU3P_USB_LOG_USB3_PHY_OFF、CYU3P_USB_LOG_USBSS_RESET 和 CYU3P_USB_LOG_USBSS_CONNECT,但该文件似乎并未包含调试打印中出现的所有值。对于所有 DMA 复位,我们始终遵循以下顺序:
CyU3PUsbSetEpNak(CY_FX_EP_UVC_VS, CyTrue);CyU3PBusyWait(100);CyU3PDmaChannelReset( glSingleChHandleUVCStream);CyU3PUsbFlushEp(CY_FX_EP_UVC_VS);CyU3PUsbSetEpNak(CY_FX_EP_UVC_VS, CyFalse);
我还找到了
这篇帖子,其中建议查找 CYU3P_USBEP_SS_RESET_EVT 事件,并通过停滞端点来做出响应。 我们没有在日志中看到这个事件,但我们已经实施了这个修复,试图解决这个问题。 下面的代码可以让端点在收到该错误时停止运行:
sta
tic voidCyFxApplnE
PCB ( CyU3PUsbEpEvtType evtype, CyU3PUSBSpeed_t usbSpeed, uint8_t epNum ){ if (epNum == CY_FX_EP_UVC_VS) glBulkEpEvtCount++; if (evtype == CYU3P_USBEP_SS_RESET_EVT) { if (epNum == CY_FX_EP_UVC_VS) { CyU3PDebugPrint(2, "Halting UVC Bulk EP: %drn", glBulkRstCnt++); CyU3PUsbStall(CY_FX_EP_UVC_VS, CyTrue, CyFalse); } }}为了实际处理 USB 失速事件,我们的事件回调包括
else if ((bTarget == CY_U3P_USB_TARGET_ENDPT) (bRequest == CY_U3P_USB_SC_CLEAR_FEATURE) (wValue == CY_U3P_USBX_FS_EP_HALT)) // Use ENDPOINT HALT { /* Windows OS sends Clear Feature Request after it stops streaming, * however MAC OS sends clear feature request right after it sends a * Commit -> SET_CUR request. Hence, stop the video streaming and clear * the stall condition and sequence numbers */ glAbortCount++; /* If UVC is addressed, end stream */ if (wIndex == CY_FX_EP_UVC_VS) { CyU3PDebugPrint(4, "Video EP CLEAR_FEATURE(EP_HALT)rn"); CyU3PUsbSetEpNak (CY_FX_EP_UVC_VS, CyTrue); CyU3PBusyWait (125); CyFxUVCStreamStopHandler(); /* Actually stop stream */ CyU3PUsbResetEp(CY_FX_EP_UVC_VS); CyU3PUsbStall(CY_FX_EP_UVC_VS, CyFalse, CyTrue); CyU3PUsbSetEpNak (CY_FX_EP_UVC_VS, CyFalse); isHandled = CyTrue; CyU3PUsbAckSetup(); }
这些修复方法都没有解决问题。 如何解决? 只有在 MacOS 上,以及将 UVC 流媒体分辨率从一种分辨率切换到另一种不同帧频的分辨率时,我们才会看到这个问题。 当看到分辨率发生变化时,我们会停止任何活动数据流,使用 CyU3PConnectState(CyFalse, CyTrue) 断开 USB 连接,重置 DMA,然后使用 CyU3PConnectState(CyTrue, CyFalse) 重新连接 USB。