FX3 GPIF with manual DMA callback

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

cross mob
jeti
Level 1
Level 1
First question asked Welcome!

Hi,

I have a FX3 firmware project with a working GPIF state machine configured with a manual DMA channel for GPIF to USB transfer (based on the sample cyfxgpiftousb).
The GPIF is able to produce  a data package (1030 byte) up to every 60 microseconds. The interval time is configurable by the firmware.
If the data is ready, the DMA callback function is called, where I change some bytes from the buffer (add a counter) and then commit it with CyU3PDmaChannelCommitBuffer.

Now I want to commit the data only when a special firmware flag is set, otherwise I want to discard the buffer with CyU3PDmaChannelDiscardBuffer and not transfer it to the PC.
But this is working only if the interval is set to several milliseconds.
If the interval is set to lower values, so that e.g. the DMA callback is called every 1 millisecond, the buffer discarding seems to take too long, and the callback will not be called after some passes.

My question, does the discarding really takes so long or is there is something wrong on my thoughts.

void GpifToUsbDmaCallback(CyU3PDmaChannel *chHandle, CyU3PDmaCbType_t type,
CyU3PDmaCBInput_t *input) {
int i;
CyU3PReturnStatus_t status;

if (type == CY_U3P_DMA_CB_PROD_EVENT)
{
if(input != NULL && input->buffer_p.count > 0)
{
if (boTintChanged)
{
comm_PutChar (ACK);
CyU3PDmaChannelDiscardBuffer (chHandle);
boTintChanged = CyFalse;
}
else if (boFetch)
{
// The first six byte contains data garbage from the ADC pipe
// so we can change the first 4 byte and include a counter...
input->buffer_p.buffer[0] = uiDataSignature;
input->buffer_p.buffer[1] = uiDataSignature>>8;
input->buffer_p.buffer[2] = uiDataSignature>>16;
input->buffer_p.buffer[3] = uiDataSignature>>24;
uiDataSignature++;

// ...and set the next two byte to zero (preserved for future usage)
input->buffer_p.buffer[4] = 0;
input->buffer_p.buffer[5] = 0;

CyU3PReturnStatus_t status = CyU3PDmaChannelCommitBuffer (chHandle, input->buffer_p.count, 0);
CyU3PDebugPrint(4, "GpifToUsbDmaCallback CyU3PDmaChannelCommitBuffer %d \r\n", status);
boFetch = CyFalse;
}
else
status = CyU3PDmaChannelDiscardBuffer (chHandle);
}
else
status = CyU3PDmaChannelDiscardBuffer (chHandle);
}

if (type == CY_U3P_DMA_CB_CONS_EVENT)
{
/* Data transfer has been started. Enable the LPM disable loop. */

}

CyU3PDebugPrint(4, "GpifToUsbDmaCallback Event %d empfangen \r\n", type);

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

Hello,

Please find my comments below:

But this is working only if the interval is set to several milliseconds.
If the interval is set to lower values, so that e.g. the DMA callback is called every 1 millisecond, the buffer discarding seems to take too long, and the callback will not be called after some passes.

>> Please let me know the return status of CyU3PDmaChannelDiscardBuffer when the issue is seen.

Also, we do not recommend to use blocking call like CyU3PDebugPrint inside the DMA callback. You can use events or global variable to check the return status of the API used in DMA callback

Regards,
Rashi

View solution in original post

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

Hello,

Please find my comments below:

But this is working only if the interval is set to several milliseconds.
If the interval is set to lower values, so that e.g. the DMA callback is called every 1 millisecond, the buffer discarding seems to take too long, and the callback will not be called after some passes.

>> Please let me know the return status of CyU3PDmaChannelDiscardBuffer when the issue is seen.

Also, we do not recommend to use blocking call like CyU3PDebugPrint inside the DMA callback. You can use events or global variable to check the return status of the API used in DMA callback

Regards,
Rashi
0 Likes