partly working USB Device lib for STM32F746NG Discovery both Interface are working

Dependents:   DISCO-F746NG-USB_Device McLighTT project_Keyboard_to_the_Keyboard MIDIInstrumentPADProject ... more

USBDevice/USBHAL_STM32F7.cpp

Committer:
DieterGraef
Date:
2016-07-31
Revision:
0:0a2eaa300982

File content as of revision 0:0a2eaa300982:

/* Copyright (c) 2010-2011 mbed.org, MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
* and associated documentation files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

#if defined (TARGET_DISCO_F746NG)
#include "USBDevice.h"
static PCD_HandleTypeDef hpcd_USB_FS;
static PCD_HandleTypeDef hpcd_USB_HS;
static volatile int epCompleteFS = 0;
static volatile int epCompleteHS = 0;
USBHAL * USBHAL::instance;
uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer)
{
    return 0;
}

void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
{
    GPIO_InitTypeDef  GPIO_InitStruct;

    if(hpcd->Instance == USB_OTG_FS)
    {
        /* Configure USB FS GPIOs */
        __HAL_RCC_GPIOA_CLK_ENABLE();

        /* Configure DM DP Pins */
        GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* Enable USB FS Clock */
        __HAL_RCC_USB_OTG_FS_CLK_ENABLE();


    }
    else if(hpcd->Instance == USB_OTG_HS)
    {
        /* Configure USB FS GPIOs */
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_GPIOC_CLK_ENABLE();
        __HAL_RCC_GPIOH_CLK_ENABLE();

        /* CLK */
        GPIO_InitStruct.Pin = GPIO_PIN_5;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* D0 */
        GPIO_InitStruct.Pin = GPIO_PIN_3;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        /* D1 D2 D3 D4 D5 D6 D7 */
        GPIO_InitStruct.Pin = GPIO_PIN_0  | GPIO_PIN_1  | GPIO_PIN_5 |\
                              GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        /* STP */
        GPIO_InitStruct.Pin = GPIO_PIN_0;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        /* NXT */
        GPIO_InitStruct.Pin = GPIO_PIN_4;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);

        /* DIR */
        GPIO_InitStruct.Pin = GPIO_PIN_2;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS;
        HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

        __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE();

        /* Enable USB HS Clocks */
        __HAL_RCC_USB_OTG_HS_CLK_ENABLE();


    }
}

void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
{
    if(hpcd->Instance == USB_OTG_FS)
    {
        /* Disable USB FS Clock */
        __HAL_RCC_USB_OTG_FS_CLK_DISABLE();
        __HAL_RCC_SYSCFG_CLK_DISABLE();
    }
    else if(hpcd->Instance == USB_OTG_HS)
    {
        /* Disable USB HS Clocks */
        __HAL_RCC_USB_OTG_HS_CLK_DISABLE();
        __HAL_RCC_SYSCFG_CLK_DISABLE();
    }
}


USBHAL::USBHAL(uint16_t HW_Interface)
{
    HW_Interfaces=HW_Interface;
    if(HW_Interface==Fastspeed_Interface)
    {
        hpcd_USB_FS.pData = this;
        hpcd_USB_FS.Instance =  USB_OTG_FS;
        hpcd_USB_FS.Init.dev_endpoints = 8;
        hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
        hpcd_USB_FS.Init.ep0_mps = 0x40;
        hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
        hpcd_USB_FS.Init.Sof_enable = DISABLE;
        hpcd_USB_FS.Init.dma_enable = DISABLE;
        hpcd_USB_FS.Init.vbus_sensing_enable = DISABLE;
        hpcd_USB_FS.Init.lpm_enable = DISABLE;
        hpcd_USB_FS.Init.low_power_enable = DISABLE;
        //hpcd_USB_FS.Init.battery_charging_enable = DISABLE;


        NVIC_SetVector(OTG_FS_IRQn, (uint32_t)&_usbisrFS);
        /* Set USBFS Interrupt priority */
        HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0);
        /* Enable USBFS Interrupt */
        HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
        HAL_PCD_Init(&hpcd_USB_FS);
        HAL_PCDEx_SetRxFiFo(&hpcd_USB_FS, 0x80);
        HAL_PCD_Start(&hpcd_USB_FS);
    }
    else
    {
        hpcd_USB_HS.pData = this;
        hpcd_USB_HS.Instance =  USB_OTG_HS;
        hpcd_USB_HS.Init.dev_endpoints = 8;
        hpcd_USB_HS.Init.speed = PCD_SPEED_HIGH;
        hpcd_USB_HS.Init.ep0_mps = 0x40;
        hpcd_USB_HS.Init.phy_itface = PCD_PHY_ULPI;
        hpcd_USB_HS.Init.Sof_enable = DISABLE;
        hpcd_USB_HS.Init.dma_enable = DISABLE;
        hpcd_USB_HS.Init.vbus_sensing_enable = ENABLE;
        hpcd_USB_HS.Init.lpm_enable = DISABLE;
        hpcd_USB_HS.Init.low_power_enable = DISABLE;
        //hpcd_USB_HS.Init.battery_charging_enable = DISABLE;

        NVIC_SetVector(OTG_HS_IRQn, (uint32_t)&_usbisrHS);
        /* Set USBHS Interrupt to the lowest priority */
        HAL_NVIC_SetPriority(OTG_HS_IRQn, 5, 0);
        /* Enable USBHS Interrupt */
        HAL_NVIC_EnableIRQ(OTG_HS_IRQn);
        HAL_PCD_Init(&hpcd_USB_HS);
        HAL_PCDEx_SetRxFiFo(&hpcd_USB_HS, 0x200);
        HAL_PCD_Start(&hpcd_USB_HS);
    }
}

