📄 xllp_udc.c
字号:
Return Value:
XLLP_STATUS_T - error code if failed, zero if success
*******************************************************************************/
void XllpUdcControlProcessIdle (P_XLLP_UDC_T pUdcHandle,
P_XLLP_UINT32_T pControlXferStatus)
{
XLLP_UDC_USB_SETUP_DATA_T reqData;
P_XLLP_UINT32_T rxBuffP = (P_XLLP_UINT32_T)&reqData;
P_XLLP_UINT32_T pTxBuffEp0;
XLLP_UINT32_T tempDataLen;
XLLP_UINT32_T tempReqType;
XLLP_INT32_T packetLength;
volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;
// Determine if UDCCS0.OPC and UDCCS0.SA both are set.
// It means that OUT packet in the Endpoint 0 buffer identifying SETUP transaction,
if (pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA))
{
// Read data from Endpoint 0 data buffer
// The data packet of the setup stage is always 8 bytes
XllpUdcReadDwordFifo (&pRegs->UDCDR[ENDPOINT_0], rxBuffP, 8);
// Parse the data that is in the buffer
// Identify RequestType
tempReqType = (reqData.bmRequestType & XLLP_UDC_REQ_TYPE_MASK) >> 5;
if (tempReqType == STANDARD_REQ)
{
// Identify Standard Request type
switch (reqData.bRequest)
{
case GET_DESCRIPTOR:
// Get the number of data bytes in the data stage that follows
// This is the maximum number, and the device can return this
// number of bytes or fewer.
pUdcHandle->controlXfer.dataLengthEp0 = reqData.wLength;
// Identify type of descriptor
switch (reqData.wValue >> 8)
{
case DEVICE_DESCRIPTOR:
// Read the length of the device descriptor
// and compare with number of bytes in the data stage
tempDataLen = UsbDeviceDesc[0];
if (pUdcHandle->controlXfer.dataLengthEp0 > tempDataLen)
pUdcHandle->controlXfer.dataLengthEp0 = tempDataLen;
// Initialize the Tx buffer pointer with the device descriptor's address
pUdcHandle->controlXfer.pTxBuffEp0 = (P_XLLP_UINT32_T)UsbDeviceDesc;
break;
case CONFIG_DESCRIPTOR:
// Read the total length of the configuration descriptor
// and compare with number of bytes in the data stage
tempDataLen = XLLP_UDC_CONFIG_TOTAL;
if (pUdcHandle->controlXfer.dataLengthEp0 > tempDataLen)
pUdcHandle->controlXfer.dataLengthEp0 = tempDataLen;
// Initialize the Tx buffer pointer with the config. descriptor's address
pUdcHandle->controlXfer.pTxBuffEp0 = (P_XLLP_UINT32_T)UsbConfigDesc;
break;
case STRING_DESCRIPTOR:
if ( XllpUdcGetStringDescriptor(reqData.wValue,
(P_XLLP_UINT8_T*)&pUdcHandle->controlXfer.pTxBuffEp0,
&tempDataLen))
{
if (pUdcHandle->controlXfer.dataLengthEp0 > tempDataLen)
pUdcHandle->controlXfer.dataLengthEp0 = tempDataLen;
}
else
{
// error found
}
}
// Preload EP0 FIFO to get ready for IN transaction that follows.
// Write up to sixteen bytes to the Endpoint 0 data buffer
packetLength = pUdcHandle->controlXfer.dataLengthEp0;
pTxBuffEp0 = pUdcHandle->controlXfer.pTxBuffEp0;
// Write to the Endpoint 0 data buffer
if (packetLength >= MPS_CNTRL_16)
{
XllpUdcWriteDwordFifo (&pRegs->UDCDR[ENDPOINT_0], pTxBuffEp0, MPS_CNTRL_16);
pTxBuffEp0 = (P_XLLP_UINT32_T)((XLLP_UINT32_T)pTxBuffEp0 + MPS_CNTRL_16);
pUdcHandle->controlXfer.dataLengthEp0 -= MPS_CNTRL_16;
// Update pointer to the transmit buffer
pUdcHandle->controlXfer.pTxBuffEp0 = pTxBuffEp0;
}
else
{
XllpUdcWriteDwordFifo (&pRegs->UDCDR[ENDPOINT_0], pTxBuffEp0, packetLength);
pUdcHandle->controlXfer.dataLengthEp0 -= packetLength;
}
// Set UDCCSR0.IPR = 1 if the packet smaller than 16 bytes has been loaded
// to the Endpoint 0 FIFO
if (packetLength < MPS_CNTRL_16)
{
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
// Set the status of the Endpoint 0 state machine to XFER data
pUdcHandle->controlXfer.statusEp0 = EP0_END_XFER_STATE;
}
else
{
// Set the status of the Endpoint 0 state machine to IN data
pUdcHandle->controlXfer.statusEp0 = EP0_IN_DATA_STATE;
}
break;
case SET_DESCRIPTOR:
// Save descriptor index (lower byte of wValue)
pUdcHandle->controlXfer.descIndexEp0 = reqData.wValue & 0xff;
// Save descriptor type (upper byte of wValue)
pUdcHandle->controlXfer.descTypeEp0 = reqData.wValue >> 8;
// Get the number of data bytes in the data stage that follows
pUdcHandle->controlXfer.dataLengthEp0 = reqData.wLength;
// Initialize Rx buffer pointer with address where the descriptor will be stored
pUdcHandle->controlXfer.pRxBuffEp0 = pUdcHandle->controlXfer.outDataEp0;
// Set UDCCSR0.IPR in case of premature STATUS IN stage
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
// Set the status of the Endpoint 0 state machine to OUT data
pUdcHandle->controlXfer.statusEp0 = EP0_OUT_DATA_STATE;
}
}
// Process Vendor Request
else if (tempReqType == VENDOR_REQ)
{
// Get ready to process the data that would be sent in the data stage
pUdcHandle->vendorReq.recipient = reqData.bmRequestType & XLLP_USB_REQ_RECIPIENT_MASK;
pUdcHandle->vendorReq.vendorReqType = reqData.bRequest;
pUdcHandle->vendorReq.vendorReqEndpointNum = reqData.wValue;
pUdcHandle->vendorReq.vendorReqComplete = XLLP_TRUE;
// Get the number of data bytes in the data stage that follows
pUdcHandle->controlXfer.dataLengthEp0 = reqData.wLength;
// Set UDCCSR0.IPR in case of premature STATUS IN stage
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
// Set the status of the Endpoint 0 state machine to OUT data
if ( /* direction */ !(reqData.bmRequestType & 0x80) )
{
// 0: Host to device
pUdcHandle->controlXfer.statusEp0 = EP0_OUT_DATA_STATE;
}
else
{
XllpUdcProcessVendorRequest (pUdcHandle);
pUdcHandle->vendorReq.vendorReqComplete = XLLP_FALSE;
}
}
else if (tempReqType == CLASS_REQ)
{}
}
// Clear UDCCS0.OPC and UDCCS0.SA
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA;
*pControlXferStatus = 0;
}
/******************************************************************************
Function Name:
XllpUdcControlProcessOutData
Description:
This function services the data OUT state of Endpoint 0 state machine.
Global Register Modified:
None.
Input Arguments:
P_XLLP_UDC_T pUdcHandle - a pointer to the UDC's handle
Output Arguments:
P_XLLP_UINT32_T pControlXferStatus - returns the value that tells the Endpoint 0
state machine to switch to the Idle state.
Return Value:
None.
*******************************************************************************/
void XllpUdcControlProcessOutData (P_XLLP_UDC_T pUdcHandle,
P_XLLP_UINT32_T pControlXferStatus)
{
volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;
XLLP_INT32_T packetLength;
// Check UDCCS0.OPC and UDCCS0.SA
if (pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) ==
(XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) )
{
// UDCCSR0.OPC and UDCCSR0.SA both are set,
// there is another SETUP transaction has been sent by the host
// Initialize Endpoint 0 state machine to the Idle state
pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
*pControlXferStatus = EP0_JUMP_TO_IDLE;
}
else if ((pRegs->UDCCSR[ENDPOINT_0] &
(XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == 0)
{
// UDCCSR0.OPC = 0 and UDCCSR0.SA = 0 this is premature STATUS stage of
// the SETUP transaction.
// Initialize Endpoint 0 state machine to the Idle state
pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
}
else if ((pRegs->UDCCSR[ENDPOINT_0] &
(XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == XLLP_UDC_UDCCSR0_OPC)
{
// Read data from the Endpoint 0 FIFO
if (pRegs->UDCCSR[ENDPOINT_0] & XLLP_UDC_UDCCSR0_RNE)
{
packetLength = pRegs->UDCBCR[ENDPOINT_0] & XLLP_UDC_UDCBCR_BC_MASK;
XllpUdcReadDwordFifo (&pRegs->UDCDR[ENDPOINT_0], pUdcHandle->controlXfer.pRxBuffEp0, packetLength);
pUdcHandle->controlXfer.dataLengthEp0 -= packetLength;
*pControlXferStatus = 0;
}
// Clear UDCCS0.OPC
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_OPC;
// Set UDCCS0.IPR in case of premature STATUS IN stage
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
}
}
/******************************************************************************
Function Name:
XllpUdcControlProcessInData
Description:
This function services the data IN state of Endpoint 0 state machine.
Global Register Modified:
None.
Input Arguments:
P_XLLP_UDC_T pUdcHandle - a pointer to the UDC's handle
Output Arguments:
P_XLLP_UINT32_T pControlXferStatus - returns the value that tells the Endpoint 0
state machine to switch to the Idle state.
Return Value:
None.
*******************************************************************************/
void XllpUdcControlProcessInData (P_XLLP_UDC_T pUdcHandle,
P_XLLP_UINT32_T pControlXferStatus)
{
volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;
XLLP_INT32_T packetLength;
// Check UDCCSR0.OPC and UDCCSR0.SA
if (pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) ==
(XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) )
{
// UDCCSR0.OPC and UDCCSR0.SA both are set,
// there is another SETUP transaction has been sent by the host
// Initialize Endpoint 0 state machine to the Idle state
pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
*pControlXferStatus = EP0_JUMP_TO_IDLE;
}
else if ((pRegs->UDCCSR[ENDPOINT_0] &
(XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == XLLP_UDC_UDCCSR0_OPC)
{
// UDCCSR0.OPC = 1 and UDCCSR0.SA = 0 this is premature STATUS stage of
// the SETUP transaction. Clear UDCCSR0.OPC and empty transmit FIFO
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_FTF;
// Reset all state machine variables
pUdcHandle->controlXfer.dataLengthEp0 = 0;
pUdcHandle->controlXfer.pTxBuffEp0 = NULL;
pUdcHandle->controlXfer.pRxBuffEp0 = NULL;
// Initialize Endpoint 0 state machine to the Idle state
pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
}
else if ((pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == 0)
{
packetLength = pUdcHandle->controlXfer.dataLengthEp0;
if ( packetLength > MPS_CNTRL_16 ) {
packetLength = MPS_CNTRL_16;
}
XllpUdcWriteDwordFifo (&pRegs->UDCDR[ENDPOINT_0], pUdcHandle->controlXfer.pTxBuffEp0, packetLength);
pUdcHandle->controlXfer.dataLengthEp0 -= packetLength;
if ( MPS_CNTRL_16 != packetLength )
{
// short packet or ZLP
// No more data left, force UDC to send zero lenght packet.
// Set Endpoint 0 state machine to the End of transfer state
pRegs->UDCCSR[ENDPOINT_0] = XLLP_UDC_UDCCSR0_IPR;
pUdcHandle->controlXfer.statusEp0 = EP0_END_XFER_STATE;
}
else
{
pUdcHandle->controlXfer.pTxBuffEp0 += (MPS_CNTRL_16 >> 2);
// It needs more data to transmit,
// so on the next interrupt go back to the same state.
}
*pControlXferStatus = 0;
}
}
/******************************************************************************
Function Name:
XllpUdcControlProcessEndXfer
Description:
This function services the Status state of Endpoint 0 state machine.
Global Register Modified:
None.
Input Arguments:
P_XLLP_UDC_T pUdcHandle - a pointer to the UDC's handle
Output Arguments:
P_XLLP_UINT32_T pControlXferStatus - returns the value that tells the Endpoint 0
state machine to switch to the Idle state.
Return Value:
None.
*******************************************************************************/
void XllpUdcControlProcessEndXfer (P_XLLP_UDC_T pUdcHandle,
P_XLLP_UINT32_T pControlXferStatus)
{
volatile P_XLLP_UDC_REGISTERS_T pRegs = (P_XLLP_UDC_REGISTERS_T)pUdcHandle->pRegsBase;
// Check UDCCSR0.OPC and UDCCSR0.SA
if (pRegs->UDCCSR[ENDPOINT_0] & (XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) ==
(XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA) )
{
// UDCCSR0.OPC and UDCCSR0.SA both are set,
// there is another SETUP transaction has been sent by the host
// Initialize Endpoint 0 state machine to the Idle state
pUdcHandle->controlXfer.statusEp0 = EP0_IDLE_STATE;
*pControlXferStatus = EP0_JUMP_TO_IDLE;
}
else if ((pRegs->UDCCSR[ENDPOINT_0] &
(XLLP_UDC_UDCCSR0_OPC | XLLP_UDC_UDCCSR0_SA)) == XLLP_UDC_UDCCSR0_OPC)
{
// UDCCSR0.OPC = 1 and UDCCSR0.SA = 0 this is STATUS stage of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -