adding extra DMA to design

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

cross mob
E_521156
Level 4
Level 4
100 sign-ins 50 replies posted 50 sign-ins

Hi,
In USBToGPIF example, I want to add an extra memory between USB and GPIF instead of increase the existed memory.
In this example,  there is a CY_U3P_DMA_TYPE_AUTO( prod=CY_U3P_UIB_SOCKET_PROD_1 , cons=CY_U3P_PIB_SOCKET_0). I added a DMA before that and change this DMA as well. Now, I have 2 DMA back to back like:
first DMA:   CY_U3P_DMA_TYPE_AUTO,  prod = CY_U3P_UIB_SOCKET_PROD_1  , cons = CY_U3P_CPU_SOCKET_CONS,                                 notification = CY_U3P_DMA_CB_PROD_EVENT,  cb = DmaCallback

second DMA:   CY_U3P_DMA_TYPE_AUTO,  prod = CY_U3P_CPU_SOCKET_PROD,  cons = CY_U3P_PIB_SOCKET_0,
                             notification = 0,  cb = 0

I copy the data from the  fist to second DMA in DmaCallback., But when I add this extra DMA to my design, it doesn't work. and I lose the EP in CC.
What is the right way to add an extra memory between USB and GPIF?
Thanks


0 Likes
1 Solution
AliAsgar
Moderator
Moderator
Moderator
1000 replies posted 250 solutions authored 750 replies posted

Hello,

DMA channels cannot be configured as AUTO channels, if one of the sockets is CPU.
Please make the channel as a MANUAL_IN channel, when CPU is consumer socket and make the channel as MANUAL_OUT, when CPU is the producer socket.

Best Regards,
AliAsgar

View solution in original post

0 Likes
8 Replies
AliAsgar
Moderator
Moderator
Moderator
1000 replies posted 250 solutions authored 750 replies posted

Hello,

1. What exactly do you mean by "I want to add an extra memory between USB and GPIF instead of increase the existed memory"?

2. Could you share your firmware with us?

Best Regards,
AliAsgar

0 Likes
lock attach
Attachments are accessible only for community members.

Hi,
I need to store input data coming from USB in a separate memory, but I don't want to increase the size of existing memory. for this reason I added a DMA channel in series with the previous DMA. But it doesn't work. What is the best way to save data in another memory?

In USBToGPIF example, there is an auto DMA channel between prod = CY_U3P_UIB_SOCKET_PROD_1  and cons = CY_U3P_PIB_SOCKET_0. I wanted to add another DMA.
I did those changes in the attached FW, now there are glDmaChHandle0 and glDmaChHandle1, but it seems that it is not the correct way.

Thanks

0 Likes
AliAsgar
Moderator
Moderator
Moderator
1000 replies posted 250 solutions authored 750 replies posted

Hello,

DMA channels cannot be configured as AUTO channels, if one of the sockets is CPU.
Please make the channel as a MANUAL_IN channel, when CPU is consumer socket and make the channel as MANUAL_OUT, when CPU is the producer socket.

Best Regards,
AliAsgar

0 Likes

Hi,
Thanks for your reply.
I changed my code based on your comments. This example works fine.
But It doesn't work for a multi channel DMA.
I have another example, with a CY_U3P_DMA_TYPE_AUTO_ONE_TO_MANY channel, that I need to add extra DMA to it as well.
I added a MANUAL_IN channel before that and changed the second DMA to CY_U3P_DMA_TYPE_MANUAL_ONE_TO_MANY. but I got error in CyU3PDmaMultiChannelCreate.(the second DMA)

first DMA:

CyU3PMemSet ((uint8_t *)&dmaCfg0, 0, sizeof (dmaCfg0));
dmaCfg0.size = CY_FX_DMA_BUF_SIZE;
dmaCfg0.count = CY_FX_DMA_BUF_COUNT;
dmaCfg0.prodSckId = CY_FX_EP_PRODUCER_SOCKET0;
dmaCfg0.consSckId = CY_U3P_CPU_SOCKET_CONS;
dmaCfg0.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaCfg0.notification = CY_U3P_DMA_CB_PROD_EVENT;
dmaCfg0.cb = DmaCallback;
dmaCfg0.prodHeader = 0;
dmaCfg0.prodFooter = 0;
dmaCfg0.consHeader = 0;
dmaCfg0.prodAvailCount = 0;

apiRetStatus = CyU3PDmaChannelCreate (&glDmaChHandle0, CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg0);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyFxAppErrorHandler(apiRetStatus);
}

