⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xsusb.c

📁 这是一个USB的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
        error = XsDmaStart (ctxP->EPXferTable[inEpNum].dmaChannel);
        if (error != ERR_NONE)
        {
            return error;
        }

    }
    else
    {
        LOGERROR(ctxP->loggedError, ERR_L_XSUDC,
             ERR_S_XSUDC_DMA_IN, ERR_T_ILLPARAM, 2, 0, 0);
        return (ctxP->loggedError);
    }

    return error;
}

/*
******************************************************************************
*
* FUNCTION:         XsUdcSetupOutEndpointDma
*
* DESCRIPTION:      This function will setup DMA to service BULK_OUT and ISO-OUT Endpoints.
*
* INPUT PARAMETERS: ctxP is a pointer to UDC's context structure
*                   UdcEndpointsT outEpNum
*                   INT numBytes - used to allocate memory
*                   INT maxPacketSize - max. packet size for the endpoint
*
* RETURNS:          0   if successful
*                   UINT32 error   if not
*
* GLOBAL EFFECTS:   The Endpoint's interrupt service request will be disabled and
*					the endpoint uses DMA transfer.
*
* ASSUMPTIONS:      The packet size is equal to the max. packet size for the transfer
*
* CALLS:            
*
* CALLED BY:        
*
* PROTOTYPE:        UINT32 XsUdcSetupOutEndpointDma (UdcContextT * ctxP, 
*                                                UdcEndpointsT outEpNum,
*                                                numBytes, 
*                                                maxPacketSize)
*
*******************************************************************************
*/
static
UINT32 XsUdcSetupOutEndpointDma (UdcContextT * ctxP, 
                                UdcEndpointsT outEpNum, 
                                INT numBytesXfer, 
                                INT packetSize)
{
    volatile UdcRegsT * regsP = (UdcRegsT *)ctxP->regsP;
    XsDmaDeviceNamesT deviceName;
    BOOL isTarget;
    INT numDescriptors;
    INT numBytes;
    UINT error = FALSE;

    // Make sure that the packet size large than 32 bytes
    if (packetSize < 32)
    {
        LOGERROR(ctxP->loggedError, ERR_L_XSUDC,
             ERR_S_XSUDC_DMA_OUT, ERR_T_ILLPARAM, 3, 0, 0);
        return (ctxP->loggedError);
    }
        
    if (outEpNum != 0)
    {
        // Enable the endpoint's interrupt
	    XsUdcEnableEndpointInt (ctxP, outEpNum);

        switch (outEpNum)
        {
            case Endpoint2:
                // Set the UDCCSx.DME bit for the BULK-OUT endpoint
                regsP->UDCCS2 = UDC_UDCCS_DME_OUT;
                deviceName = XSDMA_DN_USB_EP2;
                break;
            case Endpoint4:
                // Set the UDCCSx.DME bit for the ISO-OUT endpoint
                regsP->UDCCS4 = UDC_UDCCS_DME_OUT;
                deviceName = XSDMA_DN_USB_EP4;
                break;
        }
        
        isTarget = FALSE;
        numDescriptors = (numBytesXfer/packetSize + 
                                (numBytesXfer % packetSize ? 1 : 0));
        numBytes = packetSize;

        // Configure the DMA channel to be used to service OUT Endpoint's FIFO:
        error = XsDmaConfigureDevice (XSDMA_CH_PR_LOW,
                                deviceName, 
                                isTarget,
                                &ctxP->EPXferTable[outEpNum].firstDescVtP,
                                numDescriptors,
                                numBytes,
                                NULL,0,0,
                                (PINT)&ctxP->EPXferTable[outEpNum].dmaChannel);

        if (error != ERR_NONE)
          return (error);
    }
    else
    {
        LOGERROR(ctxP->loggedError, ERR_L_XSUDC,
             ERR_S_XSUDC_DMA_OUT, ERR_T_ILLPARAM, 4, 0, 0);
        return (ctxP->loggedError);
    }

    return error;
}

