Robert Abad / USBDevice

Fork of USBDevice by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_LPC11U.cpp Source File

USBHAL_LPC11U.cpp

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