Fx3 Write transfer

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.
MaMa_4520856
Level 4
Level 4
25 replies posted 25 sign-ins 10 replies posted

Hello,

When I'm trying to write data to Fx3 device from a FPGA device, I always get zero-lengh data transfer despite buffer being full (I know it is full base on the state of DMA flags). I noticed strange behavior of my RDY signal in a middle of a transfer it goes low for some reason and after few clock cycles it goes high (as it should be)

MaMa_4520856_0-1620404894026.png

 

 

 

 

 

 

 

In attachment i'm sending you firmware which I use and state machine from GPIF designer

regards,

Mateusz

0 Likes
1 Solution

Hello Mateusz,

Thank you for confirming that you are using the AUTO DMA channel in the firmware.

From the firmware, I noticed that DMA buffer size used is 1024 as LOOPBACK_SHRT_ZLP is enabled. And the DATA counter value set in the GPIF state machine is 256 (0-255) which will read 256 * 2 (16bits) = 512 bytes of data.

So, once the 512 bytes of data is read by the GPIF (i.e. DATA_CNT_HIT will be triggered), the RDY signal will be  deasserted. If the RDY signal is expected to be HIGH for whole transfer i.e. 1024 bytes writing to FX3, then LD_DATA_COUNT should be set 511 instead of 255

LD_DATA_COUNT.PNG

DATA_COUNT_HIT.png 

 

Please let me know if further queries on this

Regards,
Rashi

View solution in original post

0 Likes
8 Replies
JayakrishnaT_76
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hello,

As per my understanding, you are trying to write data from FPGA to FX3 and read the data at the host end through Isochronous endpoint. Please let me know if my understanding is not correct.

After referring to the firmware, I find that the callback function CyFxSlFifoPtoUDmaCallback() will be invoked when a producer event is received for the P to U channel. But, inside this callback function, a hard reset is done by calling the API CyU3PDeviceReset(). Can you please let us know if the project shared is the latest one or not? Also, please make the following modification inside the callback function CyFxSlFifoPtoUDmaCallback () and let us know the result:

void
CyFxSlFifoPtoUDmaCallback (
        CyU3PDmaChannel   *chHandle,
        CyU3PDmaCbType_t  type,
        CyU3PDmaCBInput_t *input
        )
{
    CyU3PDmaBuffer_t buf_p;
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
    if (type == CY_U3P_DMA_CB_PROD_EVENT)
       {

    		status = CyU3PDmaChannelGetBuffer(chHandle, &buf_p, CYU3P_NO_WAIT);
            	if(status == CY_U3P_SUCCESS)
                {
                  status = CyU3PDmaChannelCommitBuffer (chHandle, buf_p.count, 0);
                }
       }
}


In addition to this, please track the size of the DMA buffer received by FX3 from FPGA.

Best Regards,
Jayakrishna
0 Likes

Hello,

>>As per my understanding, you are trying to write data from FPGA to FX3 and read the data at the host end through Isochronous endpoint. Please let me know if my understanding is not correct.

yes that is correct.

>>Can you please let us know if the project shared is the latest one or not?

Yes it is latest one, it is based on AN65974 firmware,I changed endpoint types to Isochronous

 

I changed CyFxSlFifoPtoUDmaCallback() function as follows:

 

 

void
CyFxSlFifoPtoUDmaCallback (
        CyU3PDmaChannel   *chHandle,
        CyU3PDmaCbType_t  type,
        CyU3PDmaCBInput_t *input
        )
{
    CyU3PReturnStatus_t status = CY_U3P_SUCCESS;
    CyU3PDmaBuffer_t buf_p;

    if (type == CY_U3P_DMA_CB_PROD_EVENT)
    {
        /* This is a produce event notification to the CPU. This notification is 
         * received upon reception of every buffer. The buffer will not be sent
         * out unless it is explicitly committed. The call shall fail if there
         * is a bus reset / usb disconnect or if there is any application error. */
    	status = CyU3PDmaChannelGetBuffer(chHandle, &buf_p, CYU3P_NO_WAIT);
    	if (status == CY_U3P_SUCCESS){

    		status = CyU3PDmaChannelGetBuffer(chHandle, &buf_p, CYU3P_NO_WAIT);

			if (status != CY_U3P_SUCCESS)
			{
				CyU3PDebugPrint (4, "CyU3PDmaChannelCommitBuffer failed, Error code = %d\n", status);
			}
    	}
        /* Increment the counter. */
        glDMATxCount++;

    }
}

 

 

After this change it still works as it has been before. This function is never called because I use AUTO DMA Channel creation

Regards,

Mateusz



0 Likes

Hello Mateusz,

Thank you for confirming that you are using the AUTO DMA channel in the firmware.

From the firmware, I noticed that DMA buffer size used is 1024 as LOOPBACK_SHRT_ZLP is enabled. And the DATA counter value set in the GPIF state machine is 256 (0-255) which will read 256 * 2 (16bits) = 512 bytes of data.