/*
*******************************************************************************
*
* FUNCTION:         XsUdcFillFifo
*
* DESCRIPTION:      This function is used to Fill the IN FIFO with data.
*
* INPUT PARAMETERS: UdcContextT * ctxP is a pointer to UDC's context structure
*                   INT endpointNum is an Endpoint's number
*					UINT numBytes contains number of bytes to be placed in the FIFO
*
* RETURNS:          none
*
* GLOBAL EFFECTS:   none
*
* ASSUMPTIONS:      none
*
*******************************************************************************
*/
static
VOID XsUdcFillFifo (UdcContextT * ctxP, INT epNum)
{
    volatile UdcRegsT * regsP = (UdcRegsT *)ctxP->regsP;
    PVUINT dataRegP;
    PVUINT statusRegP;
    UINT numBytes;
	PCHAR dataP;
	UINT i;

    if (ctxP->EPXferTable[epNum].xferLength >= ctxP->EPXferTable[epNum].maxPacketSize)
      numBytes = ctxP->EPXferTable[epNum].maxPacketSize;
    else
      numBytes = ctxP->EPXferTable[epNum].xferLength;

    switch (epNum)
    {
        case Endpoint1:
            dataRegP = (PVUINT)&regsP->UDDR1;
            statusRegP = (PVUINT)&regsP->UDCCS1;
            break;
        case Endpoint3:
            dataRegP = (PVUINT)&regsP->UDDR3;
            statusRegP = (PVUINT)&regsP->UDCCS3;
            break;
        case Endpoint5:
            dataRegP = (PVUINT)&regsP->UDDR5;
            statusRegP = (PVUINT)&regsP->UDCCS5;
            break;
    }

/*
	XsUdcCaptureStatistics (ctxP->intCountP->RegDbgP,
					   (PVOID)statusRegP,
					   FrameNumber,
					   16,
					   (PUINT)&ctxP->intCountP->TotalCapturedCnt);
*/
    // Check for errors
    if (*statusRegP & UDC_UDCCS_TPC_IN)
    {
        // Clear UDCCS-TPC bit
        *statusRegP = (*statusRegP & 0x20) | UDC_UDCCS_TPC_IN;
	
        // If STALL is set just return and wait for CLEAR_FEATURE to clear the stall bit
        if (*statusRegP & UDC_UDCCS_SST_IN)
        {
			XsUdcClearEndpointInt (ctxP, epNum);
            return;
        }
        // If underrun bit is set clear it
        if (*statusRegP & UDC_UDCCS_TUR_IN)
        {
            *statusRegP = (*statusRegP & 0x20) | UDC_UDCCS_TUR_IN;
        }
    }

    // No more data to transmit, we are living
    if (ctxP->EPXferTable[epNum].xferComplete == TRUE)
    {
        if (*statusRegP & UDC_UDCCS_TPC_IN)
        {
            // Clear UDCCS-TPC bit
            *statusRegP = (*statusRegP & 0x20) | UDC_UDCCS_TPC_IN;
        }
		XsUdcClearEndpointInt (ctxP, epNum);
        return;
    }

	dataP = ctxP->EPXferTable[epNum].EPDataP + ctxP->EPXferTable[epNum].xferDataCounter;
	// Fill an endpoint FIFO with the data
	for (i = 0; i < numBytes; i++)
	{
	    *dataRegP = *dataP++;
	}

	// If this is the short packet set UDCCS-TSP bit
	if ((numBytes < ctxP->EPXferTable[epNum].maxPacketSize) && (numBytes != 0))
    {
/*
		FrameNumber = XsUdcGetFrameNumber ((UdcRegsT*)regsP);
		XsUdcCaptureStatistics (ctxP->intCountP->RegDbgP,
					   (PVOID)statusRegP,
					   FrameNumber,
					   16,
					   (PUINT)&ctxP->intCountP->TotalCapturedCnt);
*/
		*statusRegP = (*statusRegP & 0x20) | UDC_UDCCS_TSP_IN | UDC_UDCCS_TPC_IN;
        ctxP->EPXferTable[epNum].xferLength -= numBytes;
        ctxP->EPXferTable[epNum].xferDataCounter += numBytes;
        ctxP->EPXferTable[epNum].xferComplete = TRUE;
        ctxP->intCountP->EPShortPackets++;
    }
    // Send zero-length packet
    else if ((numBytes == 0)&&(ctxP->EPXferTable[epNum].xferComplete == FALSE))
    {
/*
		FrameNumber = XsUdcGetFrameNumber ((UdcRegsT*)regsP);
		XsUdcCaptureStatistics (ctxP->intCountP->RegDbgP,
					   (PVOID)statusRegP,
					   FrameNumber,
					   16,
					   (PUINT)&ctxP->intCountP->TotalCapturedCnt);
*/
		*statusRegP = (*statusRegP & 0x20) | UDC_UDCCS_TSP_IN | UDC_UDCCS_TPC_IN;
        ctxP->intCountP->EPZeroPackets++;
        ctxP->EPXferTable[epNum].xferComplete = TRUE;
    }
    else 
    {
        // Update xfer length
        ctxP->EPXferTable[epNum].xferLength -= numBytes;
        ctxP->EPXferTable[epNum].xferDataCounter += numBytes;
        ctxP->intCountP->EPPackets++;
    	*statusRegP = (*statusRegP & 0x20) | UDC_UDCCS_TPC_IN;
    }

	XsUdcClearEndpointInt (ctxP, epNum);
}


