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

📄 xllp_udc.c

📁 优龙pxa270平台试验程序
💻 C
📖 第 1 页 / 共 5 页
字号:
        // 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 + -