Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

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