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

📄 usbd_otghs.c

📁 Atmel的AT91SAM9263芯片的usb存储源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
                // Enable wakeup
                SET(pInterface->OTGHS_DEVIER, AT91C_OTGHS_EORST | AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM);

                // Acknowledge interrupt
                pInterface->OTGHS_DEVICR = AT91C_OTGHS_SUSP;
                SET(*(pUsb->pState), USB_STATE_SUSPENDED);
                OTGHS_DisableTransceiver(pUsb);
                OTGHS_DisableMCK(pUsb);
                OTGHS_DisableOTGHSCK(pUsb);

                // Invoke the Suspend callback

                USB_SuspendCallback(pUsb);
            }
        }

        // Resume
        else if (ISSET(dStatus, AT91C_OTGHS_WAKEUP)
              || ISSET(dStatus, AT91C_OTGHS_EORSM)) {

            // Invoke the Resume callback
            USB_ResumeCallback(pUsb);

            TRACE_DEBUG_M("R ");

            // The device enters Configured state
            //      MCK + UDPCK must be on
            //      Pull-Up must be connected
            //      Transceiver must be enabled

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

                // Powered state
                OTGHS_EnableMCK(pUsb);
                OTGHS_EnableOTGHSCK(pUsb);

                // Default state
                if (ISSET(USB_GetState(pUsb), USB_STATE_DEFAULT)) {

                    OTGHS_EnableTransceiver(pUsb);
                }

                CLEAR(*(pUsb->pState), USB_STATE_SUSPENDED);
            }
            pInterface->OTGHS_DEVICR = 
                (AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM | AT91C_OTGHS_SUSP);

            pInterface->OTGHS_DEVIER = (AT91C_OTGHS_EORST | AT91C_OTGHS_SUSP);
            pInterface->OTGHS_DEVICR = (AT91C_OTGHS_WAKEUP | AT91C_OTGHS_EORSM);
            pInterface->OTGHS_DEVIDR = AT91C_OTGHS_WAKEUP;

        }

        // End of bus reset
        else if (dStatus & AT91C_OTGHS_EORST) {

            TRACE_DEBUG_M("EoB ");
            // The device enters the Default state
            //      MCK + UDPCK are already enabled
            //      Pull-Up is already connected
            //      Transceiver must be enabled
            //      Endpoint 0 must be enabled
            SET(*(pUsb->pState), USB_STATE_DEFAULT);

            OTGHS_EnableTransceiver(pUsb);

            // The device leaves the Address & Configured states
            CLEAR(*(pUsb->pState), USB_STATE_ADDRESS | USB_STATE_CONFIGURED);
            OTGHS_ResetEndpoints(pUsb);
            OTGHS_DisableEndpoints(pUsb);
            OTGHS_ConfigureEndpoint(pUsb, 0);

            // Flush and enable the Suspend interrupt
            SET(pInterface->OTGHS_DEVICR, AT91C_OTGHS_WAKEUP | AT91C_OTGHS_SUSP);

            // Enable the Start Of Frame (SOF) interrupt if needed
            if (pUsb->pCallbacks->startOfFrame != 0) {

                SET(pInterface->OTGHS_DEVIER, AT91C_OTGHS_SOF);
            }

            // Invoke the Reset callback
            USB_ResetCallback(pUsb);

            // Acknowledge end of bus reset interrupt
            pInterface->OTGHS_DEVICR = AT91C_OTGHS_EORST;
        }

        // Handle upstream resume interrupt
        else if (dStatus & AT91C_OTGHS_UPRSM) {

            TRACE_DEBUG_L("  External resume interrupt\n\r");

            // - Acknowledge the IT
            pInterface->OTGHS_DEVICR = AT91C_OTGHS_UPRSM;
        }

        // Endpoint interrupts
        else {
#ifndef DMA
            // Handle endpoint interrupts
            for (numIT = 0; numIT < NUM_IT_MAX; numIT++) {
                if( dStatus & (1<<SHIFT_INTERUPT<<numIT) ) {
                    OTGHS_EndpointHandler(pUsb, numIT);
                }
            }
#else
            // Handle endpoint control interrupt
            if( dStatus & (1<<SHIFT_INTERUPT<<0) ) {
                OTGHS_EndpointHandler(pUsb, 0);
            }
            // Handle DMA interrupts
            for(numIT = 1; numIT <= NUM_IT_MAX_DMA; numIT++) {
                if( dStatus & (1<<SHIFT_DMA<<numIT) ) {
                    OTGHS_DmaHandler(pUsb, numIT);
                }
            }
#endif
        }

        // Retrieve new interrupt status
        dStatus = (pInterface->OTGHS_DEVISR) & (pInterface->OTGHS_DEVIMR);

        // Mask unneeded interrupts
        if (!ISSET(USB_GetState(pUsb), USB_STATE_DEFAULT)) {

            dStatus &= AT91C_OTGHS_EORST | AT91C_OTGHS_SOF;
        }

        TRACE_DEBUG_H("\n\r");

        if (dStatus != 0) {

            TRACE_DEBUG_L("  - ");
        }
    }

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

        LED_TOGGLE(LED_USB);
    }
}