So, once the 512 bytes of data is read by the GPIF (i.e. DATA_CNT_HIT will be triggered), the RDY signal will be  deasserted. If the RDY signal is expected to be HIGH for whole transfer i.e. 1024 bytes writing to FX3, then LD_DATA_COUNT should be set 511 instead of 255

LD_DATA_COUNT.PNG

DATA_COUNT_HIT.png 

 

Please let me know if further queries on this

Regards,
Rashi
0 Likes

Hello Rashi,

As per my understanding changing LD_DATA_COUNT  should solve this rdy going low in middle of transfer. I mention before when I try send this data using USB Control Center despite buffer being full (both flags A and B asserted) I always get zero-lenght data transfer. It looks like it at least tried to send data because after this flags became de-asserted. Can you help me with this?

Regards,

Mateusz

0 Likes

Hello Mateusz,

Please change the DMA channel to CY_U3P_DMA_TYPE_AUTO_SIGNAL and register for DMA call back with CY_U3P_DMA_CB_PROD_EVENT and CY_U3P_DMA_CB_CONS_EVENT events registered. 

In the DMA callback use global variable to track the events. If the DMA buffer is fully filled by the PIB CY_U3P_DMA_CB_PROD_EVENT will be triggered and is USB socket consumes data CY_U3P_DMA_CB_CONS_EVENT will be triggered. Please use global variables like glDMATxCount/glDMARxCount to track the events and print the values in SlFifoAppThread_Entry as done in your current project.

 

Regards,
Rashi
0 Likes

Hello Rashi,

I've done as you asked. RDY signal is now high for a whole transfer but I spotted strange behaviour of a buffer, it goes low after finishing transfer indicating that buffer is full, then after few clock cycle it goes high(I didn't try to empty buffer). see screen below.

A is full flag, B partial full flag

MaMa_4520856_0-1621869794674.png

Changes I did in DMA channel creation (changed type in CyU3PDmaChannelCreate(); and modified dmaCfg.notification):

/* Create a DMA AUTO channel for U2P transfer.
       DMA size is set based on the USB speed. */
    dmaCfg.size  = DMA_BUF_SIZE* size;
    dmaCfg.count = CY_FX_SLFIFO_DMA_BUF_COUNT_U_2_P;
	dmaCfg.prodSckId = CY_FX_PRODUCER_USB_SOCKET;
    dmaCfg.consSckId = CY_FX_CONSUMER_PPORT_SOCKET;
    dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
    /* Enabling the callback for produce event. */
    dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT |  CY_U3P_DMA_CB_CONS_EVENT;
    dmaCfg.cb = NULL;
    dmaCfg.prodHeader = 0;
    dmaCfg.prodFooter = 0;
    dmaCfg.consHeader = 0;
    dmaCfg.prodAvailCount = 0;

    apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoUtoP,
               CY_U3P_DMA_TYPE_AUTO_SIGNAL, &dmaCfg);
    if (apiRetStatus != CY_U3P_SUCCESS)
    {
       CyU3PDebugPrint (4, "CyU3PDmaChannelCreate failed, Error code = %d\n", apiRetStatus);
       CyFxAppErrorHandler(apiRetStatus);
    }

    /* Create a DMA AUTO channel for P2U transfer. */
    dmaCfg.size  = DMA_BUF_SIZE*size; //increase buffer size for higher performance
    dmaCfg.count = CY_FX_SLFIFO_DMA_BUF_COUNT_P_2_U; // increase buffer count for higher performance
    dmaCfg.prodSckId = CY_FX_PRODUCER_PPORT_SOCKET;
    dmaCfg.consSckId = CY_FX_CONSUMER_USB_SOCKET;
    dmaCfg.cb = NULL;
    apiRetStatus = CyU3PDmaChannelCreate (&glChHandleSlFifoPtoU,
               CY_U3P_DMA_TYPE_AUTO_SIGNAL, &dmaCfg);

Regards,

Mateusz

0 Likes

Hello Mateusz,

For a particular DMA channel there are some DMA buffers associated. In your case, the DMA buffer count is CY_FX_SLFIFO_DMA_BUF_COUNT_P_2_U/CY_FX_SLFIFO_DMA_BUF_COUNT_U_2_P. The DMA flags will indicate the status of these DMA buffers. If one DMA buffer is filled with data, the DMA descriptors will point the next DMA buffer for filling the data and hence the DMA flags will indicate the status of the next DMA buffer which is to be filled next.

Regards,
Rashi
0 Likes

Hello,

There is still problem with zero-lenght data transfer.

Despite buffer being full (indicated by flag A is 0) I receve zero-lenght data transfer. To transfer and receive data I usbe USB Control Center.

Regards,

Mateusz

0 Likes