You are here

Failed to get buffer after first FX3->PC DMA transfer, and DMA unable to run in CyFxGpifCB | Cypress Semiconductor

Failed to get buffer after first FX3->PC DMA transfer, and DMA unable to run in CyFxGpifCB

Summary: 2 Replies, Latest post by CHLI on 10 Jan 2017 05:42 PM PST
Verified Answers: 0
Last post
Log in to post new comments.
lis_user1's picture
32 posts

I use a DMA to transfer from FX3 to PC and libUSB driver. I have two problems now. 

1) I noticed the IN endpoint only receives 1 transfer at PC then refuse to CyU3PDmaChannelGetBuffer. I can verify the received transfer is correct. In a multi-DMA IN EP, I could get 7 transfers before CyU3PDmaChannelGetBuffer fails. I believe the two issues share the same root cause. 

2) I would rather like to have the FPGAInterrupt to be called directly from CyFxGpifCB(), but it seems not working. I had to create a thread to poll for FPGA_Intr_called status and emulate an interrupt. 


Source segments below. 

void FPGAInterrupt()
    CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS;
    CyU3PDebugPrint(CY_FX_DEBUG_PRIORITY, "FPGAInterrupt() called \r\n");

    apiRetStatus = CyU3PDmaChannelGetBuffer (&glChHandleUVCControlIN, &buf_p_1, CYU3P_NO_WAIT);
    if (apiRetStatus != CY_U3P_SUCCESS) {
        CyU3PDebugPrint(CY_FX_DEBUG_PRIORITY, "FPGAInterrupt.CyU3PDmaChannelGetBuffer failed, Error code = %d\n", apiRetStatus);

    if (apiRetStatus == CY_U3P_SUCCESS) {
        CyU3PMemSet (buf_p_1.buffer, 0, 16*CY_FX_EP_BULK_VIDEO_PKT_SIZE);
        for (int i=0; i<16*CY_FX_EP_BULK_VIDEO_PKT_SIZE; i++) {
            buf_p_1.buffer[i] = FPGAInterrupt_header[i%24];
        buf_p_1.buffer[0] = intr_cnt;
        CyU3PDebugPrint(CY_FX_DEBUG_PRIORITY, "FPGAInterrupt() memset done \r\n");
        /* Commit the full buffer with default status. */
        apiRetStatus = CyU3PDmaChannelCommitBuffer (&glChHandleUVCControlIN, buf_p_1.size, 0);
        if (apiRetStatus != CY_U3P_SUCCESS) {
            CyU3PDebugPrint(CY_FX_DEBUG_PRIORITY, "CyFxUVCDmaDownloadCallback.CyU3PDmaChannelCommitBuffer failed, Error code = %d\n", apiRetStatus);
        CyU3PDebugPrint(CY_FX_DEBUG_PRIORITY, "FPGAInterrupt() memset done \r\n");
    CyU3PDebugPrint(CY_FX_DEBUG_PRIORITY, "FPGAInterrupt() exits \r\n");


CyFxGpifCB (
        uint8_t currentState            /* GPIF state which triggered the interrupt. */
    /* The ongoing video frame has ended. If we have a partial buffer sitting on the socket, we need to forcibly
     * wrap it up. We also need to toggle the FW_TRG a couple of times to get the state machine ready for the
     * next frame.
     * Note: DMA channel APIs cannot be used here as this is ISR context. We are making use of the raw socket
     * APIs.
    switch (currentState)
        case FPGA_DO_INTR:
            FPGA_Intr_called = CyTrue;
//            if (FPGA_Intr_called == CyTrue) {
//                FPGAInterrupt();
//                FPGA_Intr_called = CyFalse;
//            }



uvcFPGAIntrThread_Entry (uint32_t input)
    for (;;) {
        if (FPGA_Intr_called == CyTrue) {
            FPGA_Intr_called = CyFalse;

//        CyU3PThreadSleep(10);
        /* Allow other ready threads to run. */
        CyU3PThreadRelinquish ();



    dmaCfg.size  = 16*CY_FX_EP_BULK_VIDEO_PKT_SIZE;
    dmaCfg.count = 1;
    dmaCfg.prodSckId = CY_U3P_UIB_SOCKET_PROD_5;
    dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS;
    dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE;
    dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT | CY_U3P_DMA_CB_CONS_EVENT;
    dmaCfg.cb = CyFxUVCControlDmaCallback;
    dmaCfg.prodHeader = 0;
    dmaCfg.prodFooter = 0;
    dmaCfg.consHeader = 0;
    dmaCfg.prodAvailCount = 0;
    /* Create a DMA MANUAL_OUT channel for the consumer socket. */
    dmaCfg.notification = CY_U3P_DMA_CB_CONS_EVENT;
    dmaCfg.prodSckId = CY_U3P_CPU_SOCKET_PROD;
    dmaCfg.consSckId = CY_U3P_UIB_SOCKET_CONS_4;
    apiRetStatus = CyU3PDmaChannelCreate (&glChHandleUVCControlIN,
            CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfg);


    apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleUVCControlIN, 0);


mady's picture
Cypress Employee
1113 posts


Instead of CYU3P_NO_WAIT, can you please specify a finite timeout and see? This has been the issue in lot of similar cases.


-Madhu Sudhan

CHLI's picture
3 posts


  I have a similar issue, According to my debug, changing the size and count of DMA could ameliorate the situation. I don't know if the situation happens only when using libusb driver? Or it's the bug of FX3 when changing the size and count of DMA?

Log in to post new comments.