apiRetStatus = CyU3PDmaChannelSetXfer (&glDmaChHandle0, CY_FX_GPIFTOUSB_DMA_TX_SIZE);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyFxAppErrorHandler(apiRetStatus);
}

Second DMA:

/* Create a DMA AUTO channel for the USB to GPIF transfer. */
CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof (dmaCfg));
dmaCfg.size = CY_FX_DMA_BUF_SIZE;
dmaCfg.count = CY_FX_DMA_BUF_COUNT;
dmaCfg.validSckCount= 4;
// TODO: Producer/Consumer
dmaCfg.prodSckId[0] = CY_U3P_CPU_SOCKET_PROD;
// TODO: Producer/Consumer
dmaCfg.consSckId[0] = CY_FX_GPIF_CONSUMER_SOCKET0;//CY_U3P_PIB_SOCKET_0;
dmaCfg.consSckId[1] = CY_FX_GPIF_CONSUMER_SOCKET1;//CY_U3P_PIB_SOCKET_1;
dmaCfg.consSckId[2] = CY_FX_GPIF_CONSUMER_SOCKET2;//CY_U3P_PIB_SOCKET_2;
dmaCfg.consSckId[3] = CY_FX_GPIF_CONSUMER_SOCKET3;//CY_U3P_PIB_SOCKET_3;
dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
dmaCfg.notification = 0;
dmaCfg.cb = 0;
dmaCfg.prodHeader = 0;
dmaCfg.prodFooter = 0;
dmaCfg.consHeader = 0;
dmaCfg.prodAvailCount = 0;
// TODO: Producer/Consumer
apiRetStatus = CyU3PDmaMultiChannelCreate (&glDmaChHandle,CY_U3P_DMA_TYPE_MANUAL_ONE_TO_MANY , &dmaCfg);//CY_U3P_DMA_TYPE_AUTO_ONE_TO_MANY
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyFxAppErrorHandler(apiRetStatus);
}

apiRetStatus = CyU3PDmaMultiChannelSetXfer (&glDmaChHandle, CY_FX_GPIFTOUSB_DMA_TX_SIZE, 0);
if (apiRetStatus != CY_U3P_SUCCESS)
{
CyFxAppErrorHandler(apiRetStatus);
}

Thanks

0 Likes

Hi, 
As I mentioned, this solution doesn't work for a multi channel DMA(ONE_TO_MANY ) in my side.
Is there any workaround for that?
Thanks

0 Likes
AliAsgar
Moderator
Moderator
Moderator
1000 replies posted 250 solutions authored 750 replies posted

Hello,

A MANUAL channel is different from MANUAL_IN and MANUAL_OUT channel. The difference is that in MANUAL_IN and MANUAL_OUT channels, one of the sockets (either the consumer or the producer is the CPU). But in the case of a MANUAL channel, the sockets used in creating the channels are never CPU. But CPU (firmware) plays a role in obtaining and committing buffers based on the DMA callback events.
MANUAL_ONE_TO_MANY channels is a MANUAL channel and therefore should not have CPU as one of it sockets.

We recommend you to create one channel, with 

dmaCfg.prodSckID     = CY_FX_EP_PRODUCER_SOCKET0
dmaCfg.consSckId[0] = CY_FX_GPIF_CONSUMER_SOCKET0;//CY_U3P_PIB_SOCKET_0;
dmaCfg.consSckId[1] = CY_FX_GPIF_CONSUMER_SOCKET1;//CY_U3P_PIB_SOCKET_1;
dmaCfg.consSckId[2] = CY_FX_GPIF_CONSUMER_SOCKET2;//CY_U3P_PIB_SOCKET_2;
dmaCfg.consSckId[3] = CY_FX_GPIF_CONSUMER_SOCKET3;//CY_U3P_PIB_SOCKET_3;

Best Regards,
AliAsgar

0 Likes

Hi,
I already have that single multichannel DMA (dmaCfg) and it works.
I am looking for a way to add an extra DMA before that.
So no way for that if I use multichannel DMA, right?
Do you have any suggestion?
Thanks

0 Likes
AliAsgar
Moderator
Moderator
Moderator
1000 replies posted 250 solutions authored 750 replies posted

Hi,

For a multichannel DMA, ONE_TO_MANY in this case, one MANUAL_IN channel and multiple MANUAL_OUT channels can be created. 
The getbuffer and commitbuffer APIs must be handled appropriately in the firmware.

Best Regards,
AliAsgar

0 Likes