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.
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 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 Wed Jul 13 2022 03:25:45 by
1.7.2
