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

📄 usbd_udphs.c

📁 Atmel的AT91SAM9263芯片的usb存储源程序
💻 C
📖 第 1 页 / 共 5 页
字号:
        pTransfer = &(pEndpoint->transfer);

        // Reset endpoint transfer descriptor
        pTransfer->pData = 0;
        pTransfer->transferred = -1;
        pTransfer->buffered = -1;
        pTransfer->remaining = -1;
        pTransfer->fCallback = 0;
        pTransfer->pArgument = 0;

        // Reset endpoint state
        pEndpoint->bank = 0;
        pEndpoint->state = UDP_ENDPOINT_DISABLED;
    }
}


//------------------------------------------------------------------------------
// Disable all endpoints (except control endpoint 0), aborting current transfers
// if necessary.
//------------------------------------------------------------------------------
static void UDPHS_DisableEndpoints( void )
{
    unsigned char bEndpoint;

    // Disable each endpoint, terminating any pending transfer
    // Control endpoint 0 is not disabled
    for( bEndpoint = 1; bEndpoint < BOARD_USB_NUMENDPOINTS; bEndpoint++ ) {

        UDPHS_EndOfTransfer( bEndpoint, USBD_STATUS_ABORTED );
        endpoints[bEndpoint].state = UDP_ENDPOINT_DISABLED;
    }
}

//------------------------------------------------------------------------------
//  Function: UDP_IsTransferFinished
//      Checks if an ongoing transfer on an endpoint has been completed.
//  Parameters:
//      bEndpoint - Endpoint number.
//  Returns:
//      1 if the current transfer on the given endpoint is complete; otherwise
//      0
//------------------------------------------------------------------------------
static unsigned char UDPHS_IsTransferFinished( unsigned char bEndpoint )
{
    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
    Transfer *pTransfer = &(pEndpoint->transfer);

    // Check if it is a Control endpoint
    //  -> Control endpoint must always finish their transfer with a zero-length
    //     packet
    if( AT91C_UDPHS_EPT_TYPE_CTL_EPT == 
        (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)) ) {

        return (pTransfer->buffered < pEndpoint->size);
    }
    // Other endpoints only need to transfer all the data
    else {

        return( (pTransfer->buffered <= pEndpoint->size) && (pTransfer->remaining == 0) );
    }
}

//------------------------------------------------------------------------------
// Endpoint interrupt handler.
//         Handle IN/OUT transfers, received SETUP packets and STALLing
// bEndpoint Index of endpoint
//------------------------------------------------------------------------------
static void UDPHS_EndpointHandler( unsigned char bEndpoint )
{
    Endpoint *pEndpoint = &(endpoints[bEndpoint]);
    Transfer *pTransfer = &(pEndpoint->transfer);
    unsigned int   status = AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSTA;
    unsigned short wPacketSize;
    USBGenericRequest request;

    trace_LOG(trace_DEBUG, "E%d ", bEndpoint);

    // Handle interrupts
    // IN packet sent
    if( (AT91C_UDPHS_TX_PK_RDY == (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTL & AT91C_UDPHS_TX_PK_RDY))
     && (0 == (status & AT91C_UDPHS_TX_PK_RDY )) ) {

        trace_LOG(trace_DEBUG, "Wr ");

        // Check that endpoint was in Sending state
        if( pEndpoint->state == UDP_ENDPOINT_SENDING ) {

            // End of transfer ?
            if( UDPHS_IsTransferFinished(bEndpoint) ) {

                trace_LOG(trace_DEBUG, "%d ", pTransfer->transferred);

                pTransfer->transferred += pTransfer->buffered;
                pTransfer->buffered = 0;

                // Disable interrupt if this is not a control endpoint
                if( AT91C_UDPHS_EPT_TYPE_CTL_EPT != (AT91C_UDPHS_EPT_TYPE&(AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)) ) {

#ifndef DMA
                    AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
#else
                    AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_DMA<<bEndpoint);
#endif
                }
                AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_TX_PK_RDY;

                UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
            }
            else {

                // Transfer remaining data
                trace_LOG(trace_DEBUG, "%d ", pEndpoint->size);
                pTransfer->transferred += pEndpoint->size;
                pTransfer->buffered -= pEndpoint->size;

                // Send next packet
                UDPHS_WritePayload(bEndpoint);
                AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY;
            }
        }
        else {

            trace_LOG(trace_FATAL, "Error Wr");
        }
    }

    // OUT packet received
    if( AT91C_UDPHS_RX_BK_RDY == (status & AT91C_UDPHS_RX_BK_RDY) ) {

        trace_LOG(trace_DEBUG, "Rd ");

        // Check that the endpoint is in Receiving state
        if (pEndpoint->state != UDP_ENDPOINT_RECEIVING) {

            // Endpoint is NOT in Read state
            if( (0 == (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG & AT91C_UDPHS_EPT_TYPE))
             && (0 == (status & AT91C_UDPHS_BYTE_COUNT)) ) {

                // Control endpoint, 0 bytes received
                // Acknowledge the data and finish the current transfer
                trace_LOG(trace_DEBUG, "Ack ");
                UDPHS_ClearRxFlag(bEndpoint);

                UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
            }
            // Check if the data has been STALLed
            else if( AT91C_UDPHS_FRCESTALL == (status & AT91C_UDPHS_FRCESTALL)) {

                // Discard STALLed data
                trace_LOG(trace_DEBUG, "Discard ");
                UDPHS_ClearRxFlag(bEndpoint);
            }
            // NAK the data
            else {

                trace_LOG(trace_DEBUG, "Nak ");
#ifndef DMA
                AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
#else
                AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_DMA<<bEndpoint);
#endif
            }
        }
        else {

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

            trace_LOG(trace_DEBUG, "%d ", wPacketSize);
            UDPHS_ReadPayload(bEndpoint, wPacketSize);
            UDPHS_ClearRxFlag(bEndpoint);

            // Check if the transfer is finished
            if ((pTransfer->remaining == 0) || (wPacketSize < pEndpoint->size)) {

                AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_RX_BK_RDY;

                // Disable interrupt if this is not a control endpoint
                if( AT91C_UDPHS_EPT_TYPE_CTL_EPT != (AT91C_UDPHS_EPT_TYPE & (AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCFG)) ) {

#ifndef DMA
                    AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_INTERUPT<<bEndpoint);
#else
                    AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1<<SHIFT_DMA<<bEndpoint);
#endif
                }
                UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
            }
        }
    }

    // STALL sent
    if( AT91C_UDPHS_STALL_SNT == (status & AT91C_UDPHS_STALL_SNT) ) {

        trace_LOG(trace_WARNING, "Sta 0x%X [%d] ", status, bEndpoint);

        // Acknowledge the stall flag
        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_STALL_SNT;

        // If the endpoint is not halted, clear the STALL condition
        if (pEndpoint->state != UDP_ENDPOINT_HALTED) {

            trace_LOG(trace_WARNING, "_ " );
            AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_FRCESTALL;
        }
    }

    // SETUP packet received
    if( AT91C_UDPHS_RX_SETUP == (status & AT91C_UDPHS_RX_SETUP) )  {

        trace_LOG(trace_DEBUG, "Stp ");

        // If a transfer was pending, complete it
        // Handles 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->state == UDP_ENDPOINT_RECEIVING)
            || (pEndpoint->state == UDP_ENDPOINT_SENDING)) {

            UDPHS_EndOfTransfer(bEndpoint, USBD_STATUS_SUCCESS);
        }
        // Copy the setup packet
        UDPHS_ReadRequest(&request);

        // Acknowledge setup packet
        AT91C_BASE_UDPHS->UDPHS_EPT[bEndpoint].UDPHS_EPTCLRSTA = AT91C_UDPHS_RX_SETUP;

        // Forward the request to the upper layer
        USBDCallbacks_RequestReceived(&request);
    }

}

//------------------------------------------------------------------------------
//      Interrupt service routine
//------------------------------------------------------------------------------
#ifdef DMA
//----------------------------------------------------------------------------
// \fn    UDPHS_DmaHandler
// \brief This function (ISR) handles dma interrupts
//----------------------------------------------------------------------------
static void UDPHS_DmaHandler( unsigned char bEndpoint )
{
    Endpoint     *pEndpoint = &(endpoints[bEndpoint]);
    Transfer     *pTransfer = &(pEndpoint->transfer);
    unsigned int  status;
    unsigned char result = USBD_STATUS_SUCCESS;

    status = AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;
    trace_LOG(trace_DEBUG, "Dma Ept%d ", bEndpoint);

    // Disable DMA interrupt to avoid receiving 2 interrupts (B_EN and TR_EN)
    AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL &=
        ~(AT91C_UDPHS_END_TR_EN | AT91C_UDPHS_END_B_EN);

    AT91C_BASE_UDPHS->UDPHS_IEN &= ~(1 << SHIFT_DMA << bEndpoint);

    if( AT91C_UDPHS_END_BF_ST == (status & AT91C_UDPHS_END_BF_ST) ) {

        trace_LOG(trace_DEBUG, "EndBuffer ");

        // BUFF_COUNT holds the number of untransmitted bytes.
        // BUFF_COUNT is equal to zero in case of good transfer
        pTransfer->transferred = pTransfer->buffered
                                 - ((status & AT91C_UDPHS_BUFF_COUNT) >> 16);
        pTransfer->buffered = ((status & AT91C_UDPHS_BUFF_COUNT) >> 16);

        pTransfer->remaining -= pTransfer->transferred;

        trace_LOG(trace_DEBUG, "\n\rR:%d ", pTransfer->remaining );
        trace_LOG(trace_DEBUG, "B:%d ", pTransfer->buffered );
        trace_LOG(trace_DEBUG, "T:%d ", pTransfer->transferred );

        if( (pTransfer->remaining + pTransfer->buffered) > 0 ) {

            // Prepare an other transfer
            if( pTransfer->remaining > DMA_MAX_FIFO_SIZE ) {

                pTransfer->buffered = DMA_MAX_FIFO_SIZE;    
            }
            else {
                pTransfer->buffered = pTransfer->remaining;
            }

            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMAADDRESS = 
                    (unsigned int)((pTransfer->pData)+(pTransfer->buffered));

            // Clear unwanted interrupts
            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMASTATUS;

            // Enable DMA endpoint interrupt
            AT91C_BASE_UDPHS->UDPHS_IEN |= (1 << SHIFT_DMA << bEndpoint);
            // DMA config for receive the good size of buffer, or an error buffer

            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL = 0; // raz
            AT91C_BASE_UDPHS->UDPHS_DMA[bEndpoint].UDPHS_DMACONTROL =
                                     ( ((pTransfer->buffered << 16) & AT91C_UDPHS_BUFF_COUNT)
                                       | AT91C_UDPHS_END_TR_EN
                                       | AT91C_UDPHS_END_TR_IT
                                       | AT91C_UDPHS_END_B_EN
                                       | AT91C_UDPHS_END_BUFFIT
                                       | AT91C_UDPHS_CHANN_ENB );
        }
    }
    else if( AT91C_UDPHS_END_TR_ST == (status & AT91C_UDPHS_END_TR_ST) ) {

        trace_LOG(trace_DEBUG, "EndTransf ");

        pTransfer->transferred = pTransfer->buffered
                                 - ((status & AT91C_UDPHS_BUFF_COUNT) >> 16);
        pTransfer->remaining = 0;
        trace_LOG(trace_DEBUG, "\n\rR:%d ", pTransfer->remaining );
        trace_LOG(trace_DEBUG, "B:%d ", pTransfer->buffered );
        trace_LOG(trace_DEBUG, "T:%d ", pTransfer->transferred );
    }
    else {

        trace_LOG(trace_ERROR, "UDPHS_DmaHandler: Error (0x%08X)\n\r", status);
        result = USBD_STATUS_ABORTED;
    }

    // Invoke callback
    if( pTransfer->remaining == 0 ) {

        trace_LOG(trace_DEBUG, "EOT ");
        UDPHS_EndOfTransfer(bEndpoint, result);
    }
}
#endif


//------------------------------------------------------------------------------
//      Exported functions
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// UDP interrupt handler
//         Manages device resume, suspend, end of bus reset. Forwards endpoint
//         interrupts to the appropriate handler.

⌨️ 快捷键说明

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