USBHAL::~USBHAL(void)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        HAL_PCD_DeInit(&hpcd_USB_FS);
    }
    else
    {
        HAL_PCD_DeInit(&hpcd_USB_HS);
    }
}


void USBHAL::connect(void)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        HAL_PCD_DevConnect(&hpcd_USB_FS);
    }
    else
    {
        HAL_PCD_DevConnect(&hpcd_USB_HS);
    }
}

void USBHAL::disconnect(void)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        HAL_PCD_DevDisconnect(&hpcd_USB_FS);
    }
    else
    {
        HAL_PCD_DevDisconnect(&hpcd_USB_HS);
    }
}

void USBHAL::configureDevice(void)
{
    // Not needed
}
void USBHAL::unconfigureDevice(void)
{
    // Not needed
}

void USBHAL::setAddress(uint8_t address)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        HAL_PCD_SetAddress(&hpcd_USB_FS, address);
    }
    else
    {
        HAL_PCD_SetAddress(&hpcd_USB_HS, address);
    }
}


class PacketBufferAreaManager
{
public:
    PacketBufferAreaManager(int bufsize_):bufsize(bufsize_)
    {
        reset();
    }
    void reset()
    {
        head = 0;
        tail = bufsize;
    }
    int allocBuf(int maxPacketSize)
    {
        head += 4;
        tail -= maxPacketSize;
        if (tail < head)
        {
            return 0;
        }
        return tail;
    }
private:
    int head,tail;
    int bufsize;
} PktBufArea(512);


bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags)
{

    PCD_HandleTypeDef *hpcd;

    if(HW_Interfaces==Fastspeed_Interface)
    {
        hpcd = &hpcd_USB_FS;
    }
    else
    {
        hpcd = &hpcd_USB_HS;
    }
    uint8_t ep_type;
    switch(endpoint)
    {
    case EP0OUT:
        HAL_PCD_EP_Open(hpcd, 0x00, maxPacket, EP_TYPE_CTRL);
        break;
    case EP0IN:
        HAL_PCDEx_SetTxFiFo(hpcd,0,maxPacket);
        HAL_PCD_EP_Open(hpcd, 0x80, maxPacket, EP_TYPE_CTRL);
        break;
    case EPINT_OUT:
        HAL_PCD_EP_Open(hpcd, 0x01, maxPacket, EP_TYPE_INTR);
        break;
    case EPINT_IN:
        HAL_PCDEx_SetTxFiFo(hpcd,1,maxPacket);
        HAL_PCD_EP_Open(hpcd, 0x81, maxPacket, EP_TYPE_INTR);
        break;
    case EPBULK_OUT:
        HAL_PCD_EP_Open(hpcd, 0x02, maxPacket, EP_TYPE_BULK);
        break;
    case EPBULK_IN:
        HAL_PCDEx_SetTxFiFo(hpcd,2,maxPacket);
        HAL_PCD_EP_Open(hpcd, 0x82, maxPacket, EP_TYPE_BULK);
        break;
    case EP3OUT:
        ep_type = (flags & ISOCHRONOUS) ? EP_TYPE_ISOC : EP_TYPE_BULK;
        HAL_PCD_EP_Open(hpcd, 0x03, maxPacket, ep_type);
        break;
    case EP3IN:
        HAL_PCDEx_SetTxFiFo(hpcd,3,maxPacket);
        ep_type = (flags & ISOCHRONOUS) ? EP_TYPE_ISOC : EP_TYPE_BULK;
        HAL_PCD_EP_Open(hpcd, 0x83, maxPacket, ep_type);
        break;
    default:
        MBED_ASSERT(0);
        return false;
    }
    return true;
}


// read setup packet
void USBHAL::EP0setup(uint8_t *buffer)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        memcpy(buffer, hpcd_USB_FS.Setup, 8);
    }
    else
    {
        memcpy(buffer, hpcd_USB_HS.Setup, 8);
    }
}