/*
*******************************************************************************
*
* FUNCTION:         XsUdcUnloadFifo
*
* DESCRIPTION:      This function is used to unload the OUT FIFO with data.
*
* INPUT PARAMETERS: UdcContextT * ctxP is a pointer to UDC's context structure
*                   INT endpointNum is an Endpoint's number
*					UINT numBytes contains number of bytes to be placed in the FIFO
*
* RETURNS:          none
*
* GLOBAL EFFECTS:   none
*
* ASSUMPTIONS:      none
*
*******************************************************************************
*/

static
VOID XsUdcUnloadFifo (UdcContextT * ctxP, INT epNum)
{
    volatile UdcRegsT * regsP = (UdcRegsT *)ctxP->regsP;
    PVUINT dataRegP;
    PVUINT statusRegP;
    PVUINT byteCountRegP;
    UINT numBytes;
	PCHAR dataP;
    INT dmaChannel;
    UINT targetPh;
    PVOID targetVtP;
	UINT i;
    UINT error;

    switch (epNum)
    {
        case Endpoint2:
            dataRegP = (PVUINT)&regsP->UDDR2;
            statusRegP = (PVUINT)&regsP->UDCCS2;
            byteCountRegP = (PVUINT)&regsP->UBC2;
            break;
        case Endpoint4:
            dataRegP = (PVUINT)&regsP->UDDR4;
            statusRegP = (PVUINT)&regsP->UDCCS4;
            byteCountRegP = (PVUINT)&regsP->UBC4;
            break;
    }

    // If DMA was enabled, we must assume a short packet in FIFO
    // indicating the end of the transfer
    if (ctxP->enableDma == TRUE)
    {
        dmaChannel = ctxP->EPXferTable[epNum].dmaChannel;
        // Stop the DMA channel
        XsDmaStop (dmaChannel);
        // Wait until DMA channel stops
        error = XsDmaWaitUntilStopped (dmaChannel);
        if (error)
        {
            LOGERROR(ctxP->loggedError, ERR_L_XSUDC,
                 ERR_S_XSUDC_DMA_OUT, ERR_T_TIMEOUT, 0, 0, 0);
        }

        // Get the address of the data buffer
        targetPh = XsDmaGetPointerLastDataBuffer (dmaChannel);
        PhysicalToVirtual(targetPh, 0, &targetVtP);
        dataP = (PCHAR)targetVtP;

        DM_CwDbgPrintf(DM_CW_USB_CLIENT,"Target Buff Ph: %08x", targetPh);
        DM_CwDbgPrintf(DM_CW_USB_CLIENT,"Target Buff Vt: %08x", (UINT)targetVtP);
        DM_CwDbgPrintf(DM_CW_USB_CLIENT,"Data Pointer: %08x", (UINT)dataP);
	}
    else
    {
	    // Set the pointer to where the data will be placed to
        dataP = ctxP->EPXferTable[epNum].EPDataP + ctxP->EPXferTable[epNum].xferDataCounter;
    }

	// Check if this is zero-length packet UDCCS-RSP = 1 and UDCCS-RNE = 0 
	if ((*statusRegP & UDC_UDCCS_RSP_OUT) && ((*statusRegP & UDC_UDCCS_RNE_OUT) == 0))
	{
		// Clear UDCCS-RPC bit
		*statusRegP |= UDC_UDCCS_RPC_OUT;
        ctxP->EPXferTable[epNum].xferLength = 0;
//        ctxP->EPXferTable[epNum].xferDataCounter = 0;
	}	
	else if (*statusRegP & UDC_UDCCS_RNE_OUT)
	{
		// Get number of bytes in OUT FIFO
		numBytes = *byteCountRegP + 1;
		for (i = 0; i < numBytes; i++)
		{
			// Get the data from EP2 FIFO
			*dataP++ = *dataRegP;	
		}

		// Clear UDCCS_RPC bit
		*statusRegP |= UDC_UDCCS_RPC_OUT;

        // Update xfer length
        ctxP->EPXferTable[epNum].xferLength -= numBytes;
        ctxP->EPXferTable[epNum].xferDataCounter += numBytes;
	}

	XsUdcClearEndpointInt (ctxP, epNum);
}


/*
*******************************************************************************
*
* FUNCTION:         XsUdcSetupInEndpoint
*
* DESCRIPTION:      This function will setup BULK IN, ISO IN and Interrupt IN endpoints.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -