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

📄 udp.c

📁 AT91SAM9261的USB设备驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
              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;
   // }


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


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


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

//------------------------------------------------------------------------------
// \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
//------------------------------------------------------------------------------
char UDP_Stall(const S_usb *pUsb,
               unsigned char bEndpoint)
{
    S_usb_endpoint *pEndpoint = USB_GetEndpoint(pUsb, bEndpoint);

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


        return USB_STATUS_LOCKED;
    }


    UDP_SETEPFLAGS(pUsb, bEndpoint, AT91C_UDP_FORCESTALL);

    return USB_STATUS_SUCCESS;
}

//------------------------------------------------------------------------------
// \brief  Activates a remote wakeup procedure
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
void UDP_RemoteWakeUp(const S_usb *pUsb)
{
    AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);

    UDP_EnableMCK(pUsb);
    UDP_EnableUDPCK(pUsb);
    UDP_EnableTransceiver(pUsb);


    // Activates a remote wakeup (edge on ESR)
    SET(pInterface->UDP_GLBSTATE, AT91C_UDP_ESR);
    // Then clear ESR
    CLEAR(pInterface->UDP_GLBSTATE, AT91C_UDP_ESR);
}

//------------------------------------------------------------------------------
// \brief  Handles attachment or detachment from the USB when the VBus power
//         line status changes.
// \param  pUsb Pointer to a S_usb instance
// \return true if VBus is present, false otherwise
// \see    S_usb
//------------------------------------------------------------------------------
bool UDP_Attach(const S_usb *pUsb)
{
    AT91PS_UDP pInterface = UDP_GetDriverInterface(pUsb);


    // Check if VBus is present
    if (!ISSET(USB_GetState(pUsb), USB_STATE_POWERED))
       // && BRD_IsVBusConnected(pInterface)) 
    {

        // Powered state:
        //      MCK + UDPCK must be on
        //      Pull-Up must be connected
        //      Transceiver must be disabled

        // Invoke the Resume callback
        USB_ResumeCallback(pUsb);

        UDP_EnableMCK(pUsb);
        UDP_EnableUDPCK(pUsb);

        // Reconnect the pull-up if needed
        if (ISSET(*(pUsb->pState), UDP_STATE_SHOULD_RECONNECT)) {

            USB_Connect(pUsb);
            CLEAR(*(pUsb->pState), UDP_STATE_SHOULD_RECONNECT);
        }

        // Clear the Suspend and Resume interrupts
        SET(pInterface->UDP_ICR,
            AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM | AT91C_UDP_RXSUSP);

        SET(pInterface->UDP_IER, AT91C_UDP_RXSUSP);

        // The device is in Powered state
        SET(*(pUsb->pState), USB_STATE_POWERED);

    }
    else //if (ISSET(USB_GetState(pUsb), USB_STATE_POWERED)
          //   && !BRD_IsVBusConnected(pInterface)) 
    {

        // Attached state:
        //      MCK + UDPCK off
        //      Pull-Up must be disconnected
        //      Transceiver must be disabled

        // Warning: MCK must be enabled to be able to write in UDP registers
        // It may have been disabled by the Suspend interrupt, so re-enable it
        UDP_EnableMCK(pUsb);

        // Disable interrupts
        SET(pInterface->UDP_IDR, AT91C_UDP_WAKEUP | AT91C_UDP_RXRSM
                               | AT91C_UDP_RXSUSP | AT91C_UDP_SOFINT);

        UDP_DisableEndpoints(pUsb);
        UDP_DisableTransceiver(pUsb);

        // Disconnect the pull-up if needed
        if (ISSET(USB_GetState(pUsb), USB_STATE_DEFAULT)) {

            USB_Disconnect(pUsb);
            SET(*(pUsb->pState), UDP_STATE_SHOULD_RECONNECT);
        }

        UDP_DisableMCK(pUsb);
        UDP_DisableUDPCK(pUsb);

        // The device leaves the all states except Attached
        CLEAR(*(pUsb->pState), USB_STATE_POWERED | USB_STATE_DEFAULT
              | USB_STATE_ADDRESS | USB_STATE_CONFIGURED | USB_STATE_SUSPENDED);

        // Invoke the Suspend callback
        USB_SuspendCallback(pUsb);
    }


    return ISSET(USB_GetState(pUsb), USB_STATE_POWERED);
}

//------------------------------------------------------------------------------
// \brief  Sets or unsets the device address
//
//         This function directly accesses the S_usb_request instance located
//         in the S_usb structure to extract its new address.
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
void UDP_SetAddress(S_usb const *pUsb)
{
    unsigned short wAddress = USB_GetSetup(pUsb)->wValue;
    AT91PS_UDP     pInterface = UDP_GetDriverInterface(pUsb);


    // Set address
    SET(pInterface->UDP_FADDR, AT91C_UDP_FEN | wAddress);

    if (wAddress == 0) {

        SET(pInterface->UDP_GLBSTATE, 0);

        // Device enters the Default state
        CLEAR(*(pUsb->pState), USB_STATE_ADDRESS);
    }
    else {

        SET(pInterface->UDP_GLBSTATE, AT91C_UDP_FADDEN);

        // The device enters the Address state
        SET(*(pUsb->pState), USB_STATE_ADDRESS);
    }
}

