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

📄 udp.c

📁 AT91SAM9261的USB设备驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
        if (pEndpoint->dState != endpointStateRead&&pEndpoint->dState!=endpointStateIdle)
        {

            // Endpoint is NOT in Read state
            if (ISCLEARED(dStatus, AT91C_UDP_EPTYPE)
                && ISCLEARED(dStatus, 0xFFFF0000)) {

                // Control endpoint, 0 bytes received
                // Acknowledge the data and finish the current transfer

                UDP_ClearRXFlag(pUsb, bEndpoint);

                UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
            else if (ISSET(dStatus, AT91C_UDP_FORCESTALL)) {

                // Non-control endpoint
                // Discard stalled data
                UDP_ClearRXFlag(pUsb, bEndpoint);
            }
            else {

                // Non-control endpoint
                // Nak data
                SET(pInterface->UDP_IDR, 1 << bEndpoint);
            }
        }
        else {

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


            UDP_GetPayload(pUsb, bEndpoint, wPacketSize);
            UDP_ClearRXFlag(pUsb, bEndpoint);

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

                // Disable interrupt if this is not a control endpoint
                if (!ISCLEARED(dStatus, AT91C_UDP_EPTYPE)) {

                    SET(pInterface->UDP_IDR, 1 << bEndpoint);
                }

                UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
            }
        }
    }
    // SETUP packet received
    if (ISSET(dStatus, AT91C_UDP_RXSETUP)) {

        // 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)) {

            UDP_EndOfTransfer(pEndpoint, USB_STATUS_SUCCESS);
        }

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

        // Set the DIR bit before clearing RXSETUP in Control IN sequence
        if (USB_GetSetup(pUsb)->bmRequestType & 0x80) {

            UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_DIR);
        }

        UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_RXSETUP);

        // Forward the request to the upper layer
        USB_NewRequestCallback(pUsb);
    }
    // STALL sent
    if (ISSET(dStatus, AT91C_UDP_STALLSENT)) {


        // Acknowledge the stall flag
        UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_STALLSENT);

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

            UDP_CLEAREPFLAGS(pUsb, bEndpoint, AT91C_UDP_FORCESTALL);
        }
    }
}

//------------------------------------------------------------------------------
//      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
//------------------------------------------------------------------------------
bool UDP_ConfigureEndpoint(const S_usb                     *pUsb,
                           const S_usb_endpoint_descriptor *pEpDesc)
{
    AT91PS_UDP     pInterface = UDP_GetDriverInterface(pUsb);
    S_usb_endpoint *pEndpoint;
    unsigned char  bEndpoint;
    unsigned char  bType;
    bool           isINEndpoint;
    unsigned int   dFlags;

    // NULL descriptor -> Control endpoint 0
    if (pEpDesc == 0) {

        bEndpoint = 0;
        bType = ENDPOINT_TYPE_CONTROL;
        isINEndpoint = false;
    }
    else {

        bEndpoint = (unsigned char) (pEpDesc->bEndpointAddress & 0x7);
        bType = (unsigned char) (pEpDesc->bmAttributes & 0x3);

        if (ISSET(pEpDesc->bEndpointAddress, 1 << 7)) {

            isINEndpoint = true;
        }
        else {

            isINEndpoint = false;
        }
    }

    // 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)) {

        UDP_EndOfTransfer(pEndpoint, USB_STATUS_RESET);
    }

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

    // Reset Endpoint Fifos
    SET(pInterface->UDP_RSTEP, 1 << bEndpoint);
    CLEAR(pInterface->UDP_RSTEP, 1 << bEndpoint);

    // Configure endpoint
    dFlags = AT91C_UDP_EPEDS;
    SET(dFlags, bType << UDP_EPTYPE_INDEX);

    if (isINEndpoint) {

        SET(dFlags, 1 << UDP_EPDIR_INDEX);
    }

    if (bType == ENDPOINT_TYPE_CONTROL) 
    {

        SET(pInterface->UDP_IER, 1 << bEndpoint);
    }


    UDP_SETEPFLAGS(pUsb, bEndpoint, dFlags);

    return true;
}

//------------------------------------------------------------------------------
// \brief  UDP 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
//------------------------------------------------------------------------------
void UDP_Handler(const S_usb *pUsb)
{
    AT91PS_UDP          pInterface = UDP_GetDriverInterface(pUsb);
    unsigned int        dStatus;
    unsigned char       bEndpoint;
    // Get interrupts status
    dStatus = pInterface->UDP_ISR & pInterface->UDP_IMR & ISR_MASK;

    // Handle all UDP interrupts
    while (dStatus != 0) {

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

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

        // Suspend
        if (dStatus == AT91C_UDP_RXSUSP) {


            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);


            // 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)) {


            // 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);
            }
        }

        // 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;
        }

        
    }
}

//------------------------------------------------------------------------------
// \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;
    }


    // 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,

⌨️ 快捷键说明

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