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