Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBBusInterface_LPC17_LPC23.c Source File

USBBusInterface_LPC17_LPC23.c

00001 /* USBBusInterface_LPC17_LPC23.c */
00002 /* USB Bus Interface for NXP LPC1768 and LPC2368 */
00003 /* Copyright (c) 2011 ARM Limited. All rights reserved. */
00004 
00005 #ifdef TARGET_LPC1768
00006 
00007 #include "USBBusInterface.h"
00008 #include "USBEvents.h"
00009 
00010 
00011 /* Get endpoint direction */
00012 #define IN_EP(endpoint)     ((endpoint) & 1U ? true : false)
00013 #define OUT_EP(endpoint)    ((endpoint) & 1U ? false : true)
00014 
00015 /* Convert physical endpoint number to register bit */
00016 #define EP(endpoint) (1UL<<endpoint)
00017 
00018 /* Power Control for Peripherals register */
00019 #define PCUSB      (1UL<<31)
00020 
00021 /* USB Clock Control register */
00022 #define DEV_CLK_EN (1UL<<1)
00023 #define AHB_CLK_EN (1UL<<4)
00024 
00025 /* USB Clock Status register */
00026 #define DEV_CLK_ON (1UL<<1)
00027 #define AHB_CLK_ON (1UL<<4)
00028 
00029 /* USB Device Interupt registers */
00030 #define FRAME      (1UL<<0)
00031 #define EP_FAST    (1UL<<1)
00032 #define EP_SLOW    (1UL<<2)
00033 #define DEV_STAT   (1UL<<3)
00034 #define CCEMPTY    (1UL<<4)
00035 #define CDFULL     (1UL<<5)
00036 #define RxENDPKT   (1UL<<6)
00037 #define TxENDPKT   (1UL<<7)
00038 #define EP_RLZED   (1UL<<8)
00039 #define ERR_INT    (1UL<<9)
00040 
00041 /* USB Control register */
00042 #define RD_EN (1<<0)
00043 #define WR_EN (1<<1)
00044 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
00045 
00046 /* USB Receive Packet Length register */
00047 #define DV      (1UL<<10)
00048 #define PKT_RDY (1UL<<11)
00049 #define PKT_LNGTH_MASK (0x3ff)
00050 
00051 /* Serial Interface Engine (SIE) */
00052 #define SIE_WRITE   (0x01)
00053 #define SIE_READ    (0x02)
00054 #define SIE_COMMAND (0x05)
00055 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
00056 
00057 /* SIE Command codes */
00058 #define SIE_CMD_SET_ADDRESS        (0xD0)
00059 #define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
00060 #define SIE_CMD_SET_MODE           (0xF3)
00061 #define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
00062 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
00063 #define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
00064 #define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
00065 #define SIE_CMD_GET_ERROR_CODE     (0xFF)
00066 #define SIE_CMD_READ_ERROR_STATUS  (0xFB)
00067 
00068 #define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
00069 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
00070 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
00071 
00072 #define SIE_CMD_CLEAR_BUFFER    (0xF2)
00073 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
00074 
00075 /* SIE Device Status register */
00076 #define SIE_DS_CON    (1<<0)
00077 #define SIE_DS_CON_CH (1<<1)
00078 #define SIE_DS_SUS    (1<<2)
00079 #define SIE_DS_SUS_CH (1<<3)
00080 #define SIE_DS_RST    (1<<4)
00081 
00082 /* SIE Device Set Address register */
00083 #define SIE_DSA_DEV_EN  (1<<7)
00084 
00085 /* SIE Configue Device register */
00086 #define SIE_CONF_DEVICE (1<<0)
00087 
00088 /* Select Endpoint register */
00089 #define SIE_SE_FE       (1<<0)
00090 #define SIE_SE_ST       (1<<1)
00091 #define SIE_SE_STP      (1<<2)
00092 #define SIE_SE_PO       (1<<3)
00093 #define SIE_SE_EPN      (1<<4)
00094 #define SIE_SE_B_1_FULL (1<<5)
00095 #define SIE_SE_B_2_FULL (1<<6)
00096 
00097 /* Set Endpoint Status command */
00098 #define SIE_SES_ST      (1<<0)
00099 #define SIE_SES_DA      (1<<5)
00100 #define SIE_SES_RF_MO   (1<<6)
00101 #define SIE_SES_CND_ST  (1<<7)
00102 
00103 static uint32_t endpointStallState;
00104 
00105 static int epComplete = 0;
00106 /*
00107  *  Serial Interface Engine commands
00108  */
00109 
00110 static void SIECommand(uint32_t command)
00111 {
00112     /* The command phase of a SIE transaction */
00113     LPC_USB->USBDevIntClr = CCEMPTY;
00114     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
00115     while (!(LPC_USB->USBDevIntSt & CCEMPTY)); 
00116 }
00117 
00118 static void SIEWriteData(uint8_t data)
00119 {
00120     /* The data write phase of a SIE transaction */
00121     LPC_USB->USBDevIntClr = CCEMPTY;
00122     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
00123     while (!(LPC_USB->USBDevIntSt & CCEMPTY)); 
00124 }
00125 
00126 static uint8_t SIEReadData(uint32_t command)
00127 {
00128     /* The data read phase of a SIE transaction */
00129     LPC_USB->USBDevIntClr = CDFULL;
00130     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
00131     while (!(LPC_USB->USBDevIntSt & CDFULL));
00132     return (uint8_t)LPC_USB->USBCmdData;
00133 }
00134 
00135 static void SIEsetDeviceStatus(uint8_t status)
00136 {
00137     /* Write SIE device status register */
00138     SIECommand(SIE_CMD_SET_DEVICE_STATUS);
00139     SIEWriteData(status);
00140 }
00141 
00142 static uint8_t SIEgetDeviceStatus(void)
00143 {
00144     /* Read SIE device status register */
00145     SIECommand(SIE_CMD_GET_DEVICE_STATUS);
00146     return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
00147 }
00148 
00149 void SIEsetAddress(uint8_t address)
00150 {
00151     /* Write SIE device address register */
00152     SIECommand(SIE_CMD_SET_ADDRESS);
00153     SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
00154 }
00155 
00156 static uint8_t SIEselectEndpoint(uint8_t endpoint)
00157 {
00158     /* SIE select endpoint command */
00159     SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
00160     return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
00161 }
00162 
00163 static uint8_t SIEclearBuffer(void)
00164 {
00165     /* SIE clear buffer command */
00166     SIECommand(SIE_CMD_CLEAR_BUFFER);
00167     return SIEReadData(SIE_CMD_CLEAR_BUFFER);
00168 }
00169 
00170 static void SIEvalidateBuffer(void)
00171 {
00172     /* SIE validate buffer command */
00173     SIECommand(SIE_CMD_VALIDATE_BUFFER);
00174 }
00175 
00176 static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status)
00177 {
00178     /* SIE set endpoint status command */
00179     SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
00180     SIEWriteData(status);
00181 }
00182 
00183 static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
00184 static uint16_t SIEgetFrameNumber(void)
00185 {
00186     /* Read current frame number */
00187     uint16_t lowByte;
00188     uint16_t highByte;
00189 
00190     SIECommand(SIE_CMD_READ_FRAME_NUMBER);
00191     lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
00192     highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
00193 
00194     return (highByte << 8) | lowByte;
00195 }
00196 
00197 static void SIEconfigureDevice(void)
00198 {
00199     /* SIE Configure device command */
00200     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
00201     SIEWriteData(SIE_CONF_DEVICE);
00202 }
00203 
00204 static void SIEunconfigureDevice(void)
00205 {
00206     /* SIE Configure device command */
00207     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
00208     SIEWriteData(0);
00209 }
00210 
00211 static void SIEconnect(void)
00212 {
00213     /* Connect USB device */
00214     uint8_t status;
00215 
00216     status = SIEgetDeviceStatus();
00217     SIEsetDeviceStatus(status | SIE_DS_CON);
00218 }
00219 
00220 
00221 static void SIEdisconnect(void)
00222 {
00223     /* Disconnect USB device */
00224     uint8_t status;
00225 
00226     status = SIEgetDeviceStatus();
00227     SIEsetDeviceStatus(status & ~SIE_DS_CON);
00228 }
00229 
00230 /*
00231  *  Endpoint commands
00232  */
00233 
00234 static uint8_t selectEndpointClearInterrupt(uint8_t endpoint)
00235 {
00236     /* Implemented using using EP_INT_CLR. */
00237     LPC_USB->USBEpIntClr = EP(endpoint);
00238     while (!(LPC_USB->USBDevIntSt & CDFULL));
00239     return (uint8_t)LPC_USB->USBCmdData;
00240 }
00241 
00242 static void stallEndpoint(uint8_t endpoint)
00243 {
00244     /* Stall an endpoint */
00245     if ( (endpoint==EP0IN) || (endpoint==EP0OUT) )
00246     {
00247         /* Conditionally stall both control endpoints */
00248         SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
00249     }
00250     else
00251     {
00252         SIEsetEndpointStatus(endpoint, SIE_SES_ST);
00253 
00254         /* Update stall state */
00255         endpointStallState |= EP(endpoint);
00256     }
00257 }
00258 
00259 static void unstallEndpoint(uint8_t endpoint)
00260 {
00261     /* Unstall an endpoint. The endpoint will also be reinitialised */
00262     SIEsetEndpointStatus(endpoint, 0);
00263 
00264     /* Update stall state */
00265     endpointStallState &= ~EP(endpoint);
00266 }
00267 
00268 static bool getEndpointStallState(uint8_t endpoint)
00269 { 
00270     /* Returns true if endpoint stalled */
00271     return endpointStallState & EP(endpoint);
00272 }
00273 
00274 static void realiseEndpoint(uint8_t endpoint, uint32_t maxPacket)
00275 {
00276     /* Realise an endpoint */
00277     LPC_USB->USBDevIntClr = EP_RLZED;
00278     LPC_USB->USBReEp |= EP(endpoint);
00279     LPC_USB->USBEpInd = endpoint;
00280     LPC_USB->USBMaxPSize = maxPacket;
00281 
00282     while (!(LPC_USB->USBDevIntSt & EP_RLZED));
00283     LPC_USB->USBDevIntClr = EP_RLZED;
00284 
00285     /* Clear stall state */
00286     endpointStallState &= ~EP(endpoint);
00287 }
00288 
00289 static void enableEndpointEvent(uint8_t endpoint)
00290 {
00291     /* Enable an endpoint interrupt */
00292     LPC_USB->USBEpIntEn |= EP(endpoint);
00293 }
00294 
00295 static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
00296 static void disableEndpointEvent(uint8_t endpoint)
00297 {
00298     /* Disable an endpoint interrupt */
00299     LPC_USB->USBEpIntEn &= ~EP(endpoint);
00300 }
00301 
00302 static volatile uint32_t __attribute__((used)) dummyRead;
00303 
00304 static uint32_t endpointRead(uint8_t endpoint, uint8_t *buffer)
00305 {
00306     /* Read from an OUT endpoint */
00307     uint32_t size;
00308     uint32_t i;
00309     uint32_t data;
00310     uint8_t offset;
00311 
00312     LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
00313     while (!(LPC_USB->USBRxPLen & PKT_RDY));
00314 
00315     size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
00316 
00317     offset = 0;
00318 
00319     if (size > 0)
00320     {
00321         for (i=0; i<size; i++)
00322         {
00323             if (offset==0)
00324             {
00325                 /* Fetch up to four bytes of data as a word */
00326                 data = LPC_USB->USBRxData;
00327             }
00328 
00329             /* extract a byte */
00330             *buffer++ = data>>offset;
00331 
00332             /* move on to the next byte */
00333             offset = (offset + 8) % 32;
00334         }
00335     }
00336     else
00337     {
00338         dummyRead = LPC_USB->USBRxData;
00339     }
00340 
00341     SIEselectEndpoint(endpoint);
00342     SIEclearBuffer();
00343     return size;
00344 }
00345 
00346 static void endpointWrite(uint8_t endpoint, uint8_t *buffer, uint32_t size)
00347 {
00348     /* Write to an IN endpoint */
00349     uint32_t temp, data;
00350     uint8_t offset;
00351 
00352     LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
00353 
00354     LPC_USB->USBTxPLen = size;
00355     offset = 0;
00356     data = 0;
00357 
00358     if (size>0)
00359     {
00360         do {
00361             /* Fetch next data byte into a word-sized temporary variable */
00362             temp = *buffer++;
00363 
00364             /* Add to current data word */
00365             temp = temp << offset;
00366             data = data | temp;
00367 
00368             /* move on to the next byte */
00369             offset = (offset + 8) % 32;
00370             size--;
00371 
00372             if ((offset==0) || (size==0))
00373             {
00374                 /* Write the word to the endpoint */
00375                 LPC_USB->USBTxData = data;
00376                 data = 0;
00377             }
00378         } while (size>0);
00379     }
00380     else
00381     {
00382         LPC_USB->USBTxData = 0;
00383     }
00384 
00385     /* Clear WR_EN to cover zero length packet case */
00386     LPC_USB->USBCtrl=0;
00387 
00388     SIEselectEndpoint(endpoint);
00389     SIEvalidateBuffer();
00390 }
00391 
00392 /*
00393  *  USBBusInterface API
00394  */
00395 
00396 bool USBBusInterface_init(void)
00397 {
00398     /* Disable IRQ */
00399     NVIC_DisableIRQ(USB_IRQn);
00400 
00401     /* Enable power to USB device controller */
00402     LPC_SC->PCONP |= PCUSB;
00403 
00404     /* Enable USB clocks */
00405     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
00406     while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
00407 
00408     /* Configure pins P0.29 and P0.30 to be USB D+ and USB D- */
00409     LPC_PINCON->PINSEL1 &= 0xc3ffffff;
00410     LPC_PINCON->PINSEL1 |= 0x14000000;
00411 
00412     /* Disconnect USB device */
00413     SIEdisconnect();
00414 
00415     /* Configure pin P2.9 to be Connect */
00416     LPC_PINCON->PINSEL4 &= 0xfffcffff;
00417     LPC_PINCON->PINSEL4 |= 0x00040000;
00418     
00419     /* Connect must be low for at least 2.5uS */
00420     wait(0.3);
00421 
00422     /* Set the maximum packet size for the control endpoints */
00423     realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0);
00424     realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0);
00425 
00426     /* Attach IRQ */
00427     NVIC_EnableIRQ(USB_IRQn); 
00428 
00429     /* Enable interrupts for device events and EP0 */
00430     LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT;
00431     enableEndpointEvent(EP0IN);
00432     enableEndpointEvent(EP0OUT);
00433     return true;
00434 }
00435 
00436 void USBBusInterface_uninit(void)
00437 {
00438     /* Ensure device disconnected */
00439     SIEdisconnect();
00440 
00441     /* Disable USB interrupts */
00442     NVIC_DisableIRQ(USB_IRQn);
00443 }
00444 
00445 void USBBusInterface_connect(void)
00446 {
00447     /* Connect USB device */
00448     SIEconnect();
00449 }
00450 
00451 void USBBusInterface_disconnect(void)
00452 {
00453     /* Disconnect USB device */
00454     SIEdisconnect();
00455 }
00456 
00457 void USBBusInterface_configureDevice(void)
00458 {
00459     SIEconfigureDevice();
00460 }
00461 
00462 void USBBusInterface_unconfigureDevice(void)
00463 {
00464     SIEunconfigureDevice();
00465 }
00466 
00467 void USBBusInterface_setAddress(uint8_t address)
00468 {
00469     SIEsetAddress(address);
00470 }
00471 
00472 void USBBusInterface_EP0setup(uint8_t *buffer)
00473 {
00474     endpointRead(EP0OUT, buffer);
00475 }
00476 
00477 void USBBusInterface_EP0read(void)
00478 {
00479     /* Not required */
00480 }
00481 
00482 uint32_t USBBusInterface_EP0getReadResult(uint8_t *buffer)
00483 {
00484     return endpointRead(EP0OUT, buffer);
00485 }
00486 
00487 void USBBusInterface_EP0write(uint8_t *buffer, uint32_t size)
00488 {
00489     endpointWrite(EP0IN, buffer, size);
00490 }
00491 
00492 void USBBusInterface_EP0getWriteResult(void)
00493 {
00494     /* Not required */
00495 }
00496 
00497 void USBBusInterface_EP0stall(void)
00498 {
00499     /* This will stall both control endpoints */
00500     stallEndpoint(EP0OUT);
00501 }
00502 
00503 EP_STATUS USBBusInterface_endpointRead(uint8_t endpoint, uint8_t *data, uint32_t maximumSize)
00504 {
00505     if (getEndpointStallState(endpoint))
00506     {
00507         return EP_STALLED;
00508     }
00509 
00510     return EP_PENDING;
00511 }
00512 
00513 EP_STATUS USBBusInterface_endpointReadResult(uint8_t endpoint, uint32_t *bytesRead)
00514 {
00515     return EP_PENDING;
00516 }
00517 
00518 EP_STATUS USBBusInterface_endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
00519 {
00520     if (getEndpointStallState(endpoint))
00521     {
00522         return EP_STALLED;
00523     }
00524 
00525     epComplete &= EP(endpoint);
00526 
00527     endpointWrite(endpoint, data, size);
00528     return EP_PENDING;
00529 }
00530 
00531 EP_STATUS USBBusInterface_endpointWriteResult(uint8_t endpoint)
00532 {
00533     if (epComplete & EP(endpoint))
00534     {
00535         epComplete &= ~EP(endpoint);
00536         return EP_COMPLETED;
00537     }
00538 
00539     return EP_PENDING;
00540 }
00541 
00542 bool USBBusInterface_realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags)
00543 {
00544     realiseEndpoint(endpoint, maxPacket);
00545     enableEndpointEvent(endpoint);
00546     return true;
00547 }
00548 
00549 void USBBusInterface_stallEndpoint(uint8_t endpoint)
00550 {
00551     stallEndpoint(endpoint);
00552 }
00553 
00554 void USBBusInterface_unstallEndpoint(uint8_t endpoint)
00555 {
00556     unstallEndpoint(endpoint);
00557 }
00558 
00559 bool USBBusInterface_getEndpointStallState(uint8_t endpoint)
00560 {
00561     return getEndpointStallState(endpoint);
00562 }
00563 
00564 void USBBusInterface_remoteWakeup(void)
00565 {
00566     /* Remote wakeup */
00567     uint8_t status;
00568 
00569     /* Enable USB clocks */
00570     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
00571     while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
00572 
00573     status = SIEgetDeviceStatus();
00574     SIEsetDeviceStatus(status & ~SIE_DS_SUS);
00575 }
00576 
00577 /*
00578  *  USB interrupt handler
00579  */
00580 
00581 extern "C"
00582 {
00583 void USB_IRQHandler(void)
00584 { 
00585     uint8_t devStat;
00586     
00587     if (LPC_USB->USBDevIntSt & FRAME)
00588     {
00589         /* Start of frame event */
00590         USBDevice_SOF(SIEgetFrameNumber());
00591         /* Clear interrupt status flag */
00592         LPC_USB->USBDevIntClr = FRAME;
00593     }
00594 
00595     if (LPC_USB->USBDevIntSt & DEV_STAT)
00596     {
00597         /* Device Status interrupt */
00598         /* Must clear the interrupt status flag before reading the device status from the SIE */
00599         LPC_USB->USBDevIntClr = DEV_STAT;
00600             
00601         /* Read device status from SIE */
00602         devStat = SIEgetDeviceStatus();
00603         
00604         if (devStat & SIE_DS_RST)
00605         {
00606             /* Bus reset */
00607             USBDevice_busReset();
00608         }
00609     }
00610 
00611     if (LPC_USB->USBDevIntSt & EP_SLOW)
00612     {
00613         /* (Slow) Endpoint Interrupt */
00614         
00615         /* Process each endpoint interrupt */
00616         if (LPC_USB->USBEpIntSt & EP(EP0OUT))
00617         {
00618             if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP)
00619             {
00620                 /* this is a setup packet */
00621                 USBDevice_EP0setup();
00622             }
00623             else
00624             {
00625                 USBDevice_EP0out();
00626             }
00627         }
00628 
00629         if (LPC_USB->USBEpIntSt & EP(EP0IN))
00630         {
00631             selectEndpointClearInterrupt(EP0IN);
00632             USBDevice_EP0in();
00633         }
00634 
00635 /* TODO: This should cover all endpoints, not just EP1,2,3:*/
00636         if (LPC_USB->USBEpIntSt & EP(EP1IN))
00637         {
00638             selectEndpointClearInterrupt(EP1IN);
00639             epComplete |= EP(EP1IN);
00640         }
00641 
00642         if (LPC_USB->USBEpIntSt & EP(EP1OUT))
00643         {
00644             selectEndpointClearInterrupt(EP1OUT);
00645             epComplete |= EP(EP1OUT);
00646         }
00647 
00648         if (LPC_USB->USBEpIntSt & EP(EP2IN))
00649         {
00650             selectEndpointClearInterrupt(EP2IN);
00651             epComplete |= EP(EP2IN);
00652         }
00653 
00654         if (LPC_USB->USBEpIntSt & EP(EP2OUT))
00655         {
00656             selectEndpointClearInterrupt(EP2OUT);
00657             epComplete |= EP(EP2OUT);
00658         }
00659 
00660         if (LPC_USB->USBEpIntSt & EP(EP3IN))
00661         {
00662             selectEndpointClearInterrupt(EP3IN);
00663             epComplete |= EP(EP3IN);
00664         }
00665 
00666         if (LPC_USB->USBEpIntSt & EP(EP3OUT))
00667         {
00668             selectEndpointClearInterrupt(EP3OUT);
00669             epComplete |= EP(EP3OUT);
00670         }
00671 
00672         /* Clear interrupt status flag */
00673         /* EP_SLOW and EP_FAST interrupt bits should be cleared after the corresponding endpoint interrupts are cleared. */
00674         LPC_USB->USBDevIntClr = EP_SLOW;
00675     }
00676 }
00677 }
00678 
00679 #endif