//------------------------------------------------------------------------------
// \brief  Changes the device state from Address to Configured, or from
//         Configured to Address.
//
//         This method directly access the last received SETUP packet to
//         decide on what to do.
// \see    S_usb
//------------------------------------------------------------------------------
void UDP_SetConfiguration(S_usb const *pUsb)
{
    unsigned short wValue = USB_GetSetup(pUsb)->wValue;
    AT91PS_UDP     pInterface = UDP_GetDriverInterface(pUsb);



    // Check the request
    if (wValue != 0) {

        // Enter Configured state
        SET(*(pUsb->pState), USB_STATE_CONFIGURED);
        SET(pInterface->UDP_GLBSTATE, AT91C_UDP_CONFG);
    }
    else {

        // Go back to Address state
        CLEAR(*(pUsb->pState), USB_STATE_CONFIGURED);
        SET(pInterface->UDP_GLBSTATE, AT91C_UDP_FADDEN);

        // Abort all transfers
        UDP_DisableEndpoints(pUsb);
    }
}

//------------------------------------------------------------------------------
// \brief  Enables the pull-up on the D+ line to connect the device to the USB.
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
void UDP_Connect(const S_usb *pUsb)
{
#if defined(UDP_INTERNAL_PULLUP)
    SET(UDP_GetDriverInterface(pUsb)->UDP_TXVC, AT91C_UDP_PUON);

#elif defined(UDP_INTERNAL_PULLUP_BY_MATRIX)
    AT91C_BASE_MATRIX->MATRIX_USBPCR |= AT91C_MATRIX_USBPCR_PUON;

#else
    BRD_ConnectPullUp(UDP_GetDriverInterface(pUsb));

#endif
}

//------------------------------------------------------------------------------
// \brief  Disables the pull-up on the D+ line to disconnect the device from
//         the bus.
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
void UDP_Disconnect(const S_usb *pUsb)
{
#if defined(UDP_INTERNAL_PULLUP)
    CLEAR(UDP_GetDriverInterface(pUsb)->UDP_TXVC, AT91C_UDP_PUON);

#elif defined(UDP_INTERNAL_PULLUP_BY_MATRIX)
    AT91C_BASE_MATRIX->MATRIX_USBPCR &= ~AT91C_MATRIX_USBPCR_PUON;

#else
    BRD_DisconnectPullUp(UDP_GetDriverInterface(pUsb));

#endif
    // Device leaves the Default state
    CLEAR(*(pUsb->pState), USB_STATE_DEFAULT);
}

//------------------------------------------------------------------------------
// \brief  Initializes the specified USB driver
//
//         This function initializes the current FIFO bank of endpoints,
//         configures the pull-up and VBus lines, disconnects the pull-up and
//         then trigger the Init callback.
// \param  pUsb Pointer to a S_usb instance
// \see    S_usb
//------------------------------------------------------------------------------
void UDP_Init(const S_usb *pUsb)
{
    unsigned int dIndex;
    AT91PS_UDP   pInterface = UDP_GetDriverInterface(pUsb);


    // Init data banks
    for (dIndex = 0; dIndex < pUsb->dNumEndpoints; dIndex++) {

        pUsb->pEndpoints[dIndex].dFlag = AT91C_UDP_RX_DATA_BK0;
    }

    // External pull-up on D+
    // Configure
    BRD_ConfigurePullUp(pInterface);

    // Disable
    UDP_Disconnect(pUsb);

    // Device is in the Attached state
    *(pUsb->pState) = USB_STATE_ATTACHED;

    // Disable the UDP transceiver and interrupts
    UDP_EnableMCK(pUsb);
    SET(pInterface->UDP_IDR, AT91C_UDP_RXRSM);
    UDP_Connect(pUsb);
    UDP_DisableTransceiver(pUsb);
    UDP_DisableMCK(pUsb);
    UDP_Disconnect(pUsb);

    // Configure interrupts
    USB_InitCallback(pUsb);
}

//------------------------------------------------------------------------------
//      Global variables
//------------------------------------------------------------------------------

// \brief Low-level driver methods to use with the UDP USB controller
// \see S_driver_methods
const S_driver_methods sUDPMethods = {

    UDP_Init,
    UDP_Write,
    UDP_Read,
    UDP_Stall,
    UDP_Halt,
    UDP_RemoteWakeUp,
    UDP_ConfigureEndpoint,
    UDP_Attach,
    UDP_SetAddress,
    UDP_SetConfiguration,
    UDP_Handler,
    UDP_Connect,
    UDP_Disconnect
};

// \brief  Default driver when an UDP controller is present on a chip
const S_usb_driver sDefaultDriver = {

    AT91C_BASE_UDP,
    0,
    0,
    AT91C_ID_UDP,
    AT91C_PMC_UDP,
    &sUDPMethods
};

#endif // UDP


⌨️ 快捷键说明

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