MANY_TO_ONE with FX3 ARM as consumer?

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

cross mob
Anonymous
Not applicable
        Good afternoon, I have an FX3 design with a 32-bit, 100MHz GPIF interface. In this particular application the GPIF interface is receiving data from an external FPGA (one direction, FPGA -> FX3 only). Before I work on the USB3 side of the design I would like to verify the GPIF interface data transfer. To do this I am trying to set up a multichannel DMA transfer to the CPU. The final product will be a multichannel DMA transfer from the GPIF interface to a USB IN endpoint. I see that there is CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE, but there is no multichannel MANUAL_IN variant which is the single-channel way of doing this. If I try to configure the consumer of the DMA data to the CPU (CY_U3P_CPU_SOCKET_CONS) CyU3PMultiDmaChannelCreate() returns error 64. To get around this I have set up the consumer socket ID to the first USB consumer socket (CY_U3P_UIB_SOCKET_CONS_0) and in the DMA handler callback, I just discard the DMA data instead of committing it. My DMA setup is otherwise textbook: size = 16384; CyU3PMemSet((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg)); dmaCfg.size = size; dmaCfg.count = 4; dmaCfg.prodSckId[0] = CY_U3P_PIB_SOCKET_0; dmaCfg.prodSckId[1] = CY_U3P_PIB_SOCKET_1; dmaCfg.consSckId[0] = CY_U3P_UIB_SOCKET_CONS_0; dmaCfg.validSckCount = 2; dmaCfg.dmaMode = CY_U3P_DMA_MODE_BUFFER; dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_ERROR; dmaCfg.cb = gpif_dma_cb; apiRetStatus = CyU3PDmaMultiChannelCreate(&h_gpif_to_cpu, CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE, &dmaCfg); I then go and start an unlimited DMA transfer with the following calls (error checking removed for clarity): apiRetStatus = CyU3PDmaMultiChannelReset(&h_gpif_to_cpu); apiRetStatus = CyU3PDmaMultiChannelSetXfer(&h_gpif_to_cpu, 0, 0); This appears to work fine. I get 8 DMA producer callbacks, and I immediately discard the data in the callback handler: void gpif_dma_cb(CyU3PDmaMultiChannel *chHandle, CyU3PDmaCbType_t type, CyU3PDmaCBInput_t *input) { CyU3PReturnStatus_t apiRetStatus; switch(type) { case CY_U3P_DMA_CB_PROD_EVENT: apiRetStatus = CyU3PDmaMultiChannelDiscardBuffer(chHandle); break; /* ... remaining function code snipped for clarity ... */ } What happens after this is that I do not get any further callbacks. It's like the DMA buffers are stuck in "used" state even though I'm discarding them. If I reset the DMA channel and restart it, it works for another 8 transfers before getting stuck again. What is the correct way to perform multi channel DMA from the GPIF to the FX3 ARM? I'm sure I'm close.   
0 Likes
10 Replies
Anonymous
Not applicable
        ok that was crap, how does one write a properly-formatted message here?   
0 Likes
Anonymous
Not applicable

testing p tag

   
    testing div tag   
   

testing

   
one two three
pre tag   
0 Likes
Anonymous
Not applicable

It appears that the forums support plain old HTML. Trying again:

   

Good afternoon,

   

I have an FX3 design with a 32-bit, 100MHz GPIF interface. In this particular application the GPIF interface is receiving data from an external FPGA (one direction, FPGA -> FX3 only). Before I work on the USB3 side of the design I would like to verify the GPIF interface data transfer. To do this I am trying to set up a multichannel DMA transfer to the CPU. The final product will be a multichannel DMA transfer from the GPIF interface to a USB IN endpoint.

   

I see that there is CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE, but there is no multichannel MANUAL_IN variant which is the single-channel way of doing this. If I try to configure the consumer of the DMA data to the CPU (CY_U3P_CPU_SOCKET_CONS) CyU3PMultiDmaChannelCreate() returns error 64. To get around this I have set up the consumer socket ID to the first USB consumer socket (CY_U3P_UIB_SOCKET_CONS_0) and in the DMA handler callback, I just discard the DMA data instead of committing it.

   

My DMA setup is otherwise textbook:

   

   
 size = 16384;  CyU3PMemSet((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg));  dmaCfg.size = size;  dmaCfg.count = 4;  dmaCfg.prodSckId[0] = CY_U3P_PIB_SOCKET_0;  dmaCfg.prodSckId[1] = CY_U3P_PIB_SOCKET_1;  dmaCfg.consSckId[0] = CY_U3P_UIB_SOCKET_CONS_0;  dmaCfg.validSckCount = 2;  dmaCfg.dmaMode = CY_U3P_DMA_MODE_BUFFER;  dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_ERROR;  dmaCfg.cb = gpif_dma_cb;   apiRetStatus = CyU3PDmaMultiChannelCreate(&h_gpif_to_cpu, CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE, &dmaCfg);
   

   

I then go and start an unlimited DMA transfer with the following calls (error checking removed for clarity):

   

   
 apiRetStatus = CyU3PDmaMultiChannelReset(&h_gpif_to_cpu);  apiRetStatus = CyU3PDmaMultiChannelSetXfer(&h_gpif_to_cpu, 0, 0);
   

   

This appears to work fine. I get 8 DMA producer callbacks, and I immediately discard the data in the callback handler:

   

   
void gpif_dma_cb(CyU3PDmaMultiChannel *chHandle, CyU3PDmaCbType_t type, CyU3PDmaCBInput_t *input) {  CyU3PReturnStatus_t apiRetStatus;   switch(type) {  case CY_U3P_DMA_CB_PROD_EVENT:   apiRetStatus = CyU3PDmaMultiChannelDiscardBuffer(chHandle);   break;   /* ... remaining function code snipped for clarity ... */ }
   

   

What happens after this is that I do not get any further callbacks. It's like the DMA buffers are stuck in "used" state even though I'm discarding them. If I reset the DMA channel and restart it, it works for another 8 transfers before getting stuck again.

   

What is the correct way to perform multi channel DMA from the GPIF to the FX3 ARM? I'm sure I'm close.

0 Likes
Anonymous
Not applicable

 Hi, 

   

 

   

After the transfer of 8 packets (8 * 16k), is the data actually being driven from FPGA? I believe you are using Slave FIFO state machine in FX3. If so, is the right flag monitored from FPGA and is the data actually being driven? Is the appropriate flag changing status appropriately. 

   

 

   

Regards,

   

Gayathri

0 Likes
Anonymous
Not applicable
        Yes, the FPGA is sending data whenever the flags indicate that the FX3 can accept data. The issue does not appear to be on the FPGA side. I can see the flags on the FX3 indicate that the FIFO cannot accept data. Once I reset/restart the DMA subsystem the flags show that the FIFOs can once again accept data.   
0 Likes
Anonymous
Not applicable

 Hi,

   

 

   

You mean to say, initially the flags indicate as buffer not full. As soon as you transfer 8 * 16k packets, flag changes state to indicate that it is full. Even after discarding the data, the flag retains this state. Is this correct? Which flag are you using for this purpose? Can you post the code showing the channel creation, callback, socket - thread mapping ?

   

 

   

Regards,

   

Gayathri

0 Likes
Anonymous
Not applicable

Yes, that is correct:

   
    - initialize DMA and GPIF, flags indicate DMA buffers are available     - transfer 8 buffers (4 from each thread) from FPGA into FX3, flags indicate no buffers available     - callback is issuing CyU3DmaMultiChannelDiscardBuffer() each time     - flags do not reset to "buffer available" until CyU3PDmaMultiChannelReset() and CyU3PDmaMultChannelSetXfer() are called
   

the code is described below. Error checking has been removed for clarity. I am using UIB_SOCKET_CONS_0 as a "dummy" destination since there is no MANUAL_IN many-to-one transfer option, and in fact I get a setup error if I try to use the processor consumer ID.

   
 /* DMA setup */  size = 16384;  CyU3PMemSet((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg));  dmaCfg.size = size;  dmaCfg.count = 4;  dmaCfg.prodSckId[0] = CY_U3P_PIB_SOCKET_0;  dmaCfg.prodSckId[1] = CY_U3P_PIB_SOCKET_1;  dmaCfg.consSckId[0] = CY_U3P_UIB_SOCKET_CONS_0;  dmaCfg.validSckCount = 2;  dmaCfg.dmaMode = CY_U3P_DMA_MODE_BUFFER;  dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_ERROR;  dmaCfg.cb = gpif_dma_cb;   apiRetStatus = CyU3PDmaMultiChannelCreate(&h_gpif_to_cpu, CY_U3P_DMA_TYPE_MANUAL_MANY_TO_ONE, &dmaCfg);   /* set up continuous DMA transfer */  apiRetStatus = CyU3PDmaMultiChannelReset(&h_gpif_to_cpu);  apiRetStatus = CyU3PDmaMultiChannelSetXfer(&h_gpif_to_cpu, 0, 0);    /* DMA callback */ void gpif_dma_cb(CyU3PDmaMultiChannel *chHandle, CyU3PDmaCbType_t type, CyU3PDmaCBInput_t *input) {  CyU3PReturnStatus_t apiRetStatus;   switch(type) {  case CY_U3P_DMA_CB_PROD_EVENT:   apiRetStatus = CyU3PDmaMultiChannelDiscardBuffer(chHandle);   break;   /* ... remaining function code snipped for clarity ... */  }; }
   

My understanding is that CyU3PDmaMultiChannelDiscardBuffer() should free up the DMA buffer, but it does not appear to do so.

0 Likes

Hello,

   

did your issue ever get resolved? 

0 Likes
Anonymous
Not applicable

 Hi,

   

 

   

Please clarify which are the flags that you are monitoring from FPGA? What flags to correspond to which threads (like TH0_RDY etc). Also, let me know what status of the flag (high/ low) are you checking from FPGA for writing to FX3?

   

 

   

Regards,

   

Gayathri

0 Likes
Anonymous
Not applicable

I'm trying to achieve a similar outcome.

   

Cypress really needs to document how to do this.

0 Likes