📄 xllp_udc.c
字号:
// the IN transaction. Clear UDCCSR0.OPC.
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_OPC;
// Initialize Endpoint 0 state machine to the Idle state
pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
*pControlXferStatus = 0;
}
}
/******************************************************************************
Function Name:
XllpUdcFillFifo
Description:
This function is used to load the packet to the A-X Endpoint's FIFO.
Global Register Modified:
None.
Input Arguments:
P_XLLP_UDC_T pUdcHandle - pointer to the UDC's handle
XLLP_UDC_EP_T udcEndpointNum - the UDC endpoint number
XLLP_BOOL_T enableZLP - a flag that controls if ZLP should be sent to the USB Host
Output Arguments:
None
Return Value:
None
Note: According to USB specification for BULK and Interrupt transfer the transfer is complete
when the endpoint dose one of the following:
- Has transfered exactly the amount of data expected
- Transfers a short packet or a zero-length packet
The different OS use different termination of the BULK and Interrupt transfer.
The enableZLP should be set to FALSE is USB Host expected the exact number of bytes
and to TRUE otherwize.
For ISO transfer enableZLP should be set to TRUE
*******************************************************************************/
void XllpUdcFillFifo (P_XLLP_UDC_T pUdcHandle,
XLLP_UDC_EP_T udcEndpointNum, XLLP_BOOL_T enableZLP)
{
volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;
XLLP_UINT32_T packetLength;
P_XLLP_UINT32_T pTxBuff;
XLLP_UINT32_T status;
// Read the UDCCSRx register
status = pRegs->UDCCSR[udcEndpointNum];
do {
// Check for errors
if (status & XLLP_UDC_UDCCSR_PC)
{
// Clear UDCCSR.PC bit
pRegs->UDCCSR[udcEndpointNum] =
(status & XLLP_UDC_UDCCSR_DME) | XLLP_UDC_UDCCSR_PC;
// Check if FIFO underun took place
if (status & XLLP_UDC_UDCCSR_EFE)
{
// Clear UDCCSR.EFE bit
pRegs->UDCCSR[udcEndpointNum] =
(status & XLLP_UDC_UDCCSR_DME) | XLLP_UDC_UDCCSR_EFE;
}
// If STALL is set just return and wait for CLEAR_FEATURE to clear UDCCSR.SST bit
if (status & XLLP_UDC_UDCCSR_SST)
{
// Clear the Interrupt
XllpUdcClearInterrupt (pUdcHandle, udcEndpointNum, PACKET_COMPL_INT);
return;
}
}
// Transfer is complete, we are leaving.
if (pUdcHandle->EpXferTable[udcEndpointNum].TxXferComplete == XLLP_TRUE) {
break;
}
if (pUdcHandle->EpXferTable[udcEndpointNum].xferLength >=
pUdcHandle->EpXferTable[udcEndpointNum].maxPacketSize)
packetLength = pUdcHandle->EpXferTable[udcEndpointNum].maxPacketSize;
else
packetLength = pUdcHandle->EpXferTable[udcEndpointNum].xferLength;
// Get the pointer to the Tx data buffer
pTxBuff = pUdcHandle->EpXferTable[udcEndpointNum].pDataEp +
(pUdcHandle->EpXferTable[udcEndpointNum].xferDataCounter >> 2);
// Write to the Endpoint's FIFO
XllpUdcWriteDwordFifo(&pRegs->UDCDR[udcEndpointNum], pTxBuff, packetLength);
// Check if this is a short packet
if (packetLength < pUdcHandle->EpXferTable[udcEndpointNum].maxPacketSize)
{
// Set UDCCSR.SP to signal UDC that a short packet was loaded into the FIFO
pRegs->UDCCSR[udcEndpointNum] =
(status & XLLP_UDC_UDCCSR_DME) | XLLP_UDC_UDCCSR_SP;
// Set xfer complete flag
if (enableZLP == XLLP_TRUE)
pUdcHandle->EpXferTable[udcEndpointNum].TxXferComplete = XLLP_TRUE;
}
// Update xfer length
pUdcHandle->EpXferTable[udcEndpointNum].xferLength -= packetLength;
pUdcHandle->EpXferTable[udcEndpointNum].xferDataCounter += packetLength;
if ((pUdcHandle->EpXferTable[udcEndpointNum].xferLength == 0) &&
(enableZLP == XLLP_FALSE))
{
// Set xfer complete flag
pUdcHandle->EpXferTable[udcEndpointNum].TxXferComplete = XLLP_TRUE;
}
status = pRegs->UDCCSR[udcEndpointNum];
} while ((status & (XLLP_UDC_UDCCSR_BNE | XLLP_UDC_UDCCSR_FS)) &&
(pUdcHandle->EpXferTable[udcEndpointNum].TxXferComplete == XLLP_FALSE));
}
/******************************************************************************
Function Name:
XllpUdcUnloadFifo
Description:
This function is used to unload the packet from the A-X Endpoint's FIFO
Global Register Modified:
None.
Input Arguments:
P_XLLP_UDC_T pUdcHandle - pointer to the UDC's handle
XLLP_UDC_EP_T udcEndpointNum - the UDC endpoint number
Output Arguments:
None
Return Value:
None
*******************************************************************************/
void XllpUdcUnloadFifo (P_XLLP_UDC_T pUdcHandle,
XLLP_UDC_EP_T udcEndpointNum)
{
volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;
P_XLLP_UINT32_T pRxBuff;
XLLP_UINT32_T packetLength;
XLLP_UINT32_T status;
// If DMA was enabled we must assume a short packet causes an interrupt
if (pUdcHandle->enableDma)
{
// Get DMA channel that has been allocated for the xfer
// Stop the DMA channel
// Wait until DMA channel stops
// Get the address of the data buffer
}
while (((status=pRegs->UDCCSR[udcEndpointNum]) & (XLLP_UDC_UDCCSR_PC | XLLP_UDC_UDCCSR_FS))
&& pUdcHandle->EpXferTable[udcEndpointNum].RxBlockXferComplete == XLLP_FALSE)
{
// Set the pointer to where the data will be placed to
pRxBuff = pUdcHandle->EpXferTable[udcEndpointNum].pDataEp +
(pUdcHandle->EpXferTable[udcEndpointNum].xferDataCounter >> 2);
// Check if this is zero-length packet, UDCCSRx.SP = 1 and UDCCSRx.BNE = 0
if ((status & XLLP_UDC_UDCCSR_SP) && ((status & XLLP_UDC_UDCCSR_BNE) == 0))
{
// Clear UDCCSRx.PC bit
pRegs->UDCCSR[udcEndpointNum] =
(pRegs->UDCCSR[udcEndpointNum] & XLLP_UDC_UDCCSR_DME) | XLLP_UDC_UDCCSR_PC;
// Update receive complete flag to signal the end of the transfer
pUdcHandle->EpXferTable[udcEndpointNum].RxXferComplete = XLLP_TRUE;
break;
}
// Check if this is a short packet, UDCCSRx.SP = 1 and UDCCSRx.BNE = 1
else if ((status & XLLP_UDC_UDCCSR_SP) && ((status & XLLP_UDC_UDCCSR_BNE) > 0))
{
packetLength = pRegs->UDCBCR[udcEndpointNum] & XLLP_UDC_UDCBCR_BC_MASK;
XllpUdcReadDwordFifo (&pRegs->UDCDR[udcEndpointNum], pRxBuff, packetLength);
// Update xfer data counter
pUdcHandle->EpXferTable[udcEndpointNum].xferDataCounter += packetLength;
// Update receive complete flag to signal the end of the transfer
pUdcHandle->EpXferTable[udcEndpointNum].RxXferComplete = XLLP_TRUE;
// Clear UDCCSR.PC bit
pRegs->UDCCSR[udcEndpointNum] =
(status & XLLP_UDC_UDCCSR_DME) | XLLP_UDC_UDCCSR_PC;
break;
}
// Check if this is a max. size packet, UDCCSRx.SP = 0 and UDCCSRx.BNE = 1
else if (((status & XLLP_UDC_UDCCSR_SP) == 0) && (status & XLLP_UDC_UDCCSR_BNE))
{
packetLength = pRegs->UDCBCR[udcEndpointNum] & XLLP_UDC_UDCBCR_BC_MASK;
XllpUdcReadDwordFifo ( &pRegs->UDCDR[udcEndpointNum], pRxBuff, packetLength);
// Update xfer data counter
pUdcHandle->EpXferTable[udcEndpointNum].xferDataCounter += packetLength;
// Check if the driver would have to notify upper layer to request more memory
if (pUdcHandle->EpXferTable[udcEndpointNum].xferDataCounter >=
pUdcHandle->EpXferTable[udcEndpointNum].xferLength)
{
pUdcHandle->EpXferTable[udcEndpointNum].RxBlockXferComplete = XLLP_TRUE;
}
// Clear UDCCSR.PC bit
pRegs->UDCCSR[udcEndpointNum] =
(status & XLLP_UDC_UDCCSR_DME) | XLLP_UDC_UDCCSR_PC;
}
}
}
/******************************************************************************
Function Name:
XllpUdcEp0InterruptHandler
Description:
This function is an interrupt handler for Endpoint 0 of UDC.
It dispatches the functions of the Endpoint 0 in according to the status
of the Endpoint 0 state machine.
It handles the Get_Descriptor and Set_Descriptor standard requests
and the Vendor specific requests from the USB Host.
The Set_Configuration and Set_Interface Requests are serviced upon
the invocation of the Configuration interrupt.
Global Register Modified:
None.
Input Arguments:
P_XLLP_UDC_T pUdcHandle - a pointer to the UDC's handle
Output Arguments:
None
Return Value:
None
*******************************************************************************/
void XllpUdcEp0InterruptHandler (P_XLLP_UDC_T pUdcHandle)
{
XLLP_UINT32_T controlXferStatus = 0, statusEp0;
// Determine the status of the Endpoint 0 state machine
// and call the apropriate function
do
{
statusEp0 = pUdcHandle->controlXfer.statusEp0;
if (statusEp0 == EP0_IDLE_STATE)
{
XllpUdcControlProcessIdle (pUdcHandle, &controlXferStatus);
}
else if (statusEp0 == EP0_OUT_DATA_STATE)
{
XllpUdcControlProcessOutData (pUdcHandle, &controlXferStatus);
// if (pUdcHandle->vendorReq.vendorReqComplete == XLLP_TRUE)
if (pUdcHandle->vendorReq.vendorReqComplete == XLLP_TRUE && pUdcHandle->controlXfer.dataLengthEp0 == 0 )
{
XllpUdcProcessVendorRequest (pUdcHandle);
pUdcHandle->vendorReq.vendorReqComplete = XLLP_FALSE;
}
}
else if (statusEp0 == EP0_IN_DATA_STATE)
{
XllpUdcControlProcessInData (pUdcHandle, &controlXferStatus);
}
else if (statusEp0 == EP0_END_XFER_STATE)
{
XllpUdcControlProcessEndXfer (pUdcHandle, &controlXferStatus);
}
} while (controlXferStatus == EP0_JUMP_TO_IDLE);
}
/******************************************************************************
Function Name:
XllpUdcForceRemoteWakeup
Description:
This function signals wake-up request to the USB Host.
Global Register Modified:
None.
Input Arguments:
P_XLLP_UDC_T pUdcHandle - a pointer to the UDC's handle
Output Arguments:
None.
Return Value:
None.
*******************************************************************************/
void XllpUdcForceRemoteWakeup (P_XLLP_UDC_T pUdcHandle)
{
// The USB Host enables remote wake-up faeture of the UDC by sending Set_Feature
// request. That will set UDCCR.DRWF = 1.
// Check if the Device Remote Wake-up feature of the UDC was enabled
// (UDCCR.DRWF = 1)
// Signal wake-up to the USB Host by setting UDCCR.UDR = 1
}
/******************************************************************************
Function Name:
XllpUdcBusDevSoftConnect
Description:
This function allows disconnecting or connecting UDC to and from the USB bus.
It controls USBC_P to output +3.3V or to float.
This function clears the nUSBC_SC bit in the Misc. Write register 2 (MSCWR2)
to enable USB client detection.
Global Register Modified:
None.
Input Arguments:
XLLP_BOOL_T connect
Output Arguments:
None.
Return Value:
None.
*******************************************************************************/
void XllpUdcBusDevSoftConnect (XLLP_BOOL_T connect)
{
volatile P_XLLP_BOARD_REGISTERS_T pBoardReg =
(P_XLLP_BOARD_REGISTERS_T)XLLP_BOARD_REG_BASE;
// USB Client detection enabled
if (connect == XLLP_TRUE)
{
// Clear this bit to enable USB Client detection
pBoardReg->miscWr2 &= ~XLLP_MISC_WR2_USB_SC;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -