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