Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Revision:
0:01f31e923fe2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/hic_hal/atmel/sam3u2c/usbd_ATSAM3U2C.c	Tue Apr 07 12:55:42 2020 +0200
@@ -0,0 +1,807 @@
+/**
+ * @file    usbd_ATSAM3U2C.c
+ * @brief   
+ *
+ * DAPLink Interface Firmware
+ * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rl_usb.h"
+#include "sam3u.h"
+#include "util.h"
+
+#define __NO_USB_LIB_C
+#include "usb_config.c"
+
+#define UDPHS_EPTFIFO_BASE (0x20180000) /* (UDPHS_EPTFIFO) Base Address       */
+uint32_t eptsta_copy[USBD_EP_NUM + 1];
+
+/*
+ *  Calculate EP size code Function
+ *   Called during EndPoint configuration
+ *    Return Value:    EP size code for given EP size
+ */
+
+static int USBD_CalcSizeEP(uint32_t size)
+{
+    if (size <=    8) {
+        return (0);
+    } else if (size <=   16) {
+        return (1);
+    } else if (size <=   32) {
+        return (2);
+    } else if (size <=   64) {
+        return (3);
+    } else if (size <=  128) {
+        return (4);
+    } else if (size <=  256) {
+        return (5);
+    } else if (size <=  512)  {
+        return (6);
+    } else if (size <= 1024) {
+        return (7);
+    }
+
+    return (0);
+}
+
+
+/*
+ *  Retrieve maximum EP size Function
+ *   Called during EndPoint configuration
+ *    Return Value:    maximum size for given EP
+ */
+
+static int USBD_GetSizeEP(uint32_t EPNum)
+{
+    switch (EPNum & 0x0F) {
+        case 0:
+            return (64);                      /* Maximum size is 64 bytes           */
+
+        case 1:
+        case 2:
+            return (512);                     /* Maximum size is 512 bytes          */
+
+        case 3:
+        case 4:
+            return (64);                      /* Maximum size is 64 bytes           */
+
+        case 5:
+        case 6:
+            return (1024);                    /* Maximum size is 1024 bytes         */
+
+        default:
+            return (0);                       /* Non existant endpoint              */
+    }
+}
+
+
+/*
+ *  USB Device Interrupt enable
+ *   Called by USBD_Init to enable the USB Interrupt
+ *    Return Value:    None
+ */
+
+void USBD_IntrEna(void)
+{
+    NVIC_EnableIRQ(UDPHS_IRQn);           /* Enable USB interrupt               */
+}
+
+
+/*
+ *  USB Device Initialize Function
+ *   Called by the User to initialize USB Device
+ *    Return Value:    None
+ */
+
+void USBD_Init(void)
+{
+    uint32_t n;
+    /* Enables the 48MHz USB Clock UDPCK and System Peripheral USB Clock        */
+    PMC->PMC_WPMR = 0x504D4300;                              /* Disable write protect  */
+    PMC->PMC_PCER0  = (1 << ID_UDPHS);                       /* enable clock for UPDHS */
+    PMC->CKGR_UCKR  = (CKGR_UCKR_UPLLCOUNT(15) | CKGR_UCKR_UPLLEN);
+
+    while (!(PMC->PMC_SR & PMC_SR_LOCKU));                   /* wait until PLL is locked */
+
+    PMC->PMC_WPMR = 0x504D4301;                              /* Enable write protect */
+    /* Configure the pull-up on D+ and disconnect it                            */
+    UDPHS->UDPHS_CTRL |= UDPHS_CTRL_DETACH;         /* Detach                   */
+    UDPHS->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS;      /* Disable Pull Down        */
+    /* Reset IP UDPHS                                                           */
+    UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_EN_UDPHS;
+    UDPHS->UDPHS_CTRL |=  UDPHS_CTRL_EN_UDPHS;
+#if (!USBD_HS_ENABLE)                             /* If HS disabled           */
+    UDPHS->UDPHS_TST  |= (3 & UDPHS_TST_SPEED_CFG_Msk);
+#endif
+
+    /* Disable DMA for UDPHS                                                    */
+    for (n = 1; n < (UDPHSDMA_NUMBER); n++) {
+        /* RESET endpoint canal DMA:                                              */
+        UDPHS->UDPHS_DMA[n].UDPHS_DMACONTROL = 0;     /* STOP command             */
+        /* Disable endpoint                                                       */
+        UDPHS->UDPHS_EPT[n].UDPHS_EPTCTLDIS  = 0xFFFFFFFF;
+        /* Clear status endpoint                                                  */
+        UDPHS->UDPHS_EPT[n].UDPHS_EPTCLRSTA  = 0xFFFFFFFF;
+        /* Reset endpoint config                                                  */
+        UDPHS->UDPHS_EPT[n].UDPHS_EPTCTLENB  = 0;
+        /* Reset DMA channel (Buff count and Control field)                       */
+        UDPHS->UDPHS_DMA[n].UDPHS_DMACONTROL = (0x1 << 1);    /* NON STOP command */
+        /* Reset DMA channel 0 (STOP)                                             */
+        UDPHS->UDPHS_DMA[n].UDPHS_DMACONTROL = 0;             /* STOP command     */
+        /* Clear DMA channel status (read the register for clear it)              */
+        UDPHS->UDPHS_DMA[n].UDPHS_DMASTATUS =  UDPHS->UDPHS_DMA[n].UDPHS_DMASTATUS;
+    }
+
+    UDPHS->UDPHS_IEN     = 0;
+    UDPHS->UDPHS_CLRINT  = UDPHS_CLRINT_UPSTR_RES |
+                           UDPHS_CLRINT_ENDOFRSM  |
+                           UDPHS_CLRINT_WAKE_UP   |
+                           UDPHS_CLRINT_ENDRESET  |
+                           UDPHS_CLRINT_INT_SOF   |
+                           UDPHS_CLRINT_MICRO_SOF |
+                           UDPHS_CLRINT_DET_SUSPD;
+    USBD_IntrEna();                       /* Enable USB interrupt               */
+}
+
+
+/*
+ *  USB Device Connect Function
+ *   Called by the User to Connect/Disconnect USB Device
+ *    Parameters:      con:   Connect/Disconnect
+ *    Return Value:    None
+ */
+
+void USBD_Connect(BOOL con)
+{
+    if (con) {
+        UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_DETACH;          /* Pull Up on DP        */
+        UDPHS->UDPHS_CTRL |=  UDPHS_CTRL_PULLD_DIS;       /* Disable Pull Down    */
+    } else {
+        UDPHS->UDPHS_CTRL |=  UDPHS_CTRL_DETACH;          /* Detach               */
+        UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_PULLD_DIS;       /* Enable Pull Down     */
+    }
+}
+
+/*
+ *  USB Device Reset Function
+ *   Called automatically on USB Device Reset
+ *    Return Value:    None
+ */
+extern U8 USBD_ConfigDescriptor_HS[];
+extern U8 USBD_ConfigDescriptor[];
+void USBD_Reset(void)
+{
+    uint32_t ep, EPMask;
+    EPMask = ((1 << (USBD_EP_NUM + 1)) - 1);
+
+    /* Reset & Disable USB Endpoints                                            */
+    for (ep = 0; ep <= USBD_EP_NUM; ep++) {
+        UDPHS->UDPHS_EPT[ep].UDPHS_EPTCFG    =  0;
+        UDPHS->UDPHS_EPT[ep].UDPHS_EPTCTLDIS = (0x1 <<  0);     /* Disable EP     */
+        eptsta_copy[ep] = 0;
+    }
+
+    UDPHS->UDPHS_EPTRST = EPMask;                             /* Reset   EPs    */
+    UDPHS->UDPHS_EPTRST = 0;
+    /* Setup USB Interrupts */               /* note: Micro_SOF not yet handled */
+#ifdef __RTX
+    UDPHS->UDPHS_IEN = ((USBD_RTX_DevTask     != 0) ? UDPHS_IEN_DET_SUSPD : 0) |
+                       ((USBD_RTX_DevTask     != 0) ? UDPHS_IEN_MICRO_SOF : 0) |
+                       ((USBD_RTX_DevTask     != 0) ? UDPHS_IEN_INT_SOF   : 0) |
+                       ((USBD_RTX_DevTask     != 0) ? UDPHS_IEN_ENDRESET  : 0) |
+//                   ((USBD_RTX_DevTask     != 0) ? UDPHS_IEN_WAKE_UP   : 0) |
+//                   ((USBD_RTX_DevTask     != 0) ? UDPHS_IEN_UPSTR_RES : 0) |
+#else
+    UDPHS->UDPHS_IEN = ((USBD_P_Suspend_Event != 0) ? UDPHS_IEN_DET_SUSPD : 0) |
+                       ((USBD_P_SOF_Event     != 0) ? UDPHS_IEN_MICRO_SOF : 0) |
+                       ((USBD_P_SOF_Event     != 0) ? UDPHS_IEN_INT_SOF   : 0) |
+                       ((USBD_P_Reset_Event   != 0) ? UDPHS_IEN_ENDRESET  : 0) |
+//                   ((USBD_P_WakeUp_Event  != 0) ? UDPHS_IEN_WAKE_UP   : 0) |
+//                   ((USBD_P_Resume_Event  != 0) ? UDPHS_IEN_UPSTR_RES : 0) |
+#endif
+                       (EPMask << 8);
+    /* Setup Control Endpoint 0                                                 */
+    UDPHS->UDPHS_EPT[0].UDPHS_EPTCFG     = UDPHS_EPTCFG_BK_NUMBER_1            |
+                                           UDPHS_EPTCFG_EPT_TYPE_CTRL8         |
+                                           USBD_CalcSizeEP(USBD_MAX_PACKET0)   ;
+    UDPHS->UDPHS_EPT[0].UDPHS_EPTCTLENB  = UDPHS_EPTCTLENB_RXRDY_TXKL          |
+                                           UDPHS_EPTCTLENB_TX_COMPLT           |
+                                           UDPHS_EPTCTLENB_RX_SETUP            |
+                                           UDPHS_EPTCTLENB_STALL_SNT           |
+                                           UDPHS_EPTCTLENB_NYET_DIS            |
+                                           UDPHS_EPTCTLENB_EPT_ENABL;
+                                           
+    
+#if (USBD_HS_ENABLE == 1)
+    U8 * config_desc = USBD_ConfigDescriptor_HS;
+#else
+    U8 * config_desc = USBD_ConfigDescriptor;
+#endif
+
+    while (((USB_ENDPOINT_DESCRIPTOR *)config_desc)->bLength > 0) {
+        if (((USB_ENDPOINT_DESCRIPTOR *)config_desc)->bDescriptorType == USB_ENDPOINT_DESCRIPTOR_TYPE) {
+            uint32_t num, type, dir, size, banks, interval;
+            USB_ENDPOINT_DESCRIPTOR *pEPD =  (USB_ENDPOINT_DESCRIPTOR *)config_desc;
+            num      = pEPD->bEndpointAddress & 0x0F;
+            type     = pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+            dir      = pEPD->bEndpointAddress >> 7;
+            interval = pEPD->bInterval;
+            size     = USBD_CalcSizeEP(pEPD->wMaxPacketSize);
+            banks    = 1;
+            UDPHS->UDPHS_EPT[num].UDPHS_EPTCFG    = (interval << 8) |
+                                                    (banks    << 6) |
+                                                    (type     << 4) |
+                                                    (dir      << 3) |
+                                                    (size     << 0) ;
+        }
+        config_desc += ((USB_ENDPOINT_DESCRIPTOR *)config_desc)->bLength;
+    }
+}
+
+
+/*
+ *  USB Device Suspend Function
+ *   Called automatically on USB Device Suspend
+ *    Return Value:    None
+ */
+
+void USBD_Suspend(void)
+{
+    UDPHS->UDPHS_IEN  &= ~UDPHS_IEN_DET_SUSPD;
+    UDPHS->UDPHS_IEN  |=  UDPHS_IEN_WAKE_UP;
+}
+
+
+/*
+ *  USB Device Resume Function
+ *   Called automatically on USB Device Resume
+ *    Return Value:    None
+ */
+
+void USBD_Resume(void)
+{
+    UDPHS->UDPHS_IEN  &= ~UDPHS_IEN_WAKE_UP;
+    UDPHS->UDPHS_IEN  |=  UDPHS_IEN_DET_SUSPD;
+}
+
+
+/*
+ *  USB Device Remote Wakeup Function
+ *   Called automatically on USB Device Remote Wakeup
+ *    Return Value:    None
+ */
+
+void USBD_WakeUp(void)
+{
+    UDPHS->UDPHS_IEN  |=  UDPHS_IEN_UPSTR_RES;
+    UDPHS->UDPHS_CTRL |=  UDPHS_CTRL_REWAKEUP;
+}
+
+
+/*
+ *  USB Device Remote Wakeup Configuration Function
+ *    Parameters:      cfg:   Device Enable/Disable
+ *    Return Value:    None
+ */
+
+void USBD_WakeUpCfg(BOOL cfg)
+{
+    if (cfg) {
+        /* Enable wakeup mechanism */
+    } else {
+        UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_REWAKEUP;
+        UDPHS->UDPHS_IEN  &= ~UDPHS_IEN_UPSTR_RES;
+    }
+}
+
+
+/*
+ *  USB Device Set Address Function
+ *    Parameters:      adr:   USB Device Address
+ *                     setup: Called in setup stage (!=0), else after status stage
+ *    Return Value:    None
+ */
+
+void USBD_SetAddress(uint32_t adr, uint32_t setup)
+{
+    if (setup) {
+        return;
+    }
+
+    if (adr) {
+        UDPHS->UDPHS_CTRL |= (UDPHS_CTRL_FADDR_EN | adr);
+    } else {
+        UDPHS->UDPHS_CTRL &= ~(UDPHS_CTRL_FADDR_EN | UDPHS_CTRL_DEV_ADDR_Msk);
+    }
+}
+
+
+/*
+ *  USB Device Configure Function
+ *    Parameters:      cfg:   Device Configure/Deconfigure
+ *    Return Value:    None
+ */
+
+void USBD_Configure(BOOL cfg)
+{
+    /* Performed by Hardware */
+}
+
+
+/*
+ *  Configure USB Device Endpoint according to Descriptor
+ *    Parameters:      pEPD:  Pointer to Device Endpoint Descriptor
+ *    Return Value:    None
+ */
+
+void USBD_ConfigEP(USB_ENDPOINT_DESCRIPTOR *pEPD)
+{
+    uint32_t num;//, type, dir, size, banks, interval;
+    num      = pEPD->bEndpointAddress & 0x0F;
+    /*type     = pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK;
+    dir      = pEPD->bEndpointAddress >> 7;
+    interval = pEPD->bInterval;
+    size     = USBD_CalcSizeEP(pEPD->wMaxPacketSize);
+    banks    = 1;
+    */
+    /* Check if MaxPacketSize fits for EndPoint                                 */
+    if (pEPD->wMaxPacketSize <= USBD_GetSizeEP(num)) {
+        /*UDPHS->UDPHS_EPT[num].UDPHS_EPTCFG    = (interval << 8) |
+                                                (banks    << 6) |
+                                                (type     << 4) |
+                                                (dir      << 3) |
+                                                //(size     << 0) ;
+                                                 6;*/
+        UDPHS->UDPHS_EPT[num].UDPHS_EPTCTLENB =
+            (0x1 <<  9) |  /* Received OUT Data Interrupt Enable                    */
+            (0x1 << 10) |  /* Transmitted IN Data Complete Interrupt Enable         */
+            (0x0 <<  4) |  /* NYET Disable (Only for High Speed Bulk OUT endpoints) */
+            (0x1 << 13) ;  /* Stall Sent /ISO CRC Error/Number of Transaction Error */
+    }
+}
+
+
+/*
+ *  Set Direction for USB Device Control Endpoint
+ *    Parameters:      dir:   Out (dir == 0), In (dir <> 0)
+ *    Return Value:    None
+ */
+
+void USBD_DirCtrlEP(uint32_t dir)
+{
+    /* Performed by Hardware */
+}
+
+
+/*
+ *  Enable USB Device Endpoint
+ *    Parameters:      EPNum: Device Endpoint Number
+ *                       EPNum.0..3: Address
+ *                       EPNum.7:    Dir
+ *    Return Value:    None
+ */
+
+void USBD_EnableEP(uint32_t EPNum)
+{
+    UDPHS->UDPHS_EPT[EPNum & 0x0F].UDPHS_EPTCTLENB = (0x1 << 0);  /* EP Enable  */
+    eptsta_copy[EPNum & 0x0F] = UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSETSTA;
+}
+
+
+/*
+ *  Disable USB Device Endpoint
+ *    Parameters:      EPNum: Device Endpoint Number
+ *                       EPNum.0..3: Address
+ *                       EPNum.7:    Dir
+ *    Return Value:    None
+ */
+
+void USBD_DisableEP(uint32_t EPNum)
+{
+    UDPHS->UDPHS_EPT[EPNum & 0x0F].UDPHS_EPTCTLDIS = (0x1 << 0);  /* EP Disable */
+    eptsta_copy[EPNum & 0x0F] = UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSETSTA;
+}
+
+
+/*
+ *  Reset USB Device Endpoint
+ *    Parameters:      EPNum: Device Endpoint Number
+ *                       EPNum.0..3: Address
+ *                       EPNum.7:    Dir
+ *    Return Value:    None
+ */
+
+void USBD_ResetEP(uint32_t EPNum)
+{
+    EPNum &= 0x0F;
+    UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTCLRSTA = (0x1 << 6) |  /* Data Toggle Clear*/
+            (0x1 << 5);   /* Stall Req Set    */
+    UDPHS->UDPHS_EPTRST |= (1 << EPNum);                    /* Reset endpoint   */
+    UDPHS->UDPHS_EPTRST &= ~(1 << EPNum);
+    eptsta_copy[EPNum] = UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSETSTA;
+}
+
+
+/*
+ *  Set Stall for USB Device Endpoint
+ *    Parameters:      EPNum: Device Endpoint Number
+ *                       EPNum.0..3: Address
+ *                       EPNum.7:    Dir
+ *    Return Value:    None
+ */
+
+void USBD_SetStallEP(uint32_t EPNum)
+{
+    UDPHS->UDPHS_EPT[EPNum & 0x0F].UDPHS_EPTSETSTA = (0x1 << 5);  /* Stall Set  */
+    eptsta_copy[EPNum & 0x0F] |= 0x1 << 5;
+}
+
+
+/*
+ *  Clear Stall for USB Device Endpoint
+ *    Parameters:      EPNum: Device Endpoint Number
+ *                       EPNum.0..3: Address
+ *                       EPNum.7:    Dir
+ *    Return Value:    None
+ */
+
+void USBD_ClrStallEP(uint32_t EPNum)
+{
+    UDPHS->UDPHS_EPT[EPNum & 0x0F].UDPHS_EPTCLRSTA = (0x1 << 6) | /* Clr Toggle */
+            (0x1 << 5);  /* Stall Clear*/
+    eptsta_copy[EPNum & 0x0F] &= ~(0x1 << 5);
+}
+
+
+/*
+ *  Read USB Device Endpoint Data
+ *    Parameters:      EPNum: Device Endpoint Number
+ *                       EPNum.0..3: Address
+ *                       EPNum.7:    Dir
+ *                     pData: Pointer to Data Buffer
+ *    Return Value:    Number of bytes read
+ */
+
+uint32_t USBD_ReadEP(uint32_t EPNum, uint8_t *pData, uint32_t size)
+{
+    uint32_t cnt, n, copy_sz;
+    uint8_t *pEPFIFO;                                /* Pointer to EP FIFO           */
+    uint32_t eptsta;
+    EPNum  &= 0x0F;
+    eptsta = eptsta_copy[EPNum];
+    pEPFIFO = (uint8_t *)((uint32_t *)UDPHS_EPTFIFO_BASE + (16384 * EPNum));
+    cnt     = (eptsta >> 20) & 0x07FF;  /* Get by */
+    copy_sz = cnt > size ? size : cnt;
+
+    for (n = 0; n < copy_sz; n++) {
+        *pData++ = *pEPFIFO++;
+    }
+
+    util_assert(cnt == copy_sz);
+
+    if ((cnt == copy_sz) && (eptsta & (0x1 << 9))) {
+        UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTCLRSTA = (0x1 << 9);   /* Rece OUT Clear   */
+    }
+
+    /* RX_Setup must be cleared after Setup packet is read                      */
+    if (eptsta & (0x1 << 12)) {
+        UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTCLRSTA = (0x1 << 12);  /* Rece SETUP Clear */
+    }
+    UDPHS->UDPHS_IEN |= (1 << (EPNum + 8));     /* Enable EP int after data read*/
+    return (cnt);
+}
+
+
+/*
+ *  Write USB Device Endpoint Data
+ *    Parameters:      EPNum: Device Endpoint Number
+ *                       EPNum.0..3: Address
+ *                       EPNum.7:    Dir
+ *                     pData: Pointer to Data Buffer
+ *                     cnt:   Number of bytes to write
+ *    Return Value:    Number of bytes written
+ */
+
+uint32_t USBD_WriteEP(uint32_t EPNum, uint8_t *pData, uint32_t cnt)
+{
+    uint32_t n;
+    uint8_t *pEPFIFO;                          /* Pointer to the endpoint FIFO       */
+    uint32_t eptsta;
+    EPNum &= 0x0F;
+    eptsta = eptsta_copy[EPNum];
+
+    // Cached value should match the real value
+    util_assert((UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSTA & (0x1 << 5)) == (eptsta & (0x1 << 5)));
+    if (eptsta & (0x1 << 5)) {  /* If EP is stall */
+        return (cnt);
+    }
+
+    // Both register and cached value should indicate that the bank is ready (bit 11 clear)
+    util_assert(!(UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSTA & (0x1 << 11)));
+    util_assert(!(eptsta & (0x1 << 11)));
+
+    pEPFIFO = (uint8_t *)((uint32_t *)UDPHS_EPTFIFO_BASE + (16384 * EPNum));
+
+    for (n = 0; n < cnt; n++) {
+        *pEPFIFO++ = *pData++;              /* Write data to FIFO                 */
+    }
+
+    UDPHS->UDPHS_EPT[EPNum].UDPHS_EPTSETSTA = (0x1 << 11);  /* Set packet ready */
+    return (cnt);
+}
+
+
+/*
+ *  Get USB Device Last Frame Number
+ *    Parameters:      None
+ *    Return Value:    Frame Number
+ */
+
+uint32_t USBD_GetFrame(void)
+{
+    uint32_t val;
+
+    if ((UDPHS->UDPHS_FNUM & (1UL << 31)) == 0) {
+        if (USBD_HighSpeed) {
+            val = UDPHS->UDPHS_FNUM & 0x7FFFFFFF;
+        } else {
+            val = (UDPHS->UDPHS_FNUM & UDPHS_FNUM_FRAME_NUMBER_Msk) >> 3;
+        }
+    } else {
+        val = 0xFFFFFFFF;
+    }
+
+    return (val);
+}
+
+
+#ifdef __RTX
+uint32_t LastError;                          /* Last Error                         */
+
+/*
+ *  Get USB Device Last Error Code
+ *    Parameters:      None
+ *    Return Value:    Error Code
+ */
+
+uint32_t USBD_GetError(void)
+{
+    return (LastError);
+}
+#endif
+
+
+/*
+ *  USB Device Interrupt Service Routine
+ */
+
+void UDPHS_IRQHandler(void)
+{
+    NVIC_DisableIRQ(UDPHS_IRQn);
+    USBD_SignalHandler();
+}
+
+/*
+ *  USB Device Service Routine
+ */
+
+void USBD_Handler(void)
+{
+    uint32_t intsta, eptsta, n;
+    intsta = UDPHS->UDPHS_INTSTA & UDPHS->UDPHS_IEN;
+
+    /* End of Bus Reset Interrupt                                               */
+    if (intsta & UDPHS_INTSTA_ENDRESET) {
+        /* Get used speed (HighSpeed or FullSpeed)                                */
+        USBD_HighSpeed = (UDPHS->UDPHS_INTSTA & UDPHS_INTSTA_SPEED) ? 1 : 0;
+        USBD_Reset();
+        usbd_reset_core();
+#ifdef __RTX
+        UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_ENDRESET;
+
+        if (USBD_RTX_DevTask) {
+            isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask);
+        }
+
+#else
+
+        if (USBD_P_Reset_Event) {
+            USBD_P_Reset_Event();
+        }
+
+        UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_ENDRESET;
+#endif
+    }
+
+    /* USB Suspend Interrupt                                                    */
+    if (intsta & UDPHS_INTSTA_DET_SUSPD) {
+        USBD_Suspend();
+#ifdef __RTX
+        UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_DET_SUSPD;
+
+        if (USBD_RTX_DevTask) {
+            isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask);
+        }
+
+#else
+
+        if (USBD_P_Suspend_Event) {
+            USBD_P_Suspend_Event();
+        }
+
+        UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_DET_SUSPD;
+#endif
+    }
+
+    /* USB Resume Interrupt                                                     */
+    if (intsta & UDPHS_INTSTA_WAKE_UP) {
+        USBD_Resume();
+#ifdef __RTX
+        UDPHS->UDPHS_CLRINT = UDPHS_INTSTA_WAKE_UP;
+
+        if (USBD_RTX_DevTask) {
+            isr_evt_set(USBD_EVT_RESUME,  USBD_RTX_DevTask);
+        }
+
+#else
+
+        if (USBD_P_Resume_Event) {
+            USBD_P_Resume_Event();
+        }
+
+        UDPHS->UDPHS_CLRINT = UDPHS_INTSTA_WAKE_UP;
+#endif
+    }
+
+    /* USB Remote Wakeup Interrupt                                              */
+    if (intsta & UDPHS_INTSTA_UPSTR_RES) {
+        UDPHS->UDPHS_CLRINT = UDPHS_INTSTA_UPSTR_RES;
+    }
+
+    /* Start of Frame Interrupt                                                 */
+    if (intsta & UDPHS_INTSTA_INT_SOF) {
+        /* Process the SOF interrupt even in high speed mode.
+        The SOF and MICRO_SOF interrupt are never generated at the same
+        time. Instead, when in high speed mode there is 1 SOF
+        interrupt and 7 MICRO_SOF interrupts every 1ms. */
+
+#ifdef __RTX
+        UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_INT_SOF;
+
+        if (USBD_RTX_DevTask) {
+            isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
+        }
+
+#else
+
+        if (USBD_P_SOF_Event) {
+            USBD_P_SOF_Event();
+        }
+
+        UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_INT_SOF;
+#endif
+    }
+
+    /* Micro Frame Interrupt                                                    */
+    if (intsta & UDPHS_INTSTA_MICRO_SOF) {
+        if (USBD_HighSpeed == 1) {
+#ifdef __RTX
+            UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_MICRO_SOF;
+
+            if (USBD_RTX_DevTask) {
+                isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
+            }
+
+#else
+
+            if (USBD_P_SOF_Event) {
+                USBD_P_SOF_Event();
+            }
+
+            UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_MICRO_SOF;
+#endif
+
+        } else {
+            UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_MICRO_SOF;
+        }
+    }
+
+    /* Endpoint Interrupts                                                      */
+    for (n = 0; n <= USBD_EP_NUM; n++) {
+        if (intsta & (1 << (n + 8))) {
+            eptsta = UDPHS->UDPHS_EPT[n].UDPHS_EPTSTA;  /* Read EP status           */
+            eptsta_copy[n] = eptsta;
+
+            /* Data Packet Sent Interrupt                                           */
+            if (eptsta & (1 << 10)) {         /* Transmitted IN Data Complete Int   */
+                UDPHS->UDPHS_EPT[n].UDPHS_EPTCLRSTA = (1 << 10);    /* Tx IN Clear    */
+#ifdef __RTX
+
+                if (USBD_RTX_EPTask[n]) {       /* IN Packet                          */
+                    isr_evt_set(USBD_EVT_IN,  USBD_RTX_EPTask[n]);
+                }
+
+#else
+
+                if (USBD_P_EP[n]) {
+                    USBD_P_EP[n](USBD_EVT_IN);
+                }
+
+#endif
+            }
+
+            /* Data Packet Received Interrupt                                       */
+            if (eptsta & (1 << 9)) {          /* Received OUT Data Interrupt        */
+                UDPHS->UDPHS_IEN &= ~(1 << (n + 8));      /* Disable EP int until read*/
+#ifdef __RTX
+
+                if (USBD_RTX_EPTask[n]) {       /* OUT Packet                         */
+                    isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[n]);
+                }
+
+#else
+
+                if (USBD_P_EP[n]) {
+                    USBD_P_EP[n](USBD_EVT_OUT);
+                }
+
+#endif
+            }
+
+            /* STALL Packet Sent Interrupt                                          */
+            if (eptsta & (0x1 << 13)) {       /* Stall Sent                         */
+                if ((UDPHS->UDPHS_EPT[n].UDPHS_EPTCFG & UDPHS_EPTCFG_EPT_TYPE_Msk) == UDPHS_EPTCFG_EPT_TYPE_CTRL8) {
+#ifdef __RTX
+
+                    if (USBD_RTX_EPTask[n]) {
+                        isr_evt_set(USBD_EVT_IN_STALL, USBD_RTX_EPTask[n]);
+                    }
+
+#else
+
+                    if (USBD_P_EP[n]) {
+                        USBD_P_EP[n](USBD_EVT_IN_STALL);
+                    }
+
+#endif
+                }
+
+                UDPHS->UDPHS_EPT[n].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_STALL_SNT;
+            }
+
+            /* Setup Packet Received Interrupt                                      */
+            if (eptsta & (0x1 << 12)) {       /* Received SETUP Interrupt           */
+                UDPHS->UDPHS_IEN &= ~(1 << (n + 8));      /* Disable EP int until read*/
+#ifdef __RTX
+
+                if (USBD_RTX_EPTask[n]) {       /* SETUP Packet                       */
+                    isr_evt_set(USBD_EVT_SETUP, USBD_RTX_EPTask[n]);
+                }
+
+#else
+
+                if (USBD_P_EP[n]) {
+                    USBD_P_EP[n](USBD_EVT_SETUP);
+                }
+
+#endif
+            }
+        }
+    }
+
+    NVIC_EnableIRQ(UDPHS_IRQn);
+}