Arrow / Mbed OS DAPLink Reset
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbd_LPC11Uxx.c Source File

usbd_LPC11Uxx.c

Go to the documentation of this file.
00001 /**
00002  * @file    usbd_LPC11Uxx.c
00003  * @brief   
00004  *
00005  * DAPLink Interface Firmware
00006  * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
00007  * SPDX-License-Identifier: Apache-2.0
00008  *
00009  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00010  * not use this file except in compliance with the License.
00011  * You may obtain a copy of the License at
00012  *
00013  * http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing, software
00016  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00017  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00018  * See the License for the specific language governing permissions and
00019  * limitations under the License.
00020  */
00021 
00022 #include "rl_usb.h"
00023 #include "LPC11Uxx.h"
00024 #include "compiler.h"
00025 #include "util.h"
00026 
00027 #define __NO_USB_LIB_C
00028 #include "usb_config.c"
00029 
00030 
00031 #define BUF_ACTIVE         (1UL << 31)
00032 #define EP_DISABLED        (1UL << 30)
00033 #define EP_STALL           (1UL << 29)
00034 #define TOOGLE_RESET       (1UL << 28)
00035 #define EP_TYPE            (1UL << 26)
00036 
00037 #define N_BYTES(n)         ((n & 0x3FF) << 16)
00038 #define BUF_ADDR(addr)     (((addr) >> 6) & 0xFFFF)
00039 
00040 #define EP_OUT_IDX(EPNum)  (EPNum * 2    )
00041 #define EP_IN_IDX(EPNum)   (EPNum * 2 + 1)
00042 
00043 #define EP_LIST_BASE       0x20004000
00044 #define EP_BUF_BASE        (U32)(EP_LIST_BASE + 0x100)
00045 
00046 typedef struct BUF_INFO {
00047     U32  buf_len;
00048     U32  buf_ptr;
00049 } EP_BUF_INFO;
00050 
00051 EP_BUF_INFO EPBufInfo[(USBD_EP_NUM + 1) * 2];
00052 volatile U32 EPList[(USBD_EP_NUM + 1) * 2]  __at(EP_LIST_BASE);
00053 
00054 static U32 addr = 3 * 64 + EP_BUF_BASE;
00055 static U32 ctrl_out_next = 0;
00056 
00057 /*
00058  *  Get EP CmdStat pointer
00059  *    Parameters:    EPNum: endpoint number
00060  *
00061  */
00062 
00063 U32 *GetEpCmdStatPtr(U32 EPNum)
00064 {
00065     U32 ptr = 0;
00066 
00067     if (EPNum & 0x80) {
00068         EPNum &= ~0x80;
00069         ptr = 8;
00070     }
00071 
00072     ptr += EP_LIST_BASE + EPNum * 16;
00073     return ((U32 *)ptr);
00074 }
00075 
00076 
00077 /*
00078  *  Usb interrupt enable/disable
00079  *    Parameters:      ena: enable/disable
00080  *                       0: disable interrupt
00081  *                       1: enable interrupt
00082  */
00083 
00084 #ifdef __RTX
00085 void __svc(1) USBD_Intr(int ena);
00086 void __SVC_1(int ena)
00087 {
00088     if (ena) {
00089         NVIC_EnableIRQ(USB_IRQn );           /* Enable USB interrupt */
00090     } else {
00091         NVIC_DisableIRQ(USB_IRQn );          /* Disable USB interrupt */
00092     }
00093 }
00094 #endif
00095 
00096 
00097 
00098 /*
00099  *  USB Device Initialize Function
00100  *   Called by the User to initialize USB Device
00101  *    Return Value:    None
00102  */
00103 
00104 void USBD_Init(void)
00105 {
00106     LPC_SYSCON->SYSAHBCLKCTRL |= (1UL <<  6);
00107     LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 14) |
00108                                  (1UL << 27);
00109     LPC_USB->DEVCMDSTAT  |= (1UL << 9);     /* PLL ON */
00110     LPC_IOCON->PIO0_3    &=  ~(0x1F);
00111     LPC_IOCON->PIO0_3    |= (1UL << 0);     /* Secondary function VBUS */
00112     LPC_IOCON->PIO0_6    &=   ~7;
00113     LPC_IOCON->PIO0_6    |= (1UL << 0);     /* Secondary function USB CON */
00114     LPC_SYSCON->PDRUNCFG &= ~((1UL << 8) |  /* USB PLL powered */
00115                               (1UL << 10)); /* USB transceiver powered */
00116     LPC_USB->DATABUFSTART = EP_BUF_BASE & 0xFFC00000;
00117     LPC_USB->EPLISTSTART  = EP_LIST_BASE;
00118     NVIC_EnableIRQ(USB_IRQn );
00119     USBD_Reset();
00120 }
00121 
00122 
00123 /*
00124  *  USB Device Connect Function
00125  *   Called by the User to Connect/Disconnect USB Device
00126  *    Parameters:      con:   Connect/Disconnect
00127  *    Return Value:    None
00128  */
00129 
00130 void USBD_Connect(BOOL con)
00131 {
00132     if (con) {
00133         LPC_USB->DEVCMDSTAT |= (1UL << 16);    /* Set device connect status */
00134     } else {
00135         LPC_USB->DEVCMDSTAT &= ~(1UL << 16);   /* Clear device connect status */
00136     }
00137 
00138     return;
00139 }
00140 
00141 
00142 /*
00143  *  USB Device Reset Function
00144  *   Called automatically on USB Device Reset
00145  *    Return Value:    None
00146  */
00147 
00148 void USBD_Reset(void)
00149 {
00150     U32 i;
00151     U32 *ptr;
00152     addr = 3 * 64 + EP_BUF_BASE;
00153 
00154     for (i = 2; i < (5 * 4); i++) {
00155         EPList[i] = (1UL << 30);            /* EPs disabled */
00156     }
00157 
00158     ctrl_out_next = 0;
00159     EPBufInfo[0].buf_len = USBD_MAX_PACKET0;
00160     EPBufInfo[0].buf_ptr = EP_BUF_BASE;
00161     EPBufInfo[1].buf_len = USBD_MAX_PACKET0;
00162     EPBufInfo[1].buf_ptr = EP_BUF_BASE + 2 * 64;
00163     ptr  = GetEpCmdStatPtr(0);
00164     *ptr = N_BYTES(EPBufInfo[0].buf_len) |     /* EP0 OUT */
00165            BUF_ADDR(EPBufInfo[0].buf_ptr) |
00166            BUF_ACTIVE;
00167     ptr++;
00168     *ptr = BUF_ADDR(EPBufInfo[0].buf_ptr + 64);/* SETUP */
00169     LPC_USB->DEVCMDSTAT |= (1UL << 7);         /*USB device enable */
00170     LPC_USB->INTSTAT     = 0x2FC;              /* clear EP interrupt flags */
00171     LPC_USB->INTEN = ((1UL << 30) |            /* SOF intr enable */
00172                       (1UL << 0)     | /* EP0 OUT intr enable */
00173                       (1UL << 1)     | /* EP0 IN intr enable */
00174                       (1UL << 31));    /* stat change int en */
00175 }
00176 
00177 
00178 /*
00179  *  USB Device Suspend Function
00180  *   Called automatically on USB Device Suspend
00181  *    Return Value:    None
00182  */
00183 
00184 void USBD_Suspend(void)
00185 {
00186     /* Performed by Hardware */
00187 }
00188 
00189 
00190 /*
00191  *  USB Device Resume Function
00192  *   Called automatically on USB Device Resume
00193  *    Return Value:    None
00194  */
00195 
00196 void USBD_Resume(void)
00197 {
00198     /* Performed by Hardware */
00199 }
00200 
00201 
00202 /*
00203  *  USB Device Remote Wakeup Function
00204  *   Called automatically on USB Device Remote Wakeup
00205  *    Return Value:    None
00206  */
00207 
00208 void USBD_WakeUp(void)
00209 {
00210     LPC_SYSCON->USBCLKCTRL = 1;
00211     LPC_USB->DEVCMDSTAT &= ~(1UL << 17);  /*clear device suspend status */
00212 
00213     while (LPC_USB->DEVCMDSTAT & (1UL << 17));
00214 
00215     LPC_SYSCON->USBCLKCTRL = 0;
00216 }
00217 
00218 
00219 /*
00220  *  USB Device Remote Wakeup Configuration Function
00221  *    Parameters:      cfg:   Device Enable/Disable
00222  *    Return Value:    None
00223  */
00224 
00225 void USBD_WakeUpCfg(BOOL cfg)
00226 {
00227     if (cfg == __TRUE) {
00228         LPC_USB->DEVCMDSTAT &= ~(1UL << 9); /*PPL_ON=0, in suspend clk is stoped */
00229     } else {
00230         LPC_USB->DEVCMDSTAT |= (1UL << 9);  /*PPL_ON=1, in suspend clk isnt stoped */
00231         LPC_SYSCON->USBCLKCTRL = 0;
00232     }
00233 }
00234 
00235 
00236 /*
00237  *  USB Device Set Address Function
00238  *    Parameters:      adr:   USB Device Address
00239  *    Return Value:    None
00240  */
00241 
00242 void USBD_SetAddress(U32 adr, U32 setup)
00243 {
00244     if (!setup) {
00245         LPC_USB->DEVCMDSTAT &= ~0x7F;
00246         LPC_USB->DEVCMDSTAT |= adr | (1UL << 7);
00247     }
00248 }
00249 
00250 
00251 
00252 /*
00253  *  USB Device Configure Function
00254  *    Parameters:      cfg:   Device Configure/Deconfigure
00255  *    Return Value:    None
00256  */
00257 
00258 void USBD_Configure(BOOL cfg)
00259 {
00260     addr = 3 * 64 + EP_BUF_BASE;
00261 }
00262 
00263 
00264 /*
00265  *  Configure USB Device Endpoint according to Descriptor
00266  *    Parameters:      pEPD:  Pointer to Device Endpoint Descriptor
00267  *    Return Value:    None
00268  */
00269 
00270 void USBD_ConfigEP(USB_ENDPOINT_DESCRIPTOR *pEPD)
00271 {
00272     U32 num, val, type;
00273     U32 *ptr;
00274     num  = pEPD->bEndpointAddress;
00275     val  = pEPD->wMaxPacketSize;
00276     type = pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK;
00277 
00278     /* IN EPs */
00279     if (num & 0x80) {
00280         num &= ~0x80;
00281         EPBufInfo[EP_IN_IDX(num)].buf_len  = val;
00282         EPBufInfo[EP_IN_IDX(num)].buf_ptr  = addr;
00283         addr += ((val + 63) >> 6) * 64;     /* calc new free buffer address */
00284         ptr  = GetEpCmdStatPtr(num | 0x80);
00285         *ptr = EP_DISABLED;
00286 
00287         if (type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
00288             *ptr |= EP_TYPE;
00289         }
00290     }
00291 
00292     /* OUT EPs */
00293     else {
00294         EPBufInfo[EP_OUT_IDX(num)].buf_len  = val;
00295         EPBufInfo[EP_OUT_IDX(num)].buf_ptr  = addr;
00296         ptr  = GetEpCmdStatPtr(num);
00297         *ptr = N_BYTES(EPBufInfo[EP_OUT_IDX(num)].buf_len) |
00298                BUF_ADDR(EPBufInfo[EP_OUT_IDX(num)].buf_ptr) |
00299                EP_DISABLED;
00300 
00301         if (type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
00302             *ptr |= EP_TYPE;
00303         }
00304 
00305         addr += ((val + 63) >> 6) * 64;     /* calc new free buffer address */
00306     }
00307 }
00308 
00309 
00310 /*
00311  *  Set Direction for USB Device Control Endpoint
00312  *    Parameters:      dir:   Out (dir == 0), In (dir <> 0)
00313  *    Return Value:    None
00314  */
00315 
00316 void USBD_DirCtrlEP(U32 dir)
00317 {
00318     /* Not needed */
00319 }
00320 
00321 
00322 /*
00323  *  Enable USB Device Endpoint
00324  *    Parameters:      EPNum: Device Endpoint Number
00325  *                       EPNum.0..3: Address
00326  *                       EPNum.7:    Dir
00327  *    Return Value:    None
00328  */
00329 
00330 void USBD_EnableEP(U32 EPNum)
00331 {
00332     U32 *ptr;;
00333     ptr = GetEpCmdStatPtr(EPNum);
00334 
00335     /* IN EP */
00336     if (EPNum & 0x80) {
00337         EPNum &= ~0x80;
00338         *ptr &= ~EP_DISABLED;
00339         LPC_USB->INTSTAT = (1 << EP_IN_IDX(EPNum));
00340         LPC_USB->INTEN  |= (1 << EP_IN_IDX(EPNum));
00341     }
00342 
00343     /* OUT EP */
00344     else {
00345         *ptr &= ~EP_DISABLED;
00346         *ptr |=  BUF_ACTIVE;
00347         LPC_USB->INTSTAT = (1 << EP_OUT_IDX(EPNum));
00348         LPC_USB->INTEN  |= (1 << EP_OUT_IDX(EPNum));
00349     }
00350 }
00351 
00352 
00353 /*
00354  *  Disable USB Device Endpoint
00355  *    Parameters:      EPNum: Device Endpoint Number
00356  *                       EPNum.0..3: Address
00357  *                       EPNum.7:    Dir
00358  *    Return Value:    None
00359  */
00360 
00361 void USBD_DisableEP(U32 EPNum)
00362 {
00363     U32 *ptr;
00364     ptr = GetEpCmdStatPtr(EPNum);
00365     *ptr = EP_DISABLED;
00366 
00367     if (EPNum & 0x80) {
00368         EPNum &= ~0x80;
00369         LPC_USB->INTEN &= ~(1 << EP_IN_IDX(EPNum));
00370 
00371     } else {
00372         LPC_USB->INTEN &= ~(1 << EP_OUT_IDX(EPNum));
00373     }
00374 }
00375 
00376 
00377 /*
00378  *  Reset USB Device Endpoint
00379  *    Parameters:      EPNum: Device Endpoint Number
00380  *                       EPNum.0..3: Address
00381  *                       EPNum.7:    Dir
00382  *    Return Value:    None
00383  */
00384 
00385 void USBD_ResetEP(U32 EPNum)
00386 {
00387     U32 *ptr;
00388     ptr = GetEpCmdStatPtr(EPNum);
00389     *ptr |= TOOGLE_RESET;
00390 }
00391 
00392 
00393 /*
00394  *  Set Stall for USB Device Endpoint
00395  *    Parameters:      EPNum: Device Endpoint Number
00396  *                       EPNum.0..3: Address
00397  *                       EPNum.7:    Dir
00398  *    Return Value:    None
00399  */
00400 
00401 void USBD_SetStallEP(U32 EPNum)
00402 {
00403     U32 *ptr;
00404     ptr = GetEpCmdStatPtr(EPNum);
00405 
00406     if (EPNum & 0x7F) {
00407         if (*ptr & BUF_ACTIVE) {
00408             *ptr &= ~(BUF_ACTIVE);
00409         }
00410 
00411     } else {
00412         if (EPNum & 0x80) {
00413             EPNum &= ~0x80;
00414             LPC_USB->EPSKIP |= (1 << EP_IN_IDX(EPNum));
00415 
00416             while (LPC_USB->EPSKIP & (1 << EP_IN_IDX(EPNum)));
00417 
00418         } else {
00419             LPC_USB->EPSKIP |= (1 << EP_OUT_IDX(EPNum));
00420 
00421             while (LPC_USB->EPSKIP & (1 << EP_OUT_IDX(EPNum)));
00422         }
00423     }
00424 
00425     if ((EPNum & 0x7F) == 0) {
00426         /* Endpoint is stalled so control out won't be next */
00427         ctrl_out_next = 0;
00428     }
00429 
00430     *ptr |=  EP_STALL;
00431 }
00432 
00433 
00434 /*
00435  *  Clear Stall for USB Device Endpoint
00436  *    Parameters:      EPNum: Device Endpoint Number
00437  *                       EPNum.0..3: Address
00438  *                       EPNum.7:    Dir
00439  *    Return Value:    None
00440  */
00441 
00442 void USBD_ClrStallEP(U32 EPNum)
00443 {
00444     U32 *ptr;
00445     ptr = GetEpCmdStatPtr(EPNum);
00446 
00447     if (EPNum & 0x80) {
00448         *ptr &=  ~EP_STALL;
00449 
00450     } else {
00451         *ptr &=  ~EP_STALL;
00452         *ptr |=   BUF_ACTIVE;
00453     }
00454 
00455     USBD_ResetEP(EPNum);
00456 }
00457 
00458 
00459 /*
00460  *  Clear USB Device Endpoint Buffer
00461  *    Parameters:      EPNum: Device Endpoint Number
00462  *                       EPNum.0..3: Address
00463  *                       EPNum.7:    Dir
00464  *    Return Value:    None
00465  */
00466 
00467 void USBD_ClearEPBuf(U32 EPNum)
00468 {
00469     U32  cnt, i;
00470     U8  *dataptr;
00471 
00472     if (EPNum & 0x80) {
00473         EPNum &= ~0x80;
00474         dataptr = (U8 *)EPBufInfo[EP_IN_IDX(EPNum)].buf_ptr;
00475         cnt     =       EPBufInfo[EP_IN_IDX(EPNum)].buf_len;
00476 
00477         for (i = 0; i < cnt; i++) {
00478             dataptr[i] = 0;
00479         }
00480 
00481     } else {
00482         dataptr = (U8 *)EPBufInfo[EP_OUT_IDX(EPNum)].buf_ptr;
00483         cnt     =       EPBufInfo[EP_OUT_IDX(EPNum)].buf_len;
00484 
00485         for (i = 0; i < cnt; i++) {
00486             dataptr[i] = 0;
00487         }
00488     }
00489 }
00490 
00491 
00492 /*
00493  *  Read USB Device Endpoint Data
00494  *    Parameters:      EPNum: Device Endpoint Number
00495  *                       EPNum.0..3: Address
00496  *                       EPNum.7:    Dir
00497  *                     pData: Pointer to Data Buffer
00498  *    Return Value:    Number of bytes read
00499  */
00500 
00501 U32 USBD_ReadEP(U32 EPNum, U8 *pData, U32 size)
00502 {
00503     U32 cnt, i, xfer_size;
00504     volatile U32 *ptr;
00505     U8 *dataptr;
00506     ptr = GetEpCmdStatPtr(EPNum);
00507     int timeout = 256;
00508 
00509     /* Setup packet */
00510     if ((EPNum == 0) && !ctrl_out_next && (LPC_USB->DEVCMDSTAT & (1UL << 8))) {
00511         cnt = USBD_MAX_PACKET0;
00512 
00513         if (size < cnt) {
00514             util_assert(0);
00515             cnt = size;
00516         }
00517 
00518         dataptr = (U8 *)(EPBufInfo[EP_OUT_IDX(EPNum)].buf_ptr + 64);
00519 
00520         for (i = 0; i < cnt; i++) {
00521             pData[i] = dataptr[i];
00522         }
00523 
00524         xfer_size = (pData[7] << 8) | (pData[6] << 0);
00525         if ((xfer_size > 0) && (pData[0] & (1 << 7))) {
00526             /* This control transfer has a data IN stage            */
00527             /* and ends with a zero length data OUT transfer.       */
00528             /* Ensure the data OUT token is not skipped even if     */
00529             /* a SETUP token arrives before USBD_ReadEP has         */
00530             /* been called.                                         */
00531             ctrl_out_next = 1;
00532         }
00533 
00534         LPC_USB->EPSKIP |= (1 << EP_IN_IDX(EPNum));
00535 
00536         while (LPC_USB->EPSKIP & (1 << EP_IN_IDX(EPNum)));
00537 
00538         if (*(ptr + 2) & EP_STALL) {
00539             *(ptr + 2) &= ~(EP_STALL);
00540         }
00541 
00542         if (*ptr & EP_STALL) {
00543             *ptr &= ~(EP_STALL);
00544         }
00545 
00546         LPC_USB->DEVCMDSTAT |= (1UL << 8);
00547     }
00548 
00549     /* OUT packet */
00550     else {
00551         ptr = GetEpCmdStatPtr(EPNum);
00552         cnt = EPBufInfo[EP_OUT_IDX(EPNum)].buf_len - ((*ptr >> 16) & 0x3FF);
00553         dataptr = (U8 *)EPBufInfo[EP_OUT_IDX(EPNum)].buf_ptr;
00554 
00555         while ((timeout-- > 0) && (*ptr & BUF_ACTIVE)); //spin on the hardware until it's done        
00556         util_assert(!(*ptr & BUF_ACTIVE)); //check for timeout
00557         
00558         if (size < cnt) {
00559             util_assert(0);
00560             cnt = size;
00561         }
00562 
00563         cnt = cnt < size ? cnt : size;
00564 
00565         for (i = 0; i < cnt; i++) {
00566             pData[i] = dataptr[i];
00567         }
00568 
00569         *ptr = N_BYTES(EPBufInfo[EP_OUT_IDX(EPNum)].buf_len) |
00570                BUF_ADDR(EPBufInfo[EP_OUT_IDX(EPNum)].buf_ptr) |
00571                BUF_ACTIVE;
00572 
00573         if (EPNum == 0) {
00574             /* If ctrl_out_next is set then this should be a zero length        */
00575             /* data OUT packet.                                                 */
00576             util_assert(!ctrl_out_next || (cnt == 0));
00577             ctrl_out_next = 0;
00578             if (LPC_USB->DEVCMDSTAT & (1UL << 8))  {
00579                 // A setup packet is still pending so trigger another interrupt
00580                 LPC_USB->INTSETSTAT |= (1 << 0);
00581             }
00582         }
00583     }
00584 
00585     return (cnt);
00586 }
00587 
00588 
00589 /*
00590  *  Write USB Device Endpoint Data
00591  *    Parameters:      EPNum: Endpoint Number
00592  *                       EPNum.0..3: Address
00593  *                       EPNum.7:    Dir
00594  *                     pData: Pointer to Data Buffer
00595  *                     cnt:   Number of bytes to write
00596  *    Return Value:    Number of bytes written
00597  */
00598 
00599 U32 USBD_WriteEP(U32 EPNum, U8 *pData, U32 cnt)
00600 {
00601     U32 i;
00602     volatile U32 *ptr;
00603     U32 *dataptr;
00604     ptr = GetEpCmdStatPtr(EPNum);
00605     EPNum &= ~0x80;
00606 
00607     while (*ptr & BUF_ACTIVE);
00608 
00609     *ptr &= ~(0x3FFFFFF);
00610     *ptr |=  BUF_ADDR(EPBufInfo[EP_IN_IDX(EPNum)].buf_ptr) |
00611              N_BYTES(cnt);
00612     dataptr = (U32 *)EPBufInfo[EP_IN_IDX(EPNum)].buf_ptr;
00613 
00614     for (i = 0; i < (cnt + 3) / 4; i++) {
00615         dataptr[i] = * ((__packed U32 *)pData);
00616         pData += 4;
00617     }
00618 
00619     if (EPNum && (*ptr & EP_STALL)) {
00620         return (0);
00621     }
00622 
00623     *ptr |= BUF_ACTIVE;
00624     return (cnt);
00625 }
00626 
00627 
00628 /*
00629  *  Get USB Device Last Frame Number
00630  *    Parameters:      None
00631  *    Return Value:    Frame Number
00632  */
00633 
00634 U32 USBD_GetFrame(void)
00635 {
00636     return (LPC_USB->INFO & 0x7FF);
00637 }
00638 
00639 
00640 /*
00641  *  USB Device Interrupt Service Routine
00642  */
00643 
00644 void USB_IRQHandler(void)
00645 {
00646     NVIC_DisableIRQ(USB_IRQn );
00647     USBD_SignalHandler();
00648 }
00649 
00650 void USBD_Handler(void)
00651 {
00652     U32 sts, val, num, i;
00653     sts = LPC_USB->INTSTAT;
00654     LPC_USB->INTSTAT = sts;
00655 
00656     /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
00657     if (sts & (1UL << 31)) {
00658         val = LPC_USB->DEVCMDSTAT;
00659 
00660         /* reset interrupt */
00661         if (val & (1UL << 26)) {
00662             LPC_USB->DEVCMDSTAT |= (1UL << 26);
00663             USBD_Reset();
00664             usbd_reset_core();
00665 #ifdef __RTX
00666 
00667             if (USBD_RTX_DevTask) {
00668                 isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask);
00669             }
00670 
00671 #else
00672 
00673             if (USBD_P_Reset_Event) {
00674                 USBD_P_Reset_Event();
00675             }
00676 
00677 #endif
00678         }
00679 
00680         /* connect interrupt */
00681         if (val & (1UL << 24)) {
00682             LPC_USB->DEVCMDSTAT |= (1UL << 24);
00683 #ifdef __RTX
00684 
00685             if (USBD_RTX_DevTask) {
00686                 if (val & (1UL << 16)) {
00687                     isr_evt_set(USBD_EVT_POWER_ON,  USBD_RTX_DevTask);
00688                 } else {
00689                     isr_evt_set(USBD_EVT_POWER_OFF, USBD_RTX_DevTask);
00690                 }
00691             }
00692 
00693 #else
00694 
00695             if (USBD_P_Power_Event) {
00696                 USBD_P_Power_Event((val >> 16) & 1);
00697             }
00698 
00699 #endif
00700         }
00701 
00702         /* suspend/resume interrupt */
00703         if (val & (1 << 25)) {
00704             LPC_USB->DEVCMDSTAT |= (1UL << 25);
00705 
00706             /* suspend interrupt */
00707             if (val & (1UL << 17)) {
00708                 USBD_Suspend();
00709 #ifdef __RTX
00710 
00711                 if (USBD_RTX_DevTask) {
00712                     isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask);
00713                 }
00714 
00715 #else
00716 
00717                 if (USBD_P_Suspend_Event) {
00718                     USBD_P_Suspend_Event();
00719                 }
00720 
00721 #endif
00722             }
00723 
00724             /* resume interrupt */
00725             else {
00726 #ifdef __RTX
00727 
00728                 if (USBD_RTX_DevTask) {
00729                     isr_evt_set(USBD_EVT_RESUME,  USBD_RTX_DevTask);
00730                 }
00731 
00732 #else
00733 
00734                 if (USBD_P_Resume_Event) {
00735                     USBD_P_Resume_Event();
00736                 }
00737 
00738 #endif
00739             }
00740         }
00741     }
00742 
00743     /* Start of Frame */
00744     if (sts & (1UL << 30)) {
00745 #ifdef __RTX
00746 
00747         if (USBD_RTX_DevTask) {
00748             isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
00749         }
00750 
00751 #else
00752 
00753         if (USBD_P_SOF_Event) {
00754             USBD_P_SOF_Event();
00755         }
00756 
00757 #endif
00758     }
00759 
00760     /* EndPoint Interrupt */
00761     if (sts & 0x3FF) {
00762         const uint32_t endpoint_count = ((USBD_EP_NUM + 1) * 2);
00763 
00764         for (i = 0; i < endpoint_count; i++) {
00765             // Iterate through endpoints in the reverse order so IN endpoints
00766             // get processed before OUT endpoints if they are both pending.
00767             num = endpoint_count - i - 1;
00768 
00769             if (sts & (1UL << num)) {
00770                 /* Setup */
00771                 if ((num == 0) && !ctrl_out_next && (LPC_USB->DEVCMDSTAT & (1UL << 8))) {
00772 #ifdef __RTX
00773 
00774                     if (USBD_RTX_EPTask[num / 2]) {
00775                         isr_evt_set(USBD_EVT_SETUP, USBD_RTX_EPTask[num / 2]);
00776                     }
00777 
00778 #else
00779 
00780                     if (USBD_P_EP[num / 2]) {
00781                         USBD_P_EP[num / 2](USBD_EVT_SETUP);
00782                     }
00783 
00784 #endif
00785                 }
00786 
00787                 /* OUT */
00788                 else if ((num % 2) == 0) {
00789 #ifdef __RTX
00790 
00791                     if (USBD_RTX_EPTask[num / 2]) {
00792                         isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[num / 2]);
00793                     }
00794 
00795 #else
00796 
00797                     if (USBD_P_EP[num / 2]) {
00798                         USBD_P_EP[num / 2](USBD_EVT_OUT);
00799                     }
00800 
00801 #endif
00802                 }
00803 
00804                 /* IN */
00805                 else {
00806 #ifdef __RTX
00807 
00808                     if (USBD_RTX_EPTask[num / 2]) {
00809                         isr_evt_set(USBD_EVT_IN,  USBD_RTX_EPTask[num / 2]);
00810                     }
00811 
00812 #else
00813 
00814                     if (USBD_P_EP[num / 2]) {
00815                         USBD_P_EP[num / 2](USBD_EVT_IN);
00816                     }
00817 
00818 #endif
00819                 }
00820             }
00821         }
00822     }
00823 
00824     NVIC_EnableIRQ(USB_IRQn );
00825 }