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

📄 usbd_otghs.c

📁 Atmel的AT91SAM9263芯片的usb存储源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
            else if (ISSET(dStatus, AT91C_OTGHS_STALL)) {

                // Non-control endpoint
                // Discard stalled data
                TRACE_DEBUG_L("Disc ");
                pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXOUT;
            }
            else {

                // Non-control endpoint
                // Nak data
                TRACE_DEBUG_L("Nak ");
                pInterface->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
            }
        }
        else {

            // Endpoint is in Read state
            // Retrieve data and store it into the current transfer buffer
            wPacketSize = (unsigned short) ((dStatus >> 20) & 0x7FF);

            TRACE_DEBUG_L("%d ", wPacketSize);

            OTGHS_GetPayload(pUsb, bEndpoint, wPacketSize);

            pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXOUT;
            pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_FIFOCON;

            if ((pEndpoint->dBytesRemaining == 0)
                || (wPacketSize < pEndpoint->wMaxPacketSize)) {

                pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_RXOUT;

                // Disable interrupt if this is not a control endpoint
                if ((AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])
                    != AT91C_OTGHS_EPT_TYPE_CTL_EPT) {

                    pInterface->OTGHS_DEVIDR = 1<<SHIFT_INTERUPT<<bEndpoint;
                }

                OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
        }
    }

    // SETUP packet received
    if(ISSET(dStatus, AT91C_OTGHS_RXSTP)) {

        TRACE_DEBUG_L("Stp ");

        // If a transfer was pending, complete it
        // Handle the case where during the status phase of a control write
        // transfer, the host receives the device ZLP and ack it, but the ack
        // is not received by the device
        if ((pEndpoint->dState == endpointStateWrite)
            || (pEndpoint->dState == endpointStateRead)) {

            OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
        }

        // Copy the setup packet in S_usb
        OTGHS_GetSetup(pUsb);

        // Acknowledge setup packet
        pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_RXSTP;

        // Forward the request to the upper layer
        USB_NewRequestCallback(pUsb);
    }

    // STALL sent
    if (ISSET(dStatus, AT91C_OTGHS_STALL)) {

        TRACE_WARNING("Sta 0x%X [%d] ", dStatus, bEndpoint);

        // Acknowledge STALL interrupt and disable it
        pInterface->OTGHS_DEVEPTCCR[bEndpoint] = AT91C_OTGHS_STALL;
        //pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_STALL;

        // If the endpoint is not halted, clear the stall condition
        if (pEndpoint->dState != endpointStateHalted) {

            TRACE_WARNING("_ " );
            // Acknowledge the stall RQ flag
            pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_STALLRQ;
        }

    }

}


