GPIF with many to one DMA for transfer doesn't work as expected

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

cross mob
lock attach
Attachments are accessible only for community members.
Marc_O
Level 1
Level 1
5 sign-ins First solution authored First like received

Hi,

I'm having issues with my design when sending data to the USB (this is my continuity from my first post "GPIFII Slave FIFO Read Sequence doesn't work."). I based my design on the AN87216 exemple, which the documentation by the way was very good!

However, I want now to make this design work with the AUTO_MANY_TO_ONE DMA transfert. I look at a lot of exemple including the  "Design by example" from John Hyde but I am still not able to get it work properly.

I put my design in the attachments but here is the image of my GPIF state machine:

Marc_O_0-1626839539737.png

Some background, my FX3 is connected to a FPGA which provide him with data as well as retrieving the command from the USB-IN endpoint. You can see the USB-IN states on the left side.

My issues are with the right-hand side where the transfert states are. I changed the DMA channel for the P2U of AN87216 to be of "CY_U3P_DMA_TYPE_AUTO_MANY_TO_ONE".

My test right now is that I send 1023 * 32-bits (the size of my DQ input). I send a command to the FPGA to send the data and I'm able to confirm from the waves that the FX3 reads all the data. However, when I click on "Transfer Data-In" in the USB Control Center, I do not get all of the data. I click 3 times before I got no more data even though there are more. And my data are not in order. I get the first 1024 (32bits) but then the next I receive are those that I should get later.

For example:

Transfer Data-Out -> Send command to receive  1023 * 32bits

Transfer Data-In -> I receive the ack

Transfer Data-In -> Zero length packet, I do not know why

Transfer Data-In -> Zero length packet, I do not know why

Transfer Data-In -> First 256 32bits counter: 0x00A to 0x108

Transfer Data-In -> Second 256 32bits counter: 0x109 to 0x208

Transfer Data-In -> failed with Error Code:997 (no more data)

What is strange in this case is that, if I send a dummy command just to receive an ack, I will receive the rest of my data:

Transfer Data-Out -> Send dummy command

Transfer Data-In -> Dummy command ack

Transfer Data-In -> Third 256 32bits counter: 0x24B to 0x34A (I miss 2 count here)

Transfer Data-In -> Last 256 32bits counter: 0x34B to 0x3FF

Also, I put a trace in the state machine to know when I was on which thread of the GPIF so that I can see with the FPGA if the change was done, and I can confirm that there is a switching:

Marc_O_1-1626841062408.png

 

I'm out of option right now, I do not see what I'm doing wrong in my settings in order not to receive all my data and why they do not always come in order of sending from the FPGA. I tried to follow the example as best as I could and in the FX3 book... it seems to be very easer adding the many_to_one!!

Thanks a lot in advance

 

 

 

 

 

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

EDITED:

Hello,

After going through the GPIF state machine, I observed that COMMIT ACTION is called in GPIF states. Please refer to Errata 3 of the FX3 datasheet. IN_DATA action should be called along with COMMIT action to avoid zero length packets. 

Also, I see that transition between READ_0 and READ_1 state doesn't include checking of the DMA buffer of particular thread is ready. We would recommend to add a dummy state between READ_0 and READ_1 to check DMA_RDY_TH1/DMA_RDY_TH0 before sampling the data (using IN_DATA)

From the GPIF state machine, I understand that LD_DATA_COUNT and LD_ADDR_COUNT counter are set to value 2048. 

The counter values should be : DMA buffer size (bytes)/ bus width (bytes) - 1. So, the counter values should be 511 instead of 2048 when DMA buffer size is 2048.

Regards,
Rashi

View solution in original post

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

EDITED:

Hello,

After going through the GPIF state machine, I observed that COMMIT ACTION is called in GPIF states. Please refer to Errata 3 of the FX3 datasheet. IN_DATA action should be called along with COMMIT action to avoid zero length packets. 

Also, I see that transition between READ_0 and READ_1 state doesn't include checking of the DMA buffer of particular thread is ready. We would recommend to add a dummy state between READ_0 and READ_1 to check DMA_RDY_TH1/DMA_RDY_TH0 before sampling the data (using IN_DATA)

From the GPIF state machine, I understand that LD_DATA_COUNT and LD_ADDR_COUNT counter are set to value 2048. 

The counter values should be : DMA buffer size (bytes)/ bus width (bytes) - 1. So, the counter values should be 511 instead of 2048 when DMA buffer size is 2048.

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

Thank you very Rashi for your quick respond!

I did the correction on the "COMMIT" state as you mention according to the Errata and now, I do not have anymore "zero length packet".

However, I'm still having the  issue where I do not get all my packets. It seems like the DMA channel, even though in Auto mode, do not commit all buffer. As I describe in my first post, I need to send another dummy command (that send a ack) in order to receive the remaining packet of the first command. And what is strange is that the "ack" is receive before the rest of the previous data...

I must say also that I base my modification of the original AN87216 on the AN75779 (which has a multichannel DMA). From that, I was expecting to get the same as in the documentation where socket 0 and socket 1 alternate and the USB socket sends it in order:

Marc_O_0-1626919764467.png

But I do not have this behaviour. I setup my multiDMA like this:

CyU3PMemSet((uint8_t *)&dmaMultiConfig, 0, sizeof(dmaMultiConfig));
dmaMultiConfig.size           = 2048;
dmaMultiConfig.count          = 8;
dmaMultiConfig.validSckCount  = 2;
dmaMultiConfig.prodSckId[0]   = CY_U3P_PIB_SOCKET_0;
dmaMultiConfig.prodSckId[1]   = CY_U3P_PIB_SOCKET_1;
dmaMultiConfig.consSckId[0]   = CY_U3P_UIB_SOCKET_CONS_1;
dmaMultiConfig.dmaMode        = CY_U3P_DMA_MODE_BYTE;
dmaMultiConfig.notification   = 0;
dmaMultiConfig.cb             = NULL;
dmaMultiConfig.prodHeader     = 0;
dmaMultiConfig.prodFooter     = 0;
dmaMultiConfig.consHeader     = 0;
dmaMultiConfig.prodAvailCount = 0;

apiRetStatus = CyU3PDmaMultiChannelCreate(&glDualGPIF2USB_Handle, CY_U3P_DMA_TYPE_AUTO_MANY_TO_ONE, &dmaMultiConfig);
apiRetStatus = CyU3PDmaMultiChannelSetXfer(&glDualGPIF2USB_Handle, CY_FX_DMA_TX_SIZE, 0);

 

Am I missing something in order to get the DMA commit correctly? My GPIF counter is set to the same size as the DMA (2048) to count before switching socket thread. This is my new state machine:

Marc_O_1-1626920076048.png

 

I put again my updated design in attachment.

Thank you again in advance for your time!

Marc-O

 

 

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

Hello Marc_O,

From the GPIF state machine, I understand that LD_DATA_COUNT and LD_ADDR_COUNT counter are set to value 2048. 

The counter values should be : DMA buffer size (bytes)/ bus width (bytes) - 1. So, the counter values should be 511 instead of 2048 when DMA buffer size is 2048.

Please make this modification and let me know the results

Regards,
Rashi
0 Likes