- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hey all,
I'm working on making my wrapper around the the CyUSB interface very robust, including being thread and process safe. I've gotten the device to recove in most of my uses cases via code, but there are still some important edge cases that currently require manually unplugging and replugging in the device to make it reset, or else needing to restart an application - which is undesirable.
To simulate different scenarios where things can go awry I'm using the CyUSBDevice reset and reconnect routines. In one of my tests I launch a separate thread that writes and reads a bunch of bulk data.What I want to happen is for the thread performing these I/O transactions to fail when I reset/reconnect/disconnect the device (whether through a false return value or exception). Sometimes this works, but other times it does not. Rather what happens is the CyUSBEndPoint gets stuck in the WaitForIO routine underneath the XferData function and hangs there, never returning! The only way to recover at this point is to kill the application..
Note that i have set the End Point Timeouts to 1sec in these tests - so the I/O if failing to timeout.
Please advise on how to properly interact with the CyUSBDevice and the Bulk End points so that this does not occur. I am using a global mutex to provide thread and process safe access to the device when reading/writing - but there is always the potential for *something* to take down the device, even if just physically unplugging and replugging it back in. I should be able to recover without the CyUSB getting into a deadlock.
Thanks,
Ryan
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Please refer to the USB control center application present in the FX3 SDK under C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\application\c_sharp\controlcenter
This should give a clear idea in which default application is implemented.
Best Regards,
Yatheesh
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello Ryan,
- Please post the code snippet of the host application if possible
- Have you tried using the Cypress USB Control Center with a large bunch of data to be transferred during which the device is removed? I tested this on the FX3 Super Speed Explorer Kit and found that the XferData() call either returns success or it fails but does not get stuck.
- Also, kindly, let me know if you have implemented the DeviceRemoved() event handler in your application.
Best regards,
Srinath S
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Srinath,
Below is the common routine used by my code for sending bulk requests (using a request-response model), let me know if you see anything odd. Note that currently the invoker will supply a ResponseBuffer of the appropriate length. If you have a good example of how to figure out how large the response is dynamically that would be helpful:
----------------------------------------------------------------------------------------------
Public Overloads Sub USBIO(ByVal CommandName As String, ByVal CommandBuffer() As Byte, ByVal ResponseBuffer() As Byte, Optional ByVal TimeOutInSec As Single = 1)
ThrowIfDisposed()
'Check if Driver Started
If Not Enabled Then Return
Dim commandBufferHandle As GCHandle = Nothing
Dim responseBufferHandle As GCHandle = Nothing
Try
_deviceMutex.WaitOne() ' Only one thread in one process may work with this FIC2USB Device at a time
Catch ex As AbandonedMutexException
' TO DO: Adding diagnostics to note that the mutex was abandoned by another process (such as from a crash)
' NOTE: Even if this exception occurs, we still successfully acquired the mutex
End Try
Try
ThrowIfDisposed()
' BEWARE OF CATASTROPHIC CYUSB BUG: We must pin the command and response buffers prior to passing them off to the unmanaged code,
' lest we risk a fatal excepion that will crash the app (regardless of any try...catch block). This bug can be seen when doing
' a lot of I/O in very tight loops.
commandBufferHandle = GCHandle.Alloc(CommandBuffer, GCHandleType.Pinned)
responseBufferHandle = GCHandle.Alloc(ResponseBuffer, GCHandleType.Pinned)
'Set Timeout (of input buffer only)
Me.CyFX2Device.BulkInEndPt.TimeOut = CUInt(TimeOutInSec * 1000)
'Send Command
If Me.CyFX2Device.BulkOutEndPt.XferData(CommandBuffer, CommandBuffer.Length) = False Then
Throw New System.IO.IOException(String.Format("Failed to XferData to BulkOutEndPt 0x{0}", Hex(CyFX2Device.BulkOutEndPt.Address)))
End If
'Read Response
If Me.CyFX2Device.BulkInEndPt.XferData(ResponseBuffer, ResponseBuffer.Length) = False Then
Throw New System.IO.IOException(String.Format("Failed to XferData from BulkInEndPt 0x{0}", Hex(CyFX2Device.BulkInEndPt.Address)))
End If
Catch ex As Exception
Me.CyFX2Device.BulkOutEndPt.Reset()
Me.CyFX2Device.BulkInEndPt.Reset()
LastError = ex
Throw ex
Finally
_deviceMutex.ReleaseMutex()
If Not IsNothing(commandBufferHandle) Then commandBufferHandle.Free()
If Not IsNothing(responseBufferHandle) Then responseBufferHandle.Free()
End Try
End Sub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Also, here is the code that handles the device attached/detached events (both call the same function). This is executed under a singleton manager class that wraps the CyUSBDeviceList instance for the process. It will in turn create wrappers for the individual CyUSBDevices that we care about. If you have any suggestions for improvement here let me know.
------------------------------------------------------------------
Private Sub UpdateDeviceList()
' Go through the CyUSB.USBDeviceList to identify anything that has been added/removed
_deviceListMutex.WaitOne()
Try
' First check for new devices
For Each cyDev As CyUSB.CyUSBDevice In mCyUSBDevices
Dim devMutex = GetMutex(cyDev)
'Try
Dim target = myDeviceList.Values.FirstOrDefault(Function(ByVal wrapper As USBDeviceWrapper) wrapper.USBAddress = cyDev.USBAddress)
If IsNothing(target) Then
If (cyDev.VendorID = MY_VID) Then
If (cyDev.ProductID >= MY_PID_LOW) And (cyDev.ProductID <= MY_PID_HIGH) Then
Dim newDev As New USBDeviceWrapper(cyDev, devMutex)
myDeviceList.Add(newDev.USBAddress, newDev)
NotifyDeviceAttached(newDev)
End If
End If
ElseIf target.VendorID <> cyDev.VendorID OrElse target.ProductID <> cyDev.ProductID Then
myDeviceList.Remove(target.USBAddress)
target.Dispose()
NotifyDeviceRemoved(cyDev.USBAddress)
If (cyDev.VendorID = MY_VID) Then
If (cyDev.ProductID >= MY_PID_LOW) And (cyDev.ProductID <= MY_PID_HIGH) Then
Dim newDev As New USBDeviceWrapper(cyDev, devMutex)
myDeviceList.Add(newDev.USBAddress, newDev)
NotifyDeviceAttached(newDev)
End If
End If
ElseIf target.CyFX2Device.DeviceHandle <> target.CyFX2Device.DeviceHandle Then
' The device was reconnected (?)
target.CyFX2Device = cyDev
End If
Next
' Second check for removed devices
Dim wrapperList = myDeviceList.Values.ToArray()
For Each curr As usbFIC2USB In wrapperList
Dim devFound As Boolean = False
Dim devIndex As Integer = 0
For devIndex = 0 To mCyUSBDevices.Count - 1
If curr.USBAddress = mCyUSBDevices(devIndex).USBAddress Then
devFound = True
Exit For
End If
Next
If devFound Then Continue For
' The wrapper did not have a corresponding cyUSBDevice, so dispose of it
myDeviceList.Remove(curr.USBAddress)
NotifyDeviceRemoved(curr.USBAddress)
curr.Dispose()
Next
Catch ex As Exception
#If DEBUG Then
Debugger.Launch()
#End If
Throw ex
Finally
_deviceListMutex.ReleaseMutex()
End Try
End Sub
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Also, after I fixed a small bug in my NotifyDeviceRemoved function that was preventing listeners from being notified that the device had been removed, the problem appears to have gone away. However, this shouldn't make any difference. Even if other code incorrectly tries to access a disposed CyUSBDevice object (since they weren't notified about it being removed), any requests should still ultimately return with either a false return value or by means of an exception and not hang. However, perhaps this will help focus the investigation into fixing this off-case.
Is there perhaps some use of a WeakReference under the covers that is being checked for disposal purposes?
EDIT: I confirmed that I could re-create the problem by commenting out the few lines of code above that are responsible for notifying listeners that a device was removed and for removing the device from the local list of devices and disposing the wrapper object. So likely a reference counting issue going on here.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The CyUSB Device hanging issue continues to intermittently pop up. This time I'm seeing it hang after a Bulk XFER fails and I attempt to Reset the BulkInEndPt. The reset command hangs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Please refer to the USB control center application present in the FX3 SDK under C:\Program Files (x86)\Cypress\EZ-USB FX3 SDK\1.3\application\c_sharp\controlcenter
This should give a clear idea in which default application is implemented.
Best Regards,
Yatheesh