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_LPC11U35_401) || defined(TARGET_LPC1347) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPC11U68) 00020 00021 #if defined(TARGET_LPC1347) 00022 #define USB_IRQ USB_IRQ_IRQn 00023 #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPC11U68) 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) || defined(TARGET_LPC11U35_501) 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 Wed Jul 13 2022 15:02:42 by
1.7.2
