USB device stack (USBDevice::connect non-blocking)

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