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
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
Generated on Tue Jul 12 2022 21:32:43 by 1.7.2