void USBHAL::EP0readStage(void)
{
}

void USBHAL::EP0read(void)
{
    endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
}


class rxTempBufferManager
{
    uint8_t buf0[MAX_PACKET_SIZE_EP0];
    uint8_t buf1[MAX_PACKET_SIZE_EP1];
    uint8_t buf2[MAX_PACKET_SIZE_EP2];
    uint8_t buf3[MAX_PACKET_SIZE_EP3_ISO];
public:
    uint8_t* ptr(uint8_t endpoint, int maxPacketSize)
    {
        switch(endpoint)
        {
        case EP0OUT:
            MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP0);
            break;
        case EP1OUT:
            MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP1);
            break;
        case EP2OUT:
            MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP2);
            break;
        case EP3OUT:
            MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP3_ISO);
            break;
        }
        return ptr(endpoint);
    }
    uint8_t* ptr(uint8_t endpoint)
    {
        switch(endpoint)
        {
        case EP0OUT:
            return buf0;
        case EP1OUT:
            return buf1;
        case EP2OUT:
            return buf2;
        case EP3OUT:
            return buf3;
        }
        MBED_ASSERT(0);
        return NULL;
    }
} rxtmp;


uint32_t USBHAL::EP0getReadResult(uint8_t *buffer)
{
    const uint8_t endpoint = EP0OUT;
    uint32_t length;
    if(HW_Interfaces==Fastspeed_Interface)
    {
        length = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1);
    }
    else
    {
        length = HAL_PCD_EP_GetRxCount(&hpcd_USB_HS, endpoint>>1);
    }
    memcpy(buffer, rxtmp.ptr(endpoint), length);
    return length;
}

void USBHAL::EP0write(uint8_t *buffer, uint32_t size)
{
    endpointWrite(EP0IN, buffer, size);
}

void USBHAL::EP0getWriteResult(void)
{
}

void USBHAL::EP0stall(void)
{
    // If we stall the out endpoint here then we have problems transferring
    // and setup requests after the (stalled) get device qualifier requests.
    // TODO: Find out if this is correct behavior, or whether we are doing
    // something else wrong
    stallEndpoint(EP0IN);
//    stallEndpoint(EP0OUT);
}

EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        epCompleteFS &= ~(1 << endpoint);
        HAL_PCD_EP_Receive(&hpcd_USB_FS, endpoint>>1, rxtmp.ptr(endpoint, maximumSize), maximumSize);
    }
    else
    {
        epCompleteHS &= ~(1 << endpoint);
        HAL_PCD_EP_Receive(&hpcd_USB_HS, endpoint>>1, rxtmp.ptr(endpoint, maximumSize), maximumSize);
    }

    return EP_PENDING;
}

EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead)
{
    int len;
    if(HW_Interfaces==Fastspeed_Interface)
    {

        if (!(epCompleteFS & (1 << endpoint)))
        {
            return EP_PENDING;
        }

        len = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1);
    }
    else
    {

        if (!(epCompleteHS & (1 << endpoint)))
        {
            return EP_PENDING;
        }

        len = HAL_PCD_EP_GetRxCount(&hpcd_USB_HS, endpoint>>1);
    }
    memcpy(buffer, rxtmp.ptr(endpoint), len);
    *bytesRead = len;
    return EP_COMPLETED;
}

EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        epCompleteFS &= ~(1 << endpoint);
        HAL_PCD_EP_Transmit(&hpcd_USB_FS, endpoint>>1, data, size);
    }
    else
    {
        epCompleteHS &= ~(1 << endpoint);
        HAL_PCD_EP_Transmit(&hpcd_USB_HS, endpoint>>1, data, size);
    }

    return EP_PENDING;
}

EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        if (epCompleteFS & (1 << endpoint))
        {
            epCompleteFS &= ~(1 << endpoint);
            return EP_COMPLETED;
        }
        return EP_PENDING;
    }
    else
    {
        if (epCompleteHS & (1 << endpoint))
        {
            epCompleteHS &= ~(1 << endpoint);
            return EP_COMPLETED;
        }
        return EP_PENDING;
    }
}

void USBHAL::stallEndpoint(uint8_t endpoint)
{
    PCD_HandleTypeDef *hpcd;
    if(HW_Interfaces==Fastspeed_Interface)
    {
        hpcd = &hpcd_USB_FS;
    }
    else
    {
        hpcd = &hpcd_USB_HS;
    }
    switch(endpoint)
    {
    case EP0IN:
        HAL_PCD_EP_SetStall(hpcd, 0x80);
        break;
    case EP0OUT:
        HAL_PCD_EP_SetStall(hpcd, 0x00);
        break;
    default:
        break;
    }
}

void USBHAL::unstallEndpoint(uint8_t endpoint)
{
}

