- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am struggling with getting stale GPIF data on the FX3 following host-side glitches or program crashes. Presently, I configure 2 DMA channels from the GPIF and ping-pong back and forth from them to stream image data, which works. However, if the host-side program crashes, and then is restarted, I get random data from the previous acquisition.
For example, if I configure a CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE transfer, I can tag each buffer with a sequentially increasing number in the call back. if I start a transfer with Begin/Wait/FinishDataXfer and then print the number sent on the host I get:
1 2 3 4 5 .... 4096 (each buffer I sent shows up in order at the host)
If instead I do Begin/Wait/FinishDataXfer and then close the program mid transfer, then launch it again, I get:
3387 3388 3389 3390 3391 3392 1 2 3 ... (I get 6 buffers from the previous aborted transfer and then the new data)
This is shifting my image data and causing all kinds of data problems in the host application.
I tried flushing the USB/DMA on start:
/* Place the EP in NAK mode before cleaning up the pipe. */
CyU3PUsbSetEpNak (CY_FX_EP_CONSUMER, CyTrue);
CyU3PBusyWait (125);
apiRetStatus = CyU3PDmaMultiChannelReset (&glDmaChHandleMulti);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaMultiChannelReset failed, Error code = 0x%x\n", apiRetStatus);
CyFxAppErrorHandler(apiRetStatus);
}
//flush any stale data in the USB endpoint
CyU3PUsbFlushEp (CY_FX_EP_CONSUMER);
CyU3PUsbResetEp (CY_FX_EP_CONSUMER); //not sure if required?
//Completely reset the entire GPIF state to be safe
apiRetStatus = CyU3PGpifLoad (&CyFxGpifConfig);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PGpifLoad failed, error code = %d\n", apiRetStatus);
CyFxAppErrorHandler (apiRetStatus);
}
//reconfigure the DMA
apiRetStatus = CyU3PDmaMultiChannelSetXfer (&glDmaChHandleMulti, CY_FX_GPIFTOUSB_DMA_TX_SIZE, 0);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer failed, Error code = %d\n", apiRetStatus);
CyFxAppErrorHandler(apiRetStatus);
}
//remove NAK, not sure if I needed to do this?
CyU3PUsbSetEpNak (CY_FX_EP_CONSUMER, CyFalse);
CyU3PBusyWait (125);
//begin the GPIF state machine and start streaming data
apiRetStatus = CyU3PGpifSMStart(START, ALPHA_START);
However, I still get ~6 stale buffers if a transfer doesn't complete. Is there something else I need to reset on the FX3? Does the host side save USB data even after the receiving process terminates?
Solved! Go to Solution.
- Labels:
-
USB Superspeed Peripherals
- Tags:
- fx3
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Please refer to this thread Solved: CyU3PUsbSendEP0Data corrupts bulk DMA to host - Infineon Developer Community
Rashi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Please let us know the how many buffers are allocated for the MANUAL Many to One channel. Have you allocated 6 buffers?
Also, when the host application is closed or stopped, does it send any command to the USB device?
Jayakrishna
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
There are 2 sockets each with 3 buffers, so yes 6 total. I tested a few times and always got 6, which is why I was trying to flush the DMA buffers, although I wasn't sure if maybe the data is stuck on host side somehow.
In this case I am simulating a hard program crash, so I am terminating the process with no further device communication. My goal is to be able to recover from this situation automatically.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Thank you for the clarification. I checked the code snippet that was shared earlier in your problem description. Can you please modify this part of the code as follows:
CyU3PGpifDisable (CyFalse); //Disable GPIF II interface
/* Place the EP in NAK mode before cleaning up the pipe. */
CyU3PUsbSetEpNak (CY_FX_EP_CONSUMER, CyTrue);
CyU3PBusyWait (125);
/* Reset and flush the endpoint pipe. */
CyU3PDmaMultiChannelReset (&glDmaChHandleMulti);
apiRetStatus = CyU3PDmaMultiChannelSetXfer (&glDmaChHandleMulti, CY_FX_GPIFTOUSB_DMA_TX_SIZE, 0);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyU3PDebugPrint (4, "CyU3PDmaChannelSetXfer failed, Error code = %d\n", apiRetStatus);
CyFxAppErrorHandler(apiRetStatus);
}
CyU3PUsbFlushEp (CY_FX_EP_CONSUMER);
CyU3PUsbSetEpNak (CY_FX_EP_CONSUMER, CyFalse);
CyU3PBusyWait (125);
Finally use the API CyU3PGpifSMSwitch () to switch to the start state.
Please try the above and let me know if you find any improvement.
Jayakrishna
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I tested that out and there was no change. I still get 6 old buffers at the start of the new acquisition.
One thing I have in my notes from a while back is that calling "CyU3PUsbStall" in my end acquisition function would prevent left over data from persisting into a future instance (for example, if the program chooses to end the acquisition early). I am not sure if that is safe here however.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
It looks like the data is stuck at the host side. Can you please try calling Abort() for the endpoint from the host side when the application is started? Please let me know if there is a difference after trying this out.
Jayakrishna
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I added:
USBDevices[devices]->Open(fx3List[j]);
USBDevices[devices]->BulkInEndPt->Abort();
To the beginning of my program but I still see 6 extra buffers on the next run. I will try further variations of this tomorrow, need to get some sleep for now.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Can you please share the source code of the firmware project? We want to know when USB/DMA flush is done.
Jayakrishna
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Please let me know if you receive a CLEAR FEATURE request on the firmware side the host application is closed.
The clear feature request can be handled in the following way
switch (bmReqType)
{
case CY_U3P_USB_TARGET_ENDPT:
if (bRequest == CY_U3P_USB_SC_CLEAR_FEATURE)
{
if (wIndex == CY_FX_EP_BULK_VIDEO)
{
/* Windows OS sends Clear Feature Request after it stops streaming,
CyU3PDebugPrint (4, "Clear feature request detected...\r\n");
/* Clear the stall condition and sequence numbers. */
CyU3PUsbStall (CY_FX_EP_BULK_VIDEO, CyFalse, CyTrue);
CyFxApplnStop ();
uvcHandleReq = CyTrue;
/* Complete Control request handshake */
CyU3PUsbAckSetup ();
}
You can refer to AN75779 firmware for the handling of clear feature request
Rashi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I added:
if(bRequest == CY_U3P_USB_SC_CLEAR_FEATURE)
CyU3PDebugPrint (4, "Received a clear feature request! \r\n\r\n");
To CyFxApplnUSBSetupCB but the message never prints when the app is closed. Stale data is then returned on the next run anyway.
In further testing, the clear feature request is transmitted if the program calls "exit()" in Windows, but not if it crashes or is manually closed by the user.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
After some more experimentation, I can generate the clear request using: BulkInEndPt->Reset() (instead of Abort). On the FX3 this calls a similar sequence of commands as recommended above:
CyU3PDmaMultiChannelReset (&glDmaChHandleMulti);
CyU3PUsbFlushEp(CY_FX_EP_CONSUMER);
CyU3PUsbResetEp (CY_FX_EP_CONSUMER);
CyU3PDmaMultiChannelSetXfer (&glDmaChHandleMulti, CY_FX_GPIFTOUSB_DMA_TX_SIZE, 0);
CyU3PUsbStall (wIndex, CyFalse, CyTrue);
Nonetheless this seems to very reliably flush all stale data, whereas calling it before I start the GPIF does not, so there must be some subtle difference. Therefore I think my solution is to call BulkInEndPt->Reset() anytime I am not sure about the FX3 state.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Thank you for confirming that the handling clear feature helped in clearing the DMA channel.
To call BulkInEndPt->Reset() independently , following sequence can be followed
CyU3PUsbStall (wIndex, CyFalse, CyTrue);
CyU3PGpifDisable (CyFalse);
CyU3PUsbSetEpNak (CY_FX_EP_BULK_VIDEO, CyTrue);
CyU3PBusyWait (125);
CyU3PDmaMultiChannelReset (&glDmaChHandleMulti);
CyU3PUsbFlushEp (CY_FX_EP_BULK_VIDEO);
CyU3PUsbSetEpNak (CY_FX_EP_BULK_VIDEO, CyFalse);
CyU3PBusyWait (125);
Please let me know if this works.
If the host app is closed/stopped completely, then maybe we can disable the GPIF state machine and put the DMA channel in the reset state. CyU3PDmachannelSetXfer puts the DMA channel in active state
Rashi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, that does not work. The call to BulkInEndPt->Reset() must still happen or the stale data is not actually flushed.
Edit: No I am wrong. I copied the code as is, but wIndex was set to 0 instead of the actual endpoint I was trying to remove the stall from.
CyU3PUsbStall (CY_FX_EP_CONSUMER, CyFalse, CyTrue);
Returns API success, but then the next transfer times out when i restart the DMA channel.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I recorded some wireshark traces with the above, and it really does seem that the FX3 sends the wrong data (not just that the Windows USB stack holds onto old data):
As you can see the DMA transfer number in wireshark also read 3551 on the first USB packet sent over the wire (should read 1 if data is new).
I'm still not sure why CyU3PUsbStall (CY_FX_EP_CONSUMER, CyFalse, CyTrue) causes bulk transfers to fail. If I comment it out, stale data is sent. If I leave it in, no data is ever sent. Here is my code, maybe I am missing something? https://pastebin.com/8P663wjW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Thank you for the update.
The firmware link is not accessible. Please share the .zip file with the post.
Can you also share the snippet of the host application where BulkInEndPt->Reset() is called
Rashi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm attaching an updated zip (the one used for the wireshark capture above).
To workaround this problem I call reset() like this on program start:
USBDevices[0] = new CCyUSBDevice(NULL);
USBDevices[0]->Open(fx3IndexList[0]);
USBDevices[0]->BulkInEndPt->Reset();
That is enough to flush out any old data from the device.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
To understand the flow of the application, please share the UART debug prints when the issue is seen. Also, please share the associated USB traces using Wireshark
Rashi
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
Please refer to this thread Solved: CyU3PUsbSendEP0Data corrupts bulk DMA to host - Infineon Developer Community
Rashi