Fork of official USB device library just changed PID (Product ID) in constructor in USBMSD.h to be different for USBMSD_AT45_HelloWorld program

Dependents:   USBMSD_AT45_HelloWorld

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 #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 }
00180 
00181 USBHAL::~USBHAL(void) {
00182     // Ensure device disconnected (DCON not set)
00183     LPC_USB->DEVCMDSTAT = 0;
00184 
00185     // Disable USB interrupts
00186     NVIC_DisableIRQ(USB_IRQn);
00187 }
00188 
00189 void USBHAL::connect(void) {
00190     NVIC_EnableIRQ(USB_IRQn);
00191     devCmdStat |= DCON;
00192     LPC_USB->DEVCMDSTAT = devCmdStat;
00193 }
00194 
00195 void USBHAL::disconnect(void) {
00196     NVIC_DisableIRQ(USB_IRQn);
00197     devCmdStat &= ~DCON;
00198     LPC_USB->DEVCMDSTAT = devCmdStat;
00199 }
00200 
00201 void USBHAL::configureDevice(void) {
00202 }
00203 
00204 void USBHAL::unconfigureDevice(void) {
00205 }
00206 
00207 void USBHAL::EP0setup(uint8_t *buffer) {
00208     // Copy setup packet data
00209     USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
00210 }
00211 
00212 void USBHAL::EP0read(void) {
00213     // Start an endpoint 0 read
00214 
00215     // The USB ISR will call USBDevice_EP0out() when a packet has been read,
00216     // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
00217     // read the data.
00218 
00219     ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
00220                    | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
00221 }
00222 
00223 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
00224     // Complete an endpoint 0 read
00225     uint32_t bytesRead;
00226 
00227     // Find how many bytes were read
00228     bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
00229 
00230     // Copy data
00231     USBMemCopy(buffer, ct->out, bytesRead);
00232     return bytesRead;
00233 }
00234 
00235 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
00236     // Start and endpoint 0 write
00237 
00238     // The USB ISR will call USBDevice_EP0in() when the data has
00239     // been written, the USBDevice layer then calls
00240     // USBBusInterface_EP0getWriteResult() to complete the transaction.
00241 
00242     // Copy data
00243     USBMemCopy(ct->in, buffer, size);
00244 
00245     // Start transfer
00246     ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
00247                   | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
00248 }
00249 
00250 
00251 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
00252     uint8_t bf = 0;
00253     uint32_t flags = 0;
00254 
00255     //check which buffer must be filled
00256     if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00257         // Double buffered
00258         if (LPC_USB->EPINUSE & EP(endpoint)) {
00259             bf = 1;
00260         } else {
00261             bf = 0;
00262         }
00263     }
00264     
00265     // if isochronous endpoint, T = 1
00266     if(endpointState[endpoint].options & ISOCHRONOUS)
00267     {
00268         flags |= CMDSTS_T;
00269     }
00270         
00271     //Active the endpoint for reading
00272     ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
00273                                        | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags;
00274     return EP_PENDING;
00275 }
00276 
00277 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) {
00278 
00279     uint8_t bf = 0;
00280 
00281     if (!(epComplete & EP(endpoint)))
00282         return EP_PENDING;
00283     else {
00284         epComplete &= ~EP(endpoint);
00285 
00286         //check which buffer has been filled
00287         if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00288             // Double buffered (here we read the previous buffer which was used)
00289             if (LPC_USB->EPINUSE & EP(endpoint)) {
00290                 bf = 0;
00291             } else {
00292                 bf = 1;
00293             }
00294         }
00295 
00296         // Find how many bytes were read
00297         *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf]));
00298 
00299         // Copy data
00300         USBMemCopy(data, ct->out, *bytesRead);
00301         return EP_COMPLETED;
00302     }
00303 }
00304 
00305 void USBHAL::EP0getWriteResult(void) {
00306     // Complete an endpoint 0 write
00307 
00308     // Nothing required for this target
00309     return;
00310 }
00311 
00312 void USBHAL::EP0stall(void) {
00313     ep[0].in[0] = CMDSTS_S;
00314     ep[0].out[0] = CMDSTS_S;
00315 }
00316 
00317 void USBHAL::setAddress(uint8_t address) {
00318     devCmdStat &= ~DEV_ADDR_MASK;
00319     devCmdStat |= DEV_ADDR(address);
00320     LPC_USB->DEVCMDSTAT = devCmdStat;
00321 }
00322 
00323 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
00324     uint32_t flags = 0;
00325     uint32_t bf;
00326 
00327     // Validate parameters
00328     if (data == NULL) {
00329         return EP_INVALID;
00330     }
00331 
00332     if (endpoint > LAST_PHYSICAL_ENDPOINT) {
00333         return EP_INVALID;
00334     }
00335 
00336     if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
00337         return EP_INVALID;
00338     }
00339 
00340     if (size > endpointState[endpoint].maxPacket) {
00341         return EP_INVALID;
00342     }
00343 
00344     if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00345         // Double buffered
00346         if (LPC_USB->EPINUSE & EP(endpoint)) {
00347             bf = 1;
00348         } else {
00349             bf = 0;
00350         }
00351     } else {
00352         // Single buffered
00353         bf = 0;
00354     }
00355 
00356     // Check if already active
00357     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
00358         return EP_INVALID;
00359     }
00360 
00361     // Check if stalled
00362     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
00363         return EP_STALLED;
00364     }
00365 
00366     // Copy data to USB RAM
00367     USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
00368 
00369     // Add options
00370     if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) {
00371         flags |= CMDSTS_RF;
00372     }
00373 
00374     if (endpointState[endpoint].options & ISOCHRONOUS) {
00375         flags |= CMDSTS_T;
00376     }
00377 
00378     // Add transfer
00379     ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
00380                                       endpointState[endpoint].buffer[bf]) \
00381                                       | CMDSTS_NBYTES(size) | CMDSTS_A | flags;
00382 
00383     return EP_PENDING;
00384 }
00385 
00386 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
00387     uint32_t bf;
00388     // Validate parameters
00389 
00390     if (endpoint > LAST_PHYSICAL_ENDPOINT) {
00391         return EP_INVALID;
00392     }
00393 
00394     if (OUT_EP(endpoint)) {
00395         return EP_INVALID;
00396     }
00397 
00398     if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00399         // Double buffered     // TODO: FIX THIS
00400         if (LPC_USB->EPINUSE & EP(endpoint)) {
00401             bf = 1;
00402         } else {
00403             bf = 0;
00404         }
00405     } else {
00406         // Single buffered
00407         bf = 0;
00408     }
00409 
00410     // Check if endpoint still active
00411     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
00412         return EP_PENDING;
00413     }
00414 
00415     // Check if stalled
00416     if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
00417         return EP_STALLED;
00418     }
00419 
00420     return EP_COMPLETED;
00421 }
00422 
00423 void USBHAL::stallEndpoint(uint8_t endpoint) {
00424 
00425     // TODO: should this clear active bit?
00426 
00427     if (IN_EP(endpoint)) {
00428         ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
00429         ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
00430     } else {
00431         ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
00432         ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
00433     }
00434 }
00435 
00436 void USBHAL::unstallEndpoint(uint8_t endpoint) {
00437     if (LPC_USB->EPBUFCFG & EP(endpoint)) {
00438         // Double buffered
00439         if (IN_EP(endpoint)) {
00440             ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0
00441             ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0
00442 
00443             if (LPC_USB->EPINUSE & EP(endpoint)) {
00444                 ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
00445             } else {
00446                 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
00447             }
00448         } else {
00449             ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0
00450             ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0
00451 
00452             if (LPC_USB->EPINUSE & EP(endpoint)) {
00453                 ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
00454             } else {
00455                 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
00456             }
00457         }
00458     } else {
00459         // Single buffered
00460         if (IN_EP(endpoint)) {
00461             ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
00462         } else {
00463             ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
00464         }
00465     }
00466 }
00467 
00468 bool USBHAL::getEndpointStallState(unsigned char endpoint) {
00469     if (IN_EP(endpoint)) {
00470         if (LPC_USB->EPINUSE & EP(endpoint)) {
00471             if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) {
00472                 return true;
00473             }
00474         } else {
00475             if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) {
00476                 return true;
00477             }
00478         }
00479     } else {
00480         if (LPC_USB->EPINUSE & EP(endpoint)) {
00481             if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) {
00482                 return true;
00483             }
00484         } else {
00485             if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) {
00486                 return true;
00487             }
00488         }
00489     }
00490 
00491     return false;
00492 }
00493 
00494 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) {
00495     uint32_t tmpEpRamPtr;
00496 
00497     if (endpoint > LAST_PHYSICAL_ENDPOINT) {
00498         return false;
00499     }
00500 
00501     // Not applicable to the control endpoints
00502     if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
00503         return false;
00504     }
00505 
00506     // Allocate buffers in USB RAM
00507     tmpEpRamPtr = epRamPtr;
00508 
00509     // Must be 64 byte aligned
00510     tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
00511 
00512     if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
00513         // Out of memory
00514         return false;
00515     }
00516 
00517     // Allocate first buffer
00518     endpointState[endpoint].buffer[0] = tmpEpRamPtr;
00519     tmpEpRamPtr += maxPacket;
00520 
00521     if (!(options & SINGLE_BUFFERED)) {
00522         // Must be 64 byte aligned
00523         tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
00524 
00525         if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
00526             // Out of memory
00527             return false;
00528         }
00529 
00530         // Allocate second buffer
00531         endpointState[endpoint].buffer[1] = tmpEpRamPtr;
00532         tmpEpRamPtr += maxPacket;
00533     }
00534 
00535     // Commit to this USB RAM allocation
00536     epRamPtr = tmpEpRamPtr;
00537 
00538     // Remaining endpoint state values
00539     endpointState[endpoint].maxPacket = maxPacket;
00540     endpointState[endpoint].options = options;
00541 
00542     // Enable double buffering if required
00543     if (options & SINGLE_BUFFERED) {
00544         LPC_USB->EPBUFCFG &= ~EP(endpoint);
00545     } else {
00546         // Double buffered
00547         LPC_USB->EPBUFCFG |= EP(endpoint);
00548     }
00549 
00550     // Enable interrupt
00551     LPC_USB->INTEN |= EP(endpoint);
00552 
00553     // Enable endpoint
00554     unstallEndpoint(endpoint);
00555     return true;
00556 }
00557 
00558 void USBHAL::remoteWakeup(void) {
00559     // Clearing DSUS bit initiates a remote wakeup if the
00560     // device is currently enabled and suspended - otherwise
00561     // it has no effect.
00562     LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
00563 }
00564 
00565 
00566 static void disableEndpoints(void) {
00567     uint32_t logEp;
00568 
00569     // Ref. Table 158 "When a bus reset is received, software
00570     // must set the disable bit of all endpoints to 1".
00571 
00572     for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) {
00573         ep[logEp].out[0] = CMDSTS_D;
00574         ep[logEp].out[1] = CMDSTS_D;
00575         ep[logEp].in[0] =  CMDSTS_D;
00576         ep[logEp].in[1] =  CMDSTS_D;
00577     }
00578 
00579     // Start of USB RAM for endpoints > 0
00580     epRamPtr = usbRamPtr;
00581 }
00582 
00583 
00584 
00585 void USBHAL::_usbisr(void) {
00586     instance->usbisr();
00587 }
00588 
00589 void USBHAL::usbisr(void) {
00590     // Start of frame
00591     if (LPC_USB->INTSTAT & FRAME_INT) {
00592         // Clear SOF interrupt
00593         LPC_USB->INTSTAT = FRAME_INT;
00594 
00595         // SOF event, read frame number
00596         SOF(FRAME_NR(LPC_USB->INFO));
00597     }
00598 
00599     // Device state
00600     if (LPC_USB->INTSTAT & DEV_INT) {
00601         LPC_USB->INTSTAT = DEV_INT;
00602 
00603         if (LPC_USB->DEVCMDSTAT & DSUS_C) {
00604             // Suspend status changed
00605             LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
00606             if((LPC_USB->DEVCMDSTAT & DSUS) != 0) {
00607                 suspendStateChanged(1);
00608             }
00609         }
00610 
00611         if (LPC_USB->DEVCMDSTAT & DRES_C) {
00612             // Bus reset
00613             LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
00614 
00615             suspendStateChanged(0);
00616 
00617             // Disable endpoints > 0
00618             disableEndpoints();
00619 
00620             // Bus reset event
00621             busReset();
00622         }
00623     }
00624 
00625     // Endpoint 0
00626     if (LPC_USB->INTSTAT & EP(EP0OUT)) {
00627         // Clear EP0OUT/SETUP interrupt
00628         LPC_USB->INTSTAT = EP(EP0OUT);
00629 
00630         // Check if SETUP
00631         if (LPC_USB->DEVCMDSTAT & SETUP) {
00632             // Clear Active and Stall bits for EP0
00633             // Documentation does not make it clear if we must use the
00634             // EPSKIP register to achieve this, Fig. 16 and NXP reference
00635             // code suggests we can just clear the Active bits - check with
00636             // NXP to be sure.
00637             ep[0].in[0] = 0;
00638             ep[0].out[0] = 0;
00639 
00640             // Clear EP0IN interrupt
00641             LPC_USB->INTSTAT = EP(EP0IN);
00642 
00643             // Clear SETUP (and INTONNAK_CI/O) in device status register
00644             LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
00645 
00646             // EP0 SETUP event (SETUP data received)
00647             EP0setupCallback();
00648         } else {
00649             // EP0OUT ACK event (OUT data received)
00650             EP0out();
00651         }
00652     }
00653 
00654     if (LPC_USB->INTSTAT & EP(EP0IN)) {
00655         // Clear EP0IN interrupt
00656         LPC_USB->INTSTAT = EP(EP0IN);
00657 
00658         // EP0IN ACK event (IN data sent)
00659         EP0in();
00660     }
00661 
00662     if (LPC_USB->INTSTAT & EP(EP1IN)) {
00663         // Clear EP1IN interrupt
00664         LPC_USB->INTSTAT = EP(EP1IN);
00665         epComplete |= EP(EP1IN);
00666         if (EP1_IN_callback())
00667             epComplete &= ~EP(EP1IN);
00668     }
00669 
00670     if (LPC_USB->INTSTAT & EP(EP1OUT)) {
00671         // Clear EP1OUT interrupt
00672         LPC_USB->INTSTAT = EP(EP1OUT);
00673         epComplete |= EP(EP1OUT);
00674         if (EP1_OUT_callback())
00675             epComplete &= ~EP(EP1OUT);
00676     }
00677 
00678     if (LPC_USB->INTSTAT & EP(EP2IN)) {
00679         // Clear EPBULK_IN interrupt
00680         LPC_USB->INTSTAT = EP(EP2IN);
00681         epComplete |= EP(EP2IN);
00682         if (EP2_IN_callback())
00683             epComplete &= ~EP(EP2IN);
00684     }
00685 
00686     if (LPC_USB->INTSTAT & EP(EP2OUT)) {
00687         // Clear EPBULK_OUT interrupt
00688         LPC_USB->INTSTAT = EP(EP2OUT);
00689         epComplete |= EP(EP2OUT);
00690         //Call callback function. If true, clear epComplete
00691         if (EP2_OUT_callback())
00692             epComplete &= ~EP(EP2OUT);
00693     }
00694 
00695     if (LPC_USB->INTSTAT & EP(EP3IN)) {
00696         // Clear EP3_IN interrupt
00697         LPC_USB->INTSTAT = EP(EP3IN);
00698         epComplete |= EP(EP3IN);
00699         if (EP3_IN_callback())
00700             epComplete &= ~EP(EP3IN);
00701     }
00702 
00703     if (LPC_USB->INTSTAT & EP(EP3OUT)) {
00704         // Clear EP3_OUT interrupt
00705         LPC_USB->INTSTAT = EP(EP3OUT);
00706         epComplete |= EP(EP3OUT);
00707         //Call callback function. If true, clear epComplete
00708         if (EP3_OUT_callback())
00709             epComplete &= ~EP(EP3OUT);
00710     }
00711 }
00712 
00713 #endif