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