📄 xsusb.c
字号:
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)®sP->UDDR1;
statusRegP = (PVUINT)®sP->UDCCS1;
break;
case Endpoint3:
dataRegP = (PVUINT)®sP->UDDR3;
statusRegP = (PVUINT)®sP->UDCCS3;
break;
case Endpoint5:
dataRegP = (PVUINT)®sP->UDDR5;
statusRegP = (PVUINT)®sP->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)®sP->UDDR2;
statusRegP = (PVUINT)®sP->UDCCS2;
byteCountRegP = (PVUINT)®sP->UBC2;
break;
case Endpoint4:
dataRegP = (PVUINT)®sP->UDDR4;
statusRegP = (PVUINT)®sP->UDCCS4;
byteCountRegP = (PVUINT)®sP->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 + -