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: 0 Replies, Latest post by lis_user1 on 30 Nov 2016 06:46 PM PST
Verified Answers: 0
Log in to post new comments.
lis_user1's picture
User
31 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");
    return;
}

 

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:
            intr_cnt++;
            FPGA_Intr_called = CyTrue;
//            if (FPGA_Intr_called == CyTrue) {
//                FPGAInterrupt();
//                FPGA_Intr_called = CyFalse;
//            }
      }
}     

 

 

void
uvcFPGAIntrThread_Entry (uint32_t input)
{
    for (;;) {
        if (FPGA_Intr_called == CyTrue) {
            FPGAInterrupt();
            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;
    <cut>
    
    /* 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);

    <cut>

    apiRetStatus = CyU3PDmaChannelSetXfer (&glChHandleUVCControlIN, 0);

 

Log in to post new comments.