//------------------------------------------------------------------------------
//      Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// \brief  Configure an endpoint with the provided endpoint descriptor
// \param  pUsb    Pointer to a S_usb instance
// \param  pEpDesc Pointer to the endpoint descriptor
// \return true if the endpoint is now configured, false otherwise
// \see    S_usb_endpoint_descriptor
// \see    S_usb
//------------------------------------------------------------------------------
static bool OTGHS_ConfigureEndpoint(const S_usb *pUsb,
                             const S_usb_endpoint_descriptor *pEpDesc)
{
    AT91PS_OTGHS   pInterface = OTGHS_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint;
    unsigned char  bEndpoint;
    unsigned char  bType;
    unsigned char  endpointDir;
    unsigned short sizeEpt = 0;

    // Maximum packet size configuration value
    if( pEpDesc->wMaxPacketSize == 8 ) {
        sizeEpt = AT91C_OTGHS_EPT_SIZE_8;
    } else if ( pEpDesc->wMaxPacketSize == 16 ) {
        sizeEpt = AT91C_OTGHS_EPT_SIZE_16;
    } else if ( pEpDesc->wMaxPacketSize == 32 ) {
        sizeEpt = AT91C_OTGHS_EPT_SIZE_32;
    } else if ( pEpDesc->wMaxPacketSize == 64 ) {
        sizeEpt = AT91C_OTGHS_EPT_SIZE_64;
    } else if ( pEpDesc->wMaxPacketSize == 128 ) {
        sizeEpt = AT91C_OTGHS_EPT_SIZE_128;
    } else if ( pEpDesc->wMaxPacketSize == 256 ) {
        sizeEpt = AT91C_OTGHS_EPT_SIZE_256;
    } else if ( pEpDesc->wMaxPacketSize == 512 ) {
        sizeEpt = AT91C_OTGHS_EPT_SIZE_512;
    } else if ( pEpDesc->wMaxPacketSize == 1024 ) {
        sizeEpt = AT91C_OTGHS_EPT_SIZE_1024;
    } //else {
    //  sizeEpt = 0; // control endpoint
    //}

    // if pEpDesc == 0 then initialize the control endpoint
    if (pEpDesc == (S_usb_endpoint_descriptor const *) 0) {

        bEndpoint = 0;
        bType = 0;    // Control endpoint
    }
    else {
        // The endpoint number
        bEndpoint   = (unsigned char) (pEpDesc->bEndpointAddress & 0x7);
        // Transfer type: Control, Isochronous, Bulk, Interrupt
        bType = (unsigned char) (pEpDesc->bmAttributes     & 0x3);
        // Direction, ignored for control endpoints
        endpointDir  = (unsigned char) (pEpDesc->bEndpointAddress & (1<<7));
    }

    // Get pointer on endpoint
    pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
    if (pEndpoint == 0) {

        return false;
    }

    // Configure wMaxPacketSize
    if (pEpDesc != 0) {

        pEndpoint->wMaxPacketSize = pEpDesc->wMaxPacketSize;
    }
    else {

        pEndpoint->wMaxPacketSize = USB_ENDPOINT0_MAXPACKETSIZE;
    }

    // Abort the current transfer is the endpoint was configured and in
    // Write or Read state
    if ((pEndpoint->dState == endpointStateRead)
        || (pEndpoint->dState == endpointStateWrite)) {

        OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
    }

    // Enter in IDLE state
    pEndpoint->dState = endpointStateIdle;

    // Reset Endpoint Fifos
    pInterface->OTGHS_DEVEPT |= (1<<bEndpoint<<16);
    pInterface->OTGHS_DEVEPT &= ~(1<<bEndpoint<<16);

    // Enable endpoint
    pInterface->OTGHS_DEVEPT |= (1<<bEndpoint);

    // Configure endpoint
    switch (bType) {

        //-------------------------
        case ENDPOINT_TYPE_CONTROL:
        //-------------------------
            TRACE_INFO("Control[%d]\n\r",bEndpoint);

            //! Configure endpoint
            pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
                            AT91C_OTGHS_EPT_SIZE_64 | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_CTL_EPT | AT91C_OTGHS_BK_NUMBER_1;

            // Enable RXSTP interrupt
            pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_RXSTP;

            // Enable endpoint IT
            pInterface->OTGHS_DEVIER = 1<<SHIFT_INTERUPT<<bEndpoint;

            break;

        //-----------------------------
        case ENDPOINT_TYPE_ISOCHRONOUS:
        //-----------------------------
            if (endpointDir) {
                TRACE_INFO("Iso In[%d]\n\r",bEndpoint);

                //! Configure endpoint
#ifndef DMA
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif

            }
            else {
                TRACE_INFO("Iso Out[%d]\n\r",bEndpoint);

                //! Configure endpoint
#ifndef DMA
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] =  AT91C_OTGHS_ALLOC |
                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_ISO_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif

            }
            break;

        //----------------------
        case ENDPOINT_TYPE_BULK:
        //----------------------
            if (endpointDir) {
                TRACE_INFO("Bulk In(%d)[%d] ",bEndpoint, pEpDesc->wMaxPacketSize);
                //! Configure endpoint
#ifndef DMA
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif

            }
            else {
                TRACE_INFO("Bulk Out(%d)[%d]\n\r",bEndpoint, pEpDesc->wMaxPacketSize);
                //! Configure endpoint
#ifndef DMA
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] =  AT91C_OTGHS_ALLOC |
                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_BUL_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif
            }
            break;

        //---------------------------
        case ENDPOINT_TYPE_INTERRUPT:
        //---------------------------
            if (endpointDir) {
                TRACE_INFO("Interrupt In[%d]\n\r",bEndpoint);
                //! Configure endpoint
#ifndef DMA
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC |
                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
                                              sizeEpt | AT91C_OTGHS_EPT_DIR_IN | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif

            }
            else {
                TRACE_INFO("Interrupt Out[%d]\n\r",bEndpoint);
                //! Configure endpoint
#ifndef DMA
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] =  AT91C_OTGHS_ALLOC |
                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
#else
                pInterface->OTGHS_DEVEPTCFG[bEndpoint] = AT91C_OTGHS_ALLOC | AT91C_OTGHS_AUTOSW |
                                             sizeEpt | AT91C_OTGHS_EPT_DIR_OUT | AT91C_OTGHS_EPT_TYPE_INT_EPT | AT91C_OTGHS_BK_NUMBER_2;
#endif

            }
            break;

        //------
        default:
        //------
            TRACE_ERROR(" unknown endpoint type\n\r");
            return false;
    }

    // Check if the configuration is ok
    if (ISCLEARED(pInterface->OTGHS_DEVEPTCSR[bEndpoint], AT91C_OTGHS_CFGOK)) {

        TRACE_FATAL("F: OTGHS_ConfigureEndpoint: Cannot configure endpoint\n\r");
        return false;
    }

    return true;
}


