I have a manual single DMA channel which is dealing with multiple small packets, one at a time. After committing the buffer, the data arrives at the host just fine.
However, I cannot start a new DMA transfer because the previous one is ACTIVE indefinitely.
The setup is:
dmaCfg.size = 96; // Multiple of 32 required
dmaCfg.count = 192; // 256 seems to crash? Not sure why, should be plenty of memory?
dmaCfg.prodSckId = CY_U3P_PIB_SOCKET_0;
dmaCfg.consSckId = CY_U3P_UIB_SOCKET_CONS_1
dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaCfg.prodHeader = 16; // Multiple of 16 required
dmaCfg.notification = 0xffff; // I'll take anything
dmaCfg.cb = funcCallback;
CyU3PDmaChannelCreate(&handle, CY_U3P_DMA_TYPE_MANUAL, &dmaCfg);
In my callback, I get a CY_U3P_DMA_CB_PROD_EVENT:
CyU3PDmaChannelGetBuffer(&handle, &bufp, CYU3P_NO_WAIT);
CyU3PMemCopy(bufp.buffer - 16, &header, 16);
CyU3PDmaChannelCommitBuffer(&handle, bufp.count + 16, 0);
CyU3PEventSet(&glEvents, PROD_COMPLETE_EVENT, CYU3P_EVENT_OR);
Then, in my event handler, I try to queue up my next packet by waiting for the transfer to complete.
But it never completes. The state is ACTIVE forever.
Is there a better way to handle multiple manual transfers? I'm sure I could completely reset & abort, but that seems like overkill.
1. How fast is the host reading the data from the endpoint?
2. You could try queueing up your next packet when a CONSUME event is seen instead of using the WaitForCompletion API.
3. Also I could notice that the SetXfer size is 80. But the buffer size is 96. Why is that?
1) The host is reading it "instantly" (i.e. no perceptible delay from when I commit the buffer to the host receiving it). The FX3 is reading at 4MHz on a synchronous 16-bit GPIF interface. On infinite block transfers, this works great at many times this speed, it's just this byte-mode (or small packets) that's causing an issue.
2) I actually don't get any other events. I get one PROD event, I commit the buffer, and then I never see any more callbacks.
3) Buffer size is 96 to leave 16 bytes for prodHeader.
Thanks for your questions!
When setXfer is set to 80 and if 80 bytes of data are sent and received, XFER_CPLT DMA callback event comes and the setXfer can again be called here inside the DMA callback function to activate the channel again. We tried this implementation at our end and it worked fine. Please do try this and let us know if you have any more queries.
Could there be an issue with the USB Descriptor (burst length? Max packet size?) or the CyU3PSetEpConfig() which is causing this odd behavior? I have a superspeed descriptor with a max burst length of 15, max packet size of 1024, and I'm connected with superspeed. I don't understand how these parameters interact with a smaller DMA packet size.
Some more surprising experiments:
1) With a buffer size of 96 and count of 192, in MODE_BYTE, I set up a transfer of 80. I get 87(!) PROD messages for different buffers (all then committed), and not a single XFER_CPLT. This doesn't make sense, I should have gotten at most a single PROD.
2) Same setup, but in MODE_BUFFER, I setup a transfer of 1. I got 150 PROD messages for different buffers, and no XFER_CPLT. Again, at most, should have gotten 1 PROD.
3) Size of 4096, count of 4, MODE_BUFFER, I setup a transfer of 1. I got 2 PROD messages (the second failed CyU3PDmaChannelGetBuffer) and a XFER_CPLT.
Is there a sample code which does small MANUAL transfers from GPIF to USB? I just can't find what I'm doing wrong (and this code works reliably well in large buffer MANUAL and AUTO modes).
If you create 192 buffers @ 96 bytes, can you transfer just one from GPIF to USB and get a single PROD message?