Fork of Smoothie to port to mbed non-LPC targets.
Fork of Smoothie by
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
Generated on Tue Jul 12 2022 20:09:03 by 1.7.2