Flush DMA data between acquisitions on FX3

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
mgiacomelli
Level 3
Level 3
25 replies posted 10 questions asked 25 sign-ins

I have implemented a working GPIF state machine that captures N individual lines of data, with one DMA buffer the size of one line.  At the end of acquisition, the state machine loops indefinitely at the final state waiting for a vendor command to reset the acquisition for a new frame.

I've been struggling with commiting/flushing data however.  I'll either get the last line of one acquisition prepended to the start of the next, or the current acquisition never completes (Begin/Wait/FinishDataXfer will time out), depending on the size of the acquisition. 

Things that are unclear to me:

1)  Do I need to flush  at the end state of the GPIF if I've made sure to capture exactly one buffer of data?  It seems like if I don't flush I may or may not get data returned.  

2)   I'm really confused about the remark in the reference manual saying that I need to read data while doing a commit to avoid a zero length packet.  I tried this (forcing the acquisition to end with a half full buffer), and without it the acquisition did not return data. With the read data it did, but I get one extra sample.  Is that expected?   

3)  For CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE, is the callback called during the FLUSH state?  Or only when the buffer is actually full?

0 Likes
1 Solution
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello,

If the DMA buffer is full, then commit action need not be used in the GPIF state with IN_DATA

If the DMA buffer is partially filled, then  while sampling last data word commit action should be called along with IN_DATA to commit the partial buffer (short packet)

If only commit action is called in a state ZLP (empty buffer) will be committed.

As this is a multi threaded (gpif threads) application,  the DMA buffer from the GPIF sockets are expected to be committed in ping pong manner. So please check the thread number (in the action settings) is as expected  when the commit action  is called 

When the commit action is executed by the GPIF State machine, a producer event will be triggered (provided that the event is registered in the DMA channel configuration) in the DMA callback and the DMA buffer needs to be committed to the USB socket.

Regards,
Rashi

View solution in original post

0 Likes
4 Replies
Rashi_Vatsa
Moderator
Moderator
Moderator
5 likes given 500 solutions authored 1000 replies posted

Hello,

If the DMA buffer is full, then commit action need not be used in the GPIF state with IN_DATA

If the DMA buffer is partially filled, then  while sampling last data word commit action should be called along with IN_DATA to commit the partial buffer (short packet)

If only commit action is called in a state ZLP (empty buffer) will be committed.

As this is a multi threaded (gpif threads) application,  the DMA buffer from the GPIF sockets are expected to be committed in ping pong manner. So please check the thread number (in the action settings) is as expected  when the commit action  is called 

When the commit action is executed by the GPIF State machine, a producer event will be triggered (provided that the event is registered in the DMA channel configuration) in the DMA callback and the DMA buffer needs to be committed to the USB socket.

Regards,
Rashi
0 Likes

OK then I am handling commit correctly (skip if buffer is full, COMMIT + IN_DATA if buffer is not full at end).  

I tested a little more and I think my confusion may be related to how Begin/Wait/FinishDataXfer works.  If I begin a transfer and then wait, does it wait until length bytes are available instead of returning less if that is all that is there?  So for example, if I do:

length = 128*1024;
BulkInEndPt->BeginDataXfer(inBuf, length, &inOvLap);
BulkInEndPt->WaitForXfer(&inOvLap,100);
BulkInEndPt->FinishDataXfer(inBuf, length, &inOvLap, inContext);

 

And on the GPIF side I COMMIT a 64KB buffer during that time period, the WaitForXfer will time out (length bytes not available) and the FinishDataXfer will return zero bytes (not the 64KB that are available)?  Basically, length is the minimum that must be returned and not the maximum?  

0 Likes

Hello,

And on the GPIF side I COMMIT a 64KB buffer during that time period, the WaitForXfer will time out (length bytes not available) and the FinishDataXfer will return zero bytes (not the 64KB that are available)? 

>> To check the DMA buffer status, please register for the producer and consumer events in the DMA channel config structure and track the producer and consumer events using a global variable and print the values in the for loop. Please note that it is not recommended to call CyU3PDebugPrint inside DMA callback.

Please let me know the size and count of DMA buffer used for Manual many to one channel

Please share the UART debug prints when the problem is seen.

//registering for events

dmaMultiConfig.notification = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;
dmaMultiConfig.cb = CyFxUvcApplnDmaCallback;
apiRetStatus = CyU3PDmaMultiChannelCreate (&glChHandleUVCStream, CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE,
&dmaMultiConfig);

//tracking prod and cons events
CyFxUvcApplnDmaCallback (
CyU3PDmaMultiChannel *chHandle,
CyU3PDmaCbType_t type,
CyU3PDmaCBInput_t *input
)
{
CyU3PDmaBuffer_t dmaBuffer;
CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
if (type == CY_U3P_DMA_CB_PROD_EVENT)
{
prod++; //global variable
..... //rest of the code
}
if (type == CY_U3P_DMA_CB_CONS_EVENT){
cons++; //global variable
}}
// printing value
for (;;)
{
CyU3PDebugPrint (4, " buffer received = %d, buffer transferred = %d",prod,cons);
...}

 

- As the timeout error is seen, please let me know if there is some improvement on increasing the timeout period and also confirm if beginxfer API is executed successfully.

in the event of an error condition, is there is someway to completely flush all pending data (both in the GPIF buffers, data waiting at the USB controller, and any data buffered by the host but not yet collected by Begin/Wait/FinishDataXfer) to ensure that no stale data is returned upon recovering the device?  

>> You can refer to AN75779 firmware where CyFxUvcApplnStop is called to stop and clear the DMA channel. Similar implementation can be done when error condition is seen.

Please let me know how will the firmware be detecting the error condition. Only if detects the error correctly the data can be flushed. Please share the UART debug prints for us to check the cause of the error and later we can add the handling of the error.

Regards,
Rashi
0 Likes

A related question:  in the event of an error condition, is there is someway to completely flush all pending data (both in the GPIF buffers, data waiting at the USB controller, and any data buffered by the host but not yet collected by Begin/Wait/FinishDataXfer) to ensure that no stale data is returned upon recovering the device?  

 

I tried running CyU3PUsbFlushEp (CY_FX_EP_CONSUMER) on the device before each acquisition, but if I intentionally collect data using the GPIF, commit it, but do not do a large enough Begin/Wait/FinishDataXfer to copy it all, the remainder still be there when I restart my acquisition program on the host.  I thought quitting the host  program and relaunching it would clear the CyUSB driver buffers, but maybe not?

0 Likes