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

📄 udp.c

📁 This software package contains the USB framework core developped by ATMEL, as well as two HID driv
💻 C
📖 第 1 页 / 共 4 页
字号:
    // Handle all UDP interrupts
    while (dStatus != 0) {

        // Start Of Frame (SOF)
        if (ISSET(dStatus, AT91C_UDP_SOFINT)) {

            TRACE_DEBUG_L("SOF ");

            // Invoke the SOF callback
            USB_StartOfFrameCallback(pUsb);

            // Acknowledge interrupt
            SET(pInterface->UDP_ICR, AT91C_UDP_SOFINT);
            CLEAR(dStatus, AT91C_UDP_SOFINT);
        }

        // Suspend
        if (dStatus == AT91C_UDP_RXSUSP) {

            TRACE_DEBUG_L("Susp ");

            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

                // Enable wakeup
                SET(pInterface->UDP_IER, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM);

                // Acknowledge interrupt
                SET(pInterface->UDP_ICR, AT91C_UDP_RXSUSP);

                SET(*(pUsb->pState), USB_STATE_SUSPENDED);
                UDP_DisableTransceiver(pUsb);
                UDP_DisableMCK(pUsb);
                UDP_DisableUDPCK(pUsb);

                // Invoke the Suspend callback
                USB_SuspendCallback(pUsb);

            }
        }
        // Resume
        else if (ISSET(dStatus, AT91C_UDP_WAKEUP)
              || ISSET(dStatus, AT91C_UDP_RXRSM)) {

            // Invoke the Resume callback
            USB_ResumeCallback(pUsb);

            TRACE_DEBUG_L("Res ");

            // 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
                UDP_EnableMCK(pUsb);
                UDP_EnableUDPCK(pUsb);

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

                    UDP_EnableTransceiver(pUsb);
                }

                CLEAR(*(pUsb->pState), USB_STATE_SUSPENDED);
            }
            SET(pInterface->UDP_ICR,
                AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP);
            SET(pInterface->UDP_IDR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM);
        }
        // End of bus reset
        else if (ISSET(dStatus, AT91C_UDP_ENDBUSRES)) {

            TRACE_DEBUG_L("EoBRes ");

            // 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);
            UDP_EnableTransceiver(pUsb);

            // The device leaves the Address & Configured states
            CLEAR(*(pUsb->pState), USB_STATE_ADDRESS | USB_STATE_CONFIGURED);
            UDP_ResetEndpoints(pUsb);
            UDP_DisableEndpoints(pUsb);
            UDP_ConfigureEndpoint(pUsb, 0);

            // Flush and enable the Suspend interrupt
            SET(pInterface->UDP_ICR,
                AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP);

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

                SET(pInterface->UDP_IER, AT91C_UDP_SOFINT);
            }

            // Invoke the Reset callback
            USB_ResetCallback(pUsb);

            // Acknowledge end of bus reset interrupt
            SET(pInterface->UDP_ICR, AT91C_UDP_ENDBUSRES);
        }
        // Endpoint interrupts
        else {

            while (dStatus != 0) {

                // Get endpoint index
                bEndpoint = lastSetBit(dStatus);
                UDP_EndpointHandler(pUsb, bEndpoint);

                /*CLEAR(pInterface->UDP_CSR[bEndpoint],
                      AT91C_UDP_TXCOMP | AT91C_UDP_RX_DATA_BK0
                    | AT91C_UDP_RX_DATA_BK1 | AT91C_UDP_RXSETUP
                    | AT91C_UDP_STALLSENT);*/

                CLEAR(dStatus, 1 << bEndpoint);

                if (dStatus != 0) {

                    TRACE_DEBUG_L("\n\r  - ");
                }
            }
        }

        // Retrieve new interrupt status
        dStatus = pInterface->UDP_ISR & pInterface->UDP_IMR & ISR_MASK;

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

            dStatus &= AT91C_UDP_ENDBUSRES | AT91C_UDP_SOFINT;
        }

        TRACE_DEBUG_L("\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
//------------------------------------------------------------------------------
char UDP_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_UDP     pInterface = UDP_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;

    // Send one packet
    pEndpoint->dState = endpointStateWrite;
    UDP_WritePayload(pUsb, bEndpoint);
    UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_TXPKTRDY);

    // If double buffering is enabled and there is data remaining,
    // prepare another packet
    if ((pEndpoint->dNumFIFO > 1) && (pEndpoint->dBytesRemaining > 0)) {

        UDP_WritePayload(pUsb, bEndpoint);
    }

    // Enable interrupt on endpoint
    SET(pInterface->UDP_IER, 1 << bEndpoint);

    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
//------------------------------------------------------------------------------
char UDP_Read(const S_usb   *pUsb,
              unsigned char bEndpoint,
              void          *pData,
              unsigned int  dLength,
              Callback_f    fCallback,
              void          *pArgument)
{
    AT91PS_UDP     pInterface = UDP_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_L("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;

    // Enable interrupt on endpoint
    SET(pInterface->UDP_IER, 1 << bEndpoint);

    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
//------------------------------------------------------------------------------
bool UDP_Halt(const S_usb   *pUsb,
              unsigned char bEndpoint,
              unsigned char bRequest)
{
    AT91PS_UDP     pInterface = UDP_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
        UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_FORCESTALL);

        // Reset Endpoint Fifos, beware this is a 2 steps operation
        SET(pInterface->UDP_RSTEP, 1 << bEndpoint);
        CLEAR(pInterface->UDP_RSTEP, 1 << bEndpoint);
    }
    // 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
        UDP_EndOfTransfer(pEndpoint, USB_STATUS_ABORTED);

        // Put endpoint into Halt state
        UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_FORCESTALL);
        pEndpoint->dState = endpointStateHalted;

        // Enable the endpoint interrupt
        SET(pInterface->UDP_IER, 1 << bEndpoint);
    }

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

        return true;
    }
    else {

        return false;

⌨️ 快捷键说明

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