//------------------------------------------------------------------------------
//      Interrupt service routine
//------------------------------------------------------------------------------
#ifdef DMA
//----------------------------------------------------------------------------
//! \fn    OTGHS_DmaHandler
//! \brief This function (ISR) handles DMA interrupts
//----------------------------------------------------------------------------
static void OTGHS_DmaHandler(const S_usb *pUsb, unsigned char endpoint)
{
    AT91PS_OTGHS   pInterface = OTGHS_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, endpoint);
    unsigned int   csr;

    csr = pInterface->OTGHS_DEVDMA[endpoint].OTGHS_DEVDMASTATUS;
    pInterface->OTGHS_DEVIDR = (1<<SHIFT_DMA<<endpoint);

    if((csr & AT91C_OTGHS_END_BF_ST) || (csr & AT91C_OTGHS_END_TR_ST)) {
        // READ
        TRACE_DEBUG_M("END_BF_ST\n\r");
        pEndpoint->dBytesTransferred = pEndpoint->dBytesBuffered;
        pEndpoint->dBytesBuffered = 0;

        TRACE_DEBUG_M("dBytesBuffered: 0x%x\n\r",pEndpoint->dBytesBuffered);
        TRACE_DEBUG_M("dBytesRemaining: 0x%x\n\r",pEndpoint->dBytesRemaining);
        TRACE_DEBUG_M("dBytesTransferred: 0x%x\n\r",pEndpoint->dBytesTransferred);

        OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
        pEndpoint->dState = endpointStateIdle;
    }
    else {
        TRACE_FATAL("Probleme IT DMA\n\r");
    }
}
#endif


//------------------------------------------------------------------------------
// \brief  OTGHS interrupt handler
//
//         Manages device resume, suspend, end of bus reset. Forwards endpoint
//         interrupts to the appropriate handler.
// \param  pUsb Pointer to a S_usb instance
//------------------------------------------------------------------------------
static void OTGHS_Handler(const S_usb *pUsb)
{
    AT91PS_OTGHS  pInterface = OTGHS_GetDriverInterface(pUsb);
    unsigned int  dStatus;
    unsigned char numIT;

    if ( (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED))
       && (ISSET(USB_GetState(pUsb), USB_STATE_POWERED))){

        LED_TOGGLE(LED_USB);
    }

    TRACE_DEBUG_H("Hlr ");

    // Get General interrupts status
    dStatus = pInterface->OTGHS_SR & pInterface->OTGHS_CTRL & 0xFF;
    while (dStatus != 0) {

        if(ISSET(dStatus, AT91C_OTGHS_VBUSTI))
        {
            TRACE_DEBUG_M("__VBus\n\r");

            USB_Attach(pUsb);

            // Acknowledge the interrupt
            pInterface->OTGHS_SCR = AT91C_OTGHS_VBUSTI;
        }

        // Don't treat others interrupt for this time
        pInterface->OTGHS_SCR = AT91C_OTGHS_IDT    | AT91C_OTGHS_SRP 
                              | AT91C_OTGHS_VBERR  | AT91C_OTGHS_BCERR
                              | AT91C_OTGHS_ROLEEX | AT91C_OTGHS_HNPERR
                              | AT91C_OTGHS_STO;

        dStatus = pInterface->OTGHS_SR & pInterface->OTGHS_CTRL & 0xFF;
    }


    // Get OTG Device interrupts status
    dStatus = pInterface->OTGHS_DEVISR & pInterface->OTGHS_DEVIMR;
    TRACE_DEBUG_H("OTGHS_DEVISR:0x%X\n\r", pInterface->OTGHS_DEVISR);
    while (dStatus != 0) {

        // Start Of Frame (SOF)
        if (ISSET(dStatus, AT91C_OTGHS_SOF)) {
            TRACE_DEBUG_L("SOF ");

            // Invoke the SOF callback
            USB_StartOfFrameCallback(pUsb);

            // Acknowledge interrupt
            SET(pInterface->OTGHS_DEVICR, AT91C_OTGHS_SOF);
            CLEAR(dStatus, AT91C_OTGHS_SOF);
        }

        // Suspend
        else if (dStatus & AT91C_OTGHS_SUSP) {

            TRACE_DEBUG_M("S ");

            if (!ISSET(USB_GetState(pUsb), USB_STATE_SUSPENDED)) {

                // The device enters the Suspended state
                //      MCK + UDPCK must be off
                //      Pull-Up must be connected
                //      Transceiver must be disabled

⌨️ 快捷键说明

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