//------------------------------------------------------------------------------
// \brief  Sends data through an USB endpoint
//
//         Sets up the transfer descriptor, write one or two data payloads
//         (depending on the number of FIFO banks for the endpoint) and then
//         starts the actual transfer. The operation is complete when all
//         the data has been sent.
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \param  pData     Pointer to a buffer containing the data to send
// \param  dLength   Length of the data buffer
// \param  fCallback Optional function to invoke when the transfer finishes
// \param  pArgument Optional argument for the callback function
// \return Operation result code
// \see    Operation result codes
// \see    Callback_f
// \see    S_usb
//------------------------------------------------------------------------------
static char OTGHS_Write(const S_usb   *pUsb,
                        unsigned char bEndpoint,
                        const void    *pData,
                        unsigned int  dLength,
                        Callback_f    fCallback,
                        void          *pArgument)
{
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);
    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);

    // Check that the endpoint is in Idle state
    if (pEndpoint->dState != endpointStateIdle) {

        return USB_STATUS_LOCKED;
    }

    TRACE_DEBUG_L("Write%d(%d) ", bEndpoint, dLength);

    // Setup the transfer descriptor
    pEndpoint->pData = (char *) pData;
    pEndpoint->dBytesRemaining = dLength;
    pEndpoint->dBytesBuffered = 0;
    pEndpoint->dBytesTransferred = 0;
    pEndpoint->fCallback = fCallback;
    pEndpoint->pArgument = pArgument;
    pEndpoint->isDataSent = false;
    
    // Send one packet
    pEndpoint->dState = endpointStateWrite;

#ifdef DMA
    // Test if endpoint type control
    if (AT91C_OTGHS_EPT_TYPE_CTL_EPT == (AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])) {
#endif
        // Enable endpoint IT
        pInterface->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
        pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_TXINI;

#ifdef DMA
    }
    else {

        // others endoint (not control)
        pEndpoint->dBytesBuffered = pEndpoint->dBytesRemaining;
        pEndpoint->dBytesRemaining = 0;

        pInterface->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMAADDRESS = (unsigned int) pEndpoint->pData;

        // Enable IT DMA
        pInterface->OTGHS_DEVIER = (1<<SHIFT_DMA<<bEndpoint);

        pInterface->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL = 
             (((pEndpoint->dBytesBuffered<<16)&AT91C_OTGHS_BUFF_LENGTH)
               | AT91C_OTGHS_END_B_EN
               | AT91C_OTGHS_END_BUFFIT
               | AT91C_OTGHS_CHANN_ENB);

    }
#endif

    return USB_STATUS_SUCCESS;
}

//------------------------------------------------------------------------------
// \brief  Reads incoming data on an USB endpoint
//
//         This methods sets the transfer descriptor and activate the endpoint
//         interrupt. The actual transfer is then carried out by the endpoint
//         interrupt handler. The Read operation finishes either when the
//         buffer is full, or a short packet (inferior to endpoint maximum
//         packet size) is received.
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \param  pData     Pointer to a buffer to store the received data
// \param  dLength   Length of the receive buffer
// \param  fCallback Optional callback function
// \param  pArgument Optional callback argument
// \return Operation result code
// \see    Callback_f
// \see    S_usb
//------------------------------------------------------------------------------
static char OTGHS_Read(const S_usb   *pUsb,
                       unsigned char bEndpoint,
                       void          *pData,
                       unsigned int  dLength,
                       Callback_f    fCallback,
                       void          *pArgument)
{
    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);

    //! Return if the endpoint is not in IDLE state
    if (pEndpoint->dState != endpointStateIdle) {

        return USB_STATUS_LOCKED;
    }

    TRACE_DEBUG_M("Read%d(%d) ", bEndpoint, dLength);

    // Endpoint enters Read state
    pEndpoint->dState = endpointStateRead;

    //! Set the transfer descriptor
    pEndpoint->pData = (char *) pData;
    pEndpoint->dBytesRemaining = dLength;
    pEndpoint->dBytesBuffered = 0;
    pEndpoint->dBytesTransferred = 0;
    pEndpoint->fCallback = fCallback;
    pEndpoint->pArgument = pArgument;

