USB Mouse (relative) example for mbed NXP LPC11U24 beta

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBBusInterface_LPC11U.c Source File

USBBusInterface_LPC11U.c

00001 /* USBBusInterface_LPC11U.c */
00002 /* USB Bus Interface for NXP LPC11Uxx */
00003 /* Copyright (c) 2011 ARM Limited. All rights reserved. */
00004 
00005 /* Reference: */
00006 /* NXP UM10462 LPC11U1x User manual Rev. 1 � 14 April 2011 */
00007 
00008 #ifdef TARGET_LPC11U24
00009 
00010 #include "USBBusInterface.h"
00011 #include "USBUtils.h"
00012 #include "USBEvents.h"
00013 
00014 
00015 /* Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1) */
00016 #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
00017 /* Convert physical endpoint number to register bit */
00018 #define EP(endpoint) (1UL<<endpoint)
00019 /* Convert physical to logical */
00020 #define PHY_TO_LOG(endpoint)    ((endpoint)>>1)
00021 /* Get endpoint direction */
00022 #define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
00023 #define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
00024 
00025 /* USB RAM */
00026 #define USB_RAM_START (0x20004000)
00027 #define USB_RAM_SIZE  (0x00000800)
00028 
00029 /* SYSAHBCLKCTRL */
00030 #define CLK_USB     (1UL<<14)
00031 #define CLK_USBRAM  (1UL<<27)
00032 
00033 /* USB Information register */
00034 #define FRAME_NR(a)     ((a) & 0x7ff)   /* Frame number */
00035 
00036 /* USB Device Command/Status register */
00037 #define DEV_ADDR_MASK   (0x7f)          /* Device address */
00038 #define DEV_ADDR(a)     ((a) & DEV_ADDR_MASK)
00039 #define DEV_EN          (1UL<<7)        /* Device enable */
00040 #define SETUP           (1UL<<8)        /* SETUP token received */
00041 #define PLL_ON          (1UL<<9)        /* PLL enabled in suspend */
00042 #define DCON            (1UL<<16)       /* Device status - connect */
00043 #define DSUS            (1UL<<17)       /* Device status - suspend */
00044 #define DCON_C          (1UL<<24)       /* Connect change */
00045 #define DSUS_C          (1UL<<25)       /* Suspend change */
00046 #define DRES_C          (1UL<<26)       /* Reset change */
00047 #define VBUSDEBOUNCED   (1UL<<28)       /* Vbus detected */
00048 
00049 /* Endpoint Command/Status list */
00050 #define CMDSTS_A                 (1UL<<31)          /* Active */
00051 #define CMDSTS_D                 (1UL<<30)          /* Disable */
00052 #define CMDSTS_S                 (1UL<<29)          /* Stall */
00053 #define CMDSTS_TR                (1UL<<28)          /* Toggle Reset */
00054 #define CMDSTS_RF                (1UL<<27)          /* Rate Feedback mode */
00055 #define CMDSTS_TV                (1UL<<27)          /* Toggle Value */
00056 #define CMDSTS_T                 (1UL<<26)          /* Endpoint Type */
00057 #define CMDSTS_NBYTES(n)         (((n)&0x3ff)<<16)  /* Number of bytes */
00058 #define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff)  /* Buffer start address */
00059 
00060 #define BYTES_REMAINING(s)       (((s)>>16)&0x3ff)  /* Bytes remaining after transfer */
00061 
00062 /* USB Non-endpoint interrupt sources */
00063 #define FRAME_INT   (1UL<<30)
00064 #define DEV_INT     (1UL<<31)
00065 
00066 /* One entry for a double-buffered logical endpoint in the endpoint */
00067 /* command/status list. Endpoint 0 is single buffered, out[1] is used */
00068 /* for the SETUP packet and in[1] is not used */
00069 typedef __packed struct {
00070     uint32_t out[2];
00071     uint32_t in[2];
00072     } EP_COMMAND_STATUS;
00073 
00074 typedef __packed struct {
00075     uint8_t out[MAX_PACKET_SIZE_EP0];
00076     uint8_t in[MAX_PACKET_SIZE_EP0];
00077     uint8_t setup[SETUP_PACKET_SIZE];
00078     } CONTROL_TRANSFER;
00079 
00080 typedef __packed struct {
00081     uint32_t    maxPacket;
00082     uint32_t    buffer[2];
00083     uint32_t    options;
00084     } EP_STATE;
00085 
00086 static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
00087 
00088 /* Pointer to the endpoint command/status list */
00089 static EP_COMMAND_STATUS *ep = NULL;
00090 
00091 /* Pointer to endpoint 0 data (IN/OUT and SETUP) */
00092 static CONTROL_TRANSFER *ct = NULL;
00093 
00094 /* Shadow DEVCMDSTAT register to avoid accidentally clearing flags or */
00095 /* initiating a remote wakeup event. */
00096 static volatile uint32_t devCmdStat;
00097 
00098 /* Pointers used to allocate USB RAM */
00099 static uint32_t usbRamPtr = USB_RAM_START;
00100 static uint32_t epRamPtr = 0; /* Buffers for endpoints > 0 start here */
00101 
00102 /*
00103  *  USBBusInterface API
00104  */
00105 
00106 bool USBBusInterface_init(void)
00107 {
00108     NVIC_DisableIRQ(USB_IRQn);
00109 
00110     /* USB_VBUS input, Pull down, Hysteresis enabled */
00111     //LPC_IOCON->PIO0_3 = 0x00000029;
00112     /* nUSB_CONNECT output */
00113     LPC_IOCON->PIO0_6 = 0x00000001;
00114 
00115     /* Enable clocks (USB registers, USB RAM) */
00116     LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
00117 
00118     /* Ensure device disconnected (DCON not set) */
00119     LPC_USB->DEVCMDSTAT = 0;
00120     /* Device must be disconnected for at least 2.5uS */
00121     /* to ensure that the USB host sees the device as */
00122     /* disconnected if the target CPU is reset. */
00123     wait(0.3);
00124     
00125 
00126     /* Reserve space in USB RAM for endpoint command/status list */
00127     /* Must be 256 byte aligned */
00128     usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256);
00129     ep = (EP_COMMAND_STATUS *)usbRamPtr;
00130     usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS);
00131     LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00;
00132 
00133     /* Reserve space in USB RAM for Endpoint 0 */
00134     /* Must be 64 byte aligned */
00135     usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64);
00136     ct = (CONTROL_TRANSFER *)usbRamPtr;
00137     usbRamPtr += sizeof(CONTROL_TRANSFER);
00138     LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000;
00139 
00140     /* Setup command/status list for EP0 */
00141     ep[0].out[0] = 0;
00142     ep[0].in[0] =  0;
00143     ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup);
00144 
00145     /* Route all interrupts to IRQ, some can be routed to  */
00146     /* USB_FIQ if you wish. */
00147     LPC_USB->INTROUTING = 0;
00148 
00149     /* Set device address 0, enable USB device, no remote wakeup */
00150     devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS;
00151     LPC_USB->DEVCMDSTAT = devCmdStat;
00152 
00153     /* Enable interrupts for device events and EP0 */
00154     LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT);
00155     NVIC_EnableIRQ(USB_IRQn);
00156     
00157 
00158     /* Successful */
00159     return true;
00160 }
00161 
00162 void USBBusInterface_uninit(void)
00163 {
00164     /* Ensure device disconnected (DCON not set) */
00165     LPC_USB->DEVCMDSTAT = 0;
00166 
00167     /* Disable USB interrupts */
00168     NVIC_DisableIRQ(USB_IRQn);
00169 }
00170 
00171 void USBBusInterface_connect(void)
00172 {
00173     devCmdStat |= DCON;
00174     LPC_USB->DEVCMDSTAT = devCmdStat;
00175 }
00176 
00177 void USBBusInterface_disconnect(void)
00178 {
00179     devCmdStat &= ~DCON;
00180     LPC_USB->DEVCMDSTAT = devCmdStat;
00181 }
00182 
00183 void USBBusInterface_configureDevice(void)
00184 {
00185 }
00186 
00187 void USBBusInterface_unconfigureDevice(void)
00188 {
00189 }
00190 
00191 void USBBusInterface_EP0setup(uint8_t *buffer)
00192 {
00193     /* Copy setup packet data */
00194     USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
00195 }
00196 
00197 void USBBusInterface_EP0read(void)
00198 {
00199     /* Start an endpoint 0 read */
00200 
00201     /* The USB ISR will call USBDevice_EP0out() when a packet has been read, */
00202     /* the USBDevice layer then calls USBBusInterface_EP0getReadResult() to */
00203     /* read the data. */
00204 
00205     ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
00206         | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
00207 }
00208 
00209 uint32_t USBBusInterface_EP0getReadResult(uint8_t *buffer)
00210 {
00211     /* Complete an endpoint 0 read */
00212     uint32_t bytesRead;
00213 
00214     /* Find how many bytes were read */
00215     bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
00216 
00217     /* Copy data */
00218     USBMemCopy(buffer, ct->out, bytesRead);
00219     return bytesRead;
00220 }
00221 
00222 void USBBusInterface_EP0write(uint8_t *buffer, uint32_t size)
00223 {
00224     /* Start and endpoint 0 write */
00225 
00226     /* The USB ISR will call USBDevice_EP0in() when the data has */
00227     /* been written, the USBDevice layer then calls */
00228     /* USBBusInterface_EP0getWriteResult() to complete the transaction. */
00229 
00230     /* Copy data */
00231     USBMemCopy(ct->in, buffer, size);
00232 
00233     /* Start transfer */
00234     ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
00235         | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
00236 }
00237 
00238 void USBBusInterface_EP0getWriteResult(void)
00239 {
00240     /* Complete an endpoint 0 write */
00241 
00242     /* Nothing required for this target */
00243     return;
00244 }
00245 
00246 void USBBusInterface_EP0stall(void)
00247 {
00248     ep[0].in[0] = CMDSTS_S;
00249     ep[0].out[0] = CMDSTS_S;
00250 }
00251 
00252 void USBBusInterface_setAddress(uint8_t address)
00253 {
00254     devCmdStat &= ~DEV_ADDR_MASK;
00255     devCmdStat |= DEV_ADDR(address);
00256     LPC_USB->DEVCMDSTAT = devCmdStat;
00257 }
00258 
00259 EP_STATUS USBBusInterface_endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
00260 {
00261     uint32_t flags = 0;
00262     uint32_t bf;
00263 
00264     /* Validate parameters */
00265     if (data == NULL)
00266     {
00267         return EP_INVALID;
00268     }
00269 
00270     if (endpoint > LAST_PHYSICAL_ENDPOINT)
00271     {
00272         return EP_INVALID;
00273     }
00274 
00275     if ((endpoint==EP0IN) || (endpoint==EP0OUT))
00276     {
00277         return EP_INVALID;
00278     }
00279 
00280     if (size > endpointState[endpoint].maxPacket)
00281     {
00282         return EP_INVALID;
00283     }
00284 
00285     if (LPC_USB->EPBUFCFG & EP(endpoint))
00286     {
00287         /* Double buffered */ /* TODO: FIX THIS */
00288         if (LPC_USB->EPINUSE & EP(endpoint))
00289         {
00290             bf = 1;
00291         }
00292         else
00293         {
00294             bf = 0;
00295         }
00296     }
00297     else
00298     {
00299         /* Single buffered */
00300         bf = 0;
00301     }
00302 
00303     /* Check if already active */
00304     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A)
00305     {
00306         return EP_INVALID;
00307     }
00308 
00309     /* Check if stalled */
00310     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S)
00311     {
00312         return EP_STALLED;
00313     }
00314 
00315     /* Copy data to USB RAM */
00316     USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
00317 
00318     /* Add options */
00319     if (endpointState[endpoint].options & RATE_FEEDBACK_MODE)
00320     {
00321         flags |= CMDSTS_RF;
00322     }
00323 
00324     if (endpointState[endpoint].options & ISOCHRONOUS)
00325     {
00326         flags |= CMDSTS_T;
00327     }
00328 
00329     /* Add transfer */
00330     ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
00331             endpointState[endpoint].buffer[bf]) \
00332             | CMDSTS_NBYTES(size) | CMDSTS_A | flags;
00333 
00334     return EP_PENDING;
00335 }
00336 
00337 EP_STATUS USBBusInterface_endpointWriteResult(uint8_t endpoint)
00338 {
00339     uint32_t bf;
00340     /* Validate parameters */
00341 
00342     if (endpoint > LAST_PHYSICAL_ENDPOINT)
00343     {
00344         return EP_INVALID;
00345     }
00346 
00347     if (OUT_EP(endpoint))
00348     {
00349         return EP_INVALID;
00350     }
00351 
00352     if (LPC_USB->EPBUFCFG & EP(endpoint))
00353     {
00354         /* Double buffered */    /* TODO: FIX THIS */
00355         if (LPC_USB->EPINUSE & EP(endpoint))
00356         {
00357             bf = 1;
00358         }
00359         else
00360         {
00361             bf = 0;
00362         }
00363     }
00364     else
00365     {
00366         /* Single buffered */
00367         bf = 0;
00368     }
00369 
00370     /* Check if endpoint still active */
00371     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A)
00372     {
00373         return EP_PENDING;
00374     }
00375 
00376     /* Check if stalled */
00377     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S)
00378     {
00379         return EP_STALLED;
00380     }
00381 
00382     return EP_COMPLETED;
00383 }
00384 
00385 void USBBusInterface_stallEndpoint(uint8_t endpoint)
00386 {
00387 
00388     // TODO: should this clear active bit?
00389 
00390     if (IN_EP(endpoint))
00391     {
00392         ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
00393         ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
00394     }
00395     else
00396     {
00397         ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
00398         ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
00399     }
00400 }
00401 
00402 void USBBusInterface_unstallEndpoint(uint8_t endpoint)
00403 {
00404     if (LPC_USB->EPBUFCFG & EP(endpoint))
00405     {
00406         /* Double buffered */
00407         if (IN_EP(endpoint))
00408         {
00409             ep[PHY_TO_LOG(endpoint)].in[0] = 0; /* S = 0 */
00410             ep[PHY_TO_LOG(endpoint)].in[1] = 0; /* S = 0 */
00411 
00412             if (LPC_USB->EPINUSE & EP(endpoint))
00413             {
00414                 ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; /* S =0, TR=1, TV = 0 */
00415             }
00416             else
00417             {
00418                 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; /* S =0, TR=1, TV = 0 */
00419             }
00420         }
00421         else
00422         {
00423             ep[PHY_TO_LOG(endpoint)].out[0] = 0; /* S = 0 */
00424             ep[PHY_TO_LOG(endpoint)].out[1] = 0; /* S = 0 */
00425 
00426             if (LPC_USB->EPINUSE & EP(endpoint))
00427             {
00428                 ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; /* S =0, TR=1, TV = 0 */
00429             }
00430             else
00431             {
00432                 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; /* S =0, TR=1, TV = 0 */
00433             }
00434         }
00435     }
00436     else
00437     {
00438         /* Single buffered */
00439         if (IN_EP(endpoint))
00440         {
00441             ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; /* S=0, TR=1, TV = 0 */
00442         }
00443         else
00444         {
00445             ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; /* S=0, TR=1, TV = 0 */
00446         }
00447     }
00448 }
00449 
00450 bool USBBusInterface_getEndpointStallState(unsigned char endpoint)
00451 {
00452     if (IN_EP(endpoint))
00453     {
00454         if (LPC_USB->EPINUSE & EP(endpoint))
00455         {
00456             if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S)
00457             {
00458                 return true;
00459             }
00460         }
00461         else
00462         {
00463             if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S)
00464             {
00465                 return true;
00466             }
00467         }
00468     }
00469     else
00470     {
00471         if (LPC_USB->EPINUSE & EP(endpoint))
00472         {
00473             if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S)
00474             {
00475                 return true;
00476             }
00477         }
00478         else
00479         {
00480             if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S)
00481             {
00482                 return true;
00483             }
00484         }
00485     }
00486 
00487     return false;
00488 }
00489 
00490 bool USBBusInterface_realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options)
00491 {
00492     uint32_t tmpEpRamPtr;
00493 
00494 /*
00495     *
00496     *   Support for double buffered endpoints needs to be fixed/finished in this
00497     *   software - force single buffered for now.
00498     *
00499 */
00500     options |= SINGLE_BUFFERED; /* TODO - FIX THIS */
00501 
00502     if (endpoint > LAST_PHYSICAL_ENDPOINT)
00503     {
00504         return false;
00505     }
00506 
00507     /* Not applicable to the control endpoints */
00508     if ((endpoint==EP0IN) || (endpoint==EP0OUT))
00509     {
00510         return false;
00511     }
00512 
00513     /* Allocate buffers in USB RAM */
00514     tmpEpRamPtr = epRamPtr;
00515 
00516     /* Must be 64 byte aligned */
00517     tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
00518 
00519     if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE))
00520     {
00521         /* Out of memory */
00522         return false;
00523     }
00524 
00525     /* Allocate first buffer */
00526     endpointState[endpoint].buffer[0] = tmpEpRamPtr;
00527     tmpEpRamPtr += maxPacket;
00528 
00529     if (!(options & SINGLE_BUFFERED))
00530     {
00531         /* Must be 64 byte aligned */
00532         tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
00533     
00534         if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE))
00535         {
00536             /* Out of memory */
00537             return false;
00538         }
00539 
00540         /* Allocate second buffer */
00541         endpointState[endpoint].buffer[1] = tmpEpRamPtr;
00542         tmpEpRamPtr += maxPacket;
00543     }
00544 
00545     /* Commit to this USB RAM allocation */
00546     epRamPtr = tmpEpRamPtr;
00547 
00548     /* Remaining endpoint state values */
00549     endpointState[endpoint].maxPacket = maxPacket;
00550     endpointState[endpoint].options = options;
00551 
00552     /* Enable double buffering if required */
00553     if (options & SINGLE_BUFFERED)
00554     {
00555         LPC_USB->EPBUFCFG &= ~EP(endpoint);
00556     }
00557     else
00558     {
00559         /* Double buffered */
00560         LPC_USB->EPBUFCFG |= EP(endpoint);
00561     }
00562 
00563     /* Enable endpoint */
00564     USBBusInterface_unstallEndpoint(endpoint);
00565     return true;
00566 }
00567 
00568 void USBBusInterface_remoteWakeup(void)
00569 {
00570     /* Clearing DSUS bit initiates a remote wakeup if the */
00571     /* device is currently enabled and suspended - otherwise */
00572     /* it has no effect. */
00573     LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
00574 }
00575 
00576 /*
00577  *  Configuration helper functions
00578  */
00579 
00580 static void disableEndpoints(void)
00581 {
00582     uint32_t logEp;
00583 
00584     /* Ref. Table 158 "When a bus reset is received, software */
00585     /* must set the disable bit of all endpoints to 1".*/
00586 
00587     for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++)
00588     {
00589         ep[logEp].out[0] = CMDSTS_D;
00590         ep[logEp].out[1] = CMDSTS_D;
00591         ep[logEp].in[0] =  CMDSTS_D;
00592         ep[logEp].in[1] =  CMDSTS_D;
00593     }
00594 
00595     /* Start of USB RAM for endpoints > 0 */
00596     epRamPtr = usbRamPtr;
00597 }
00598 
00599 /*
00600  *  USB interrupt handler
00601  */
00602 
00603 extern "C"
00604 {
00605 void USB_IRQHandler(void)
00606 {
00607     /* Start of frame */
00608     if (LPC_USB->INTSTAT & FRAME_INT)
00609     {
00610         /* Clear SOF interrupt */
00611         LPC_USB->INTSTAT = FRAME_INT;
00612 
00613         /* SOF event, read frame number */
00614         USBDevice_SOF(FRAME_NR(LPC_USB->INFO));
00615     }
00616 
00617     /* Device state */
00618     if (LPC_USB->INTSTAT & DEV_INT)
00619     {
00620         LPC_USB->INTSTAT = DEV_INT;
00621 
00622         if (LPC_USB->DEVCMDSTAT & DCON_C)
00623         {
00624             /* Connect status changed */
00625             LPC_USB->DEVCMDSTAT = devCmdStat | DCON_C;
00626 
00627             USBDevice_connectStateChanged((LPC_USB->DEVCMDSTAT & DCON) != 0);
00628         }
00629 
00630         if (LPC_USB->DEVCMDSTAT & DSUS_C)
00631         {
00632             /* Suspend status changed */
00633             LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
00634 
00635             USBDevice_suspendStateChanged((LPC_USB->DEVCMDSTAT & DSUS) != 0);
00636         }
00637 
00638         if (LPC_USB->DEVCMDSTAT & DRES_C)
00639         {
00640             /* Bus reset */
00641             LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
00642 
00643             /* Disable endpoints > 0 */
00644             disableEndpoints();
00645 
00646             /* Bus reset event */
00647             USBDevice_busReset();
00648         }
00649     }
00650 
00651     /* Endpoint 0 */
00652     if (LPC_USB->INTSTAT & EP(EP0OUT))
00653     {
00654         /* Clear EP0OUT/SETUP interrupt */
00655         LPC_USB->INTSTAT = EP(EP0OUT);
00656 
00657         /* Check if SETUP */
00658         if (LPC_USB->DEVCMDSTAT & SETUP)
00659         {
00660             /* Clear Active and Stall bits for EP0 */
00661             /* Documentation does not make it clear if we must use the */
00662             /* EPSKIP register to achieve this, Fig. 16 and NXP reference */
00663             /* code suggests we can just clear the Active bits - check with */
00664             /* NXP to be sure. */
00665             ep[0].in[0] = 0;
00666             ep[0].out[0] = 0;
00667 
00668             /* Clear EP0IN interrupt */
00669             LPC_USB->INTSTAT = EP(EP0IN);
00670 
00671             /* Clear SETUP (and INTONNAK_CI/O) in device status register */
00672             LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
00673 
00674             /* EP0 SETUP event (SETUP data received) */
00675             USBDevice_EP0setup();
00676         }
00677         else
00678         {
00679             /* EP0OUT ACK event (OUT data received) */
00680             USBDevice_EP0out();
00681         }
00682     }
00683 
00684     if (LPC_USB->INTSTAT & EP(EP0IN))
00685     {
00686         /* Clear EP0IN interrupt */
00687         LPC_USB->INTSTAT = EP(EP0IN);
00688 
00689         /* EP0IN ACK event (IN data sent) */
00690         USBDevice_EP0in();
00691     }
00692 }
00693 }
00694 
00695 #endif