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

📄 udp.c

📁 This software package contains the USB framework core developped by ATMEL, as well as two HID driv
💻 C
📖 第 1 页 / 共 4 页
字号:
    }
}

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

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

    TRACE_DEBUG_L("Stall%d ", bEndpoint);

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

    TRACE_DEBUG_L("Remote WakeUp ");

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

    TRACE_DEBUG_L("Attach(");

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

    TRACE_DEBUG_L("%d) ", ISSET(USB_GetState(pUsb), USB_STATE_POWERED));

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

    TRACE_DEBUG_L("SetAddr(%d) ", wAddress);

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

    TRACE_DEBUG_L("SetCfg() ");

    // 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)
    TRACE_DEBUG_L("PUON 1\n\r");
    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)
    TRACE_DEBUG_L("PUON 0\n\r");
    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);

    TRACE_DEBUG_L("Init()\n\r");

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