bool USBHAL::getEndpointStallState(uint8_t endpoint)
{
    return false;
}

void USBHAL::remoteWakeup(void) {}

void USBHAL::_usbisrFS(void)
{
    HAL_PCD_IRQHandler(&hpcd_USB_FS);
}

void USBHAL::_usbisrHS(void)
{
    HAL_PCD_IRQHandler(&hpcd_USB_HS);
}

void USBHAL::usbisr(void) {}

void USBHAL::SetupStageCallback()
{
    EP0setupCallback();
}

void USBHAL::DataInStageCallback(uint8_t epnum)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        switch(epnum)
        {
        case 0: // EP0IN
            EP0in();
            break;
        case 1:
            epCompleteFS |= (1<<EP1IN);
            if (EP1_IN_callback())
            {
                epCompleteFS &= ~(1<<EP1IN);
            }
            break;
        case 2:
            epCompleteFS |= (1<<EP2IN);
            if (EP2_IN_callback())
            {
                epCompleteFS &= ~(1<<EP2IN);
            }
            break;
        case 3:
            epCompleteFS |= (1<<EP3IN);
            if (EP3_IN_callback())
            {
                epCompleteFS &= ~(1<<EP3IN);
            }
            break;
        default:
            MBED_ASSERT(0);
            break;
        }
    }
    else
    {
        switch(epnum)
        {
        case 0: // EP0IN
            EP0in();
            break;
        case 1:
            epCompleteHS |= (1<<EP1IN);
            if (EP1_IN_callback())
            {
                epCompleteHS &= ~(1<<EP1IN);
            }
            break;
        case 2:
            epCompleteHS |= (1<<EP2IN);
            if (EP2_IN_callback())
            {
                epCompleteHS &= ~(1<<EP2IN);
            }
            break;
        case 3:
            epCompleteFS |= (1<<EP3IN);
            if (EP3_IN_callback())
            {
                epCompleteFS &= ~(1<<EP3IN);
            }
            break;
        default:
            MBED_ASSERT(0);
            break;
        }
    }
}

void USBHAL::DataOutStageCallback(uint8_t epnum)
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        switch(epnum)
        {
        case 0: // EP0OUT
            if ((hpcd_USB_FS.Setup[0]&0x80) == 0x00)   // host to device ?
            {
                EP0out();
            }

            break;
        case 1:
            epCompleteFS |= (1<<EP1OUT);
            if (EP1_OUT_callback())
            {
                epCompleteFS &= ~(1<<EP1OUT);
            }
            break;
        case 2:
            epCompleteFS |= (1<<EP2OUT);
            if (EP2_OUT_callback())
            {
                epCompleteFS &= ~(1<<EP2OUT);
            }
            break;
        case 3:
            epCompleteFS |= (1<<EP3OUT);
            if (EP3_OUT_callback())
            {
                epCompleteFS &= ~(1<<EP3OUT);
            }
            break;
        default:
            MBED_ASSERT(0);
            break;
        }
    }
    else
    {
        switch(epnum)
        {
        case 0: // EP0OUT

            if ((hpcd_USB_HS.Setup[0]&0x80) == 0x00)   // host to device ?
            {
                EP0out();
            }

            break;
        case 1:
            epCompleteHS |= (1<<EP1OUT);
            if (EP1_OUT_callback())
            {
                epCompleteHS &= ~(1<<EP1OUT);
            }
            break;
        case 2:
            epCompleteHS |= (1<<EP2OUT);
            if (EP2_OUT_callback())
            {
                epCompleteHS &= ~(1<<EP2OUT);
            }
            break;
        case 3:
            epCompleteHS |= (1<<EP3OUT);
            if (EP3_OUT_callback())
            {
                epCompleteHS &= ~(1<<EP3OUT);
            }
            break;
        default:
            MBED_ASSERT(0);
            break;
        }
    }
}

void USBHAL::ResetCallback()
{
    PktBufArea.reset();
    realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
    realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
}

void USBHAL::SOFCallback()
{
    if(HW_Interfaces==Fastspeed_Interface)
    {
        SOF(1);
    }
    else
    {
        SOF(1);
    }
}

void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
{
    reinterpret_cast<USBHAL*>(hpcd->pData)->SetupStageCallback();
}

void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
    reinterpret_cast<USBHAL*>(hpcd->pData)->DataInStageCallback(epnum);
}

void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
{
    reinterpret_cast<USBHAL*>(hpcd->pData)->DataOutStageCallback(epnum);
}

void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
{
    reinterpret_cast<USBHAL*>(hpcd->pData)->ResetCallback();
}

void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
{
    reinterpret_cast<USBHAL*>(hpcd->pData)->SOFCallback();
}

void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
{
    if (hpcd->Init.low_power_enable)
    {
        SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
    }
}



#endif