#ifdef DMA
    // Test if endpoint type control
    if (AT91C_OTGHS_EPT_TYPE_CTL_EPT == (AT91C_OTGHS_EPT_TYPE & pInterface->OTGHS_DEVEPTCFG[bEndpoint])) {
#endif
        // Control endpoint
        // Enable endpoint IT
        pInterface->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
        pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_RXOUT;
#ifdef DMA
    }
    else {

        // others endoint (not control)
        pEndpoint->dBytesBuffered = pEndpoint->dBytesRemaining;
        pEndpoint->dBytesRemaining = 0;

        // Enable IT DMA
        pInterface->OTGHS_DEVIER = (1<<SHIFT_DMA<<bEndpoint);

        pInterface->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMAADDRESS = (unsigned int) pEndpoint->pData;

        pInterface->OTGHS_DEVDMA[bEndpoint].OTGHS_DEVDMACONTROL = \
                             ( (pEndpoint->dBytesBuffered<<16)
                               | AT91C_OTGHS_END_TR_EN
                               | AT91C_OTGHS_END_TR_IT
                               | AT91C_OTGHS_END_B_EN
                               | AT91C_OTGHS_END_BUFFIT
                               | AT91C_OTGHS_CHANN_ENB);
    }
#endif

  return USB_STATUS_SUCCESS;
}

//------------------------------------------------------------------------------
// \brief  Clears, sets or returns the Halt state on specified endpoint
//
//         When in Halt state, an endpoint acknowledges every received packet
//         with a STALL handshake. This continues until the endpoint is
//         manually put out of the Halt state by calling this function.
// \param  pUsb Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \param  bRequest  Request to perform
//                   -> USB_SET_FEATURE, USB_CLEAR_FEATURE, USB_GET_STATUS
// \return true if the endpoint is currently Halted, false otherwise
// \see    S_usb
//------------------------------------------------------------------------------
static bool OTGHS_Halt(const S_usb   *pUsb,
                       unsigned char bEndpoint,
                       unsigned char bRequest)
{
    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);

    // Clear the Halt feature of the endpoint if it is enabled
    if (bRequest == USB_CLEAR_FEATURE) {

        TRACE_DEBUG_L("Unhalt%d ", bEndpoint);

        // Return endpoint to Idle state
        pEndpoint->dState = endpointStateIdle;

        // Clear FORCESTALL flag

        // Disable stall on endpoint
        pInterface->OTGHS_DEVEPTCDR[bEndpoint] = AT91C_OTGHS_STALLRQ;
        pEndpoint->dState = endpointStateIdle;

        // Reset data-toggle
        pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_RSTDT;
    }
    // Set the Halt feature on the endpoint if it is not already enabled
    // and the endpoint is not disabled
    else if ((bRequest == USB_SET_FEATURE)
             && (pEndpoint->dState != endpointStateHalted)
             && (pEndpoint->dState != endpointStateDisabled)) {

        TRACE_DEBUG_L("Halt%d ", bEndpoint);

        // Abort the current transfer if necessary
        OTGHS_EndOfTransfer(pEndpoint, USB_STATUS_ABORTED);

        // Put endpoint into Halt state
        pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_STALLRQ;
        pEndpoint->dState = endpointStateHalted;

        // Enable the endpoint interrupt
        pInterface->OTGHS_DEVIER = (1<<SHIFT_INTERUPT<<bEndpoint);
    }

    // Return the endpoint halt status
    if (pEndpoint->dState == endpointStateHalted) {

        return true;
    }
    else {

        return false;
    }
}

//------------------------------------------------------------------------------
// \brief  Causes the endpoint to acknowledge the next received packet with
//         a STALL handshake.
//
//         Further packets are then handled normally.
// \param  pUsb      Pointer to a S_usb instance
// \param  bEndpoint Index of endpoint
// \return Operation result code
// \see    S_usb
//------------------------------------------------------------------------------
static char OTGHS_Stall(const S_usb *pUsb,
                        unsigned char bEndpoint)
{
    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);

    // Check that endpoint is in Idle state
    if (pEndpoint->dState != endpointStateIdle) {

        TRACE_WARNING("W: UDP_Stall: Endpoint%d locked\n\r", bEndpoint);
        return USB_STATUS_LOCKED;
    }

    TRACE_DEBUG_L("Stall%d ", bEndpoint);

    pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_STALL;
    pInterface->OTGHS_DEVEPTCER[bEndpoint] = AT91C_OTGHS_STALLRQ;

    return USB_STATUS_SUCCESS;
}

//------------------------------------------------------------------------------
// \brief  Activates a remote wakeup procedure
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
static void OTGHS_RemoteWakeUp(const S_usb *pUsb)
{
    AT91PS_OTGHS pInterface = OTGHS_GetDriverInterface(pUsb);

    OTGHS_EnableMCK(pUsb);
    OTGHS_EnableOTGHSCK(pUsb);
    OTGHS_EnableTransceiver(pUsb);

    TRACE_DEBUG_L("Remote WakeUp ");

    //! Enable wakeup interrupt
    //pInterface->OTGHS_DEVIER = AT91C_OTGHS_UPRSM;

⌨️ 快捷键说明

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