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 // Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1) 00026 #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1) 00027 00028 // Convert physical endpoint number to register bit 00029 #define EP(endpoint) (1UL<<endpoint) 00030 00031 // Convert physical to logical 00032 #define PHY_TO_LOG(endpoint) ((endpoint)>>1) 00033 00034 // Get endpoint direction 00035 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false) 00036 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) 00037 00038 // USB RAM 00039 #define USB_RAM_START (0x20004000) 00040 #define USB_RAM_SIZE (0x00000800) 00041 00042 // SYSAHBCLKCTRL 00043 #define CLK_USB (1UL<<14) 00044 #define CLK_USBRAM (1UL<<27) 00045 00046 // USB Information register 00047 #define FRAME_NR(a) ((a) & 0x7ff) // Frame number 00048 00049 // USB Device Command/Status register 00050 #define DEV_ADDR_MASK (0x7f) // Device address 00051 #define DEV_ADDR(a) ((a) & DEV_ADDR_MASK) 00052 #define DEV_EN (1UL<<7) // Device enable 00053 #define SETUP (1UL<<8) // SETUP token received 00054 #define PLL_ON (1UL<<9) // PLL enabled in suspend 00055 #define DCON (1UL<<16) // Device status - connect 00056 #define DSUS (1UL<<17) // Device status - suspend 00057 #define DCON_C (1UL<<24) // Connect change 00058 #define DSUS_C (1UL<<25) // Suspend change 00059 #define DRES_C (1UL<<26) // Reset change 00060 #define VBUSDEBOUNCED (1UL<<28) // Vbus detected 00061 00062 // Endpoint Command/Status list 00063 #define CMDSTS_A (1UL<<31) // Active 00064 #define CMDSTS_D (1UL<<30) // Disable 00065 #define CMDSTS_S (1UL<<29) // Stall 00066 #define CMDSTS_TR (1UL<<28) // Toggle Reset 00067 #define CMDSTS_RF (1UL<<27) // Rate Feedback mode 00068 #define CMDSTS_TV (1UL<<27) // Toggle Value 00069 #define CMDSTS_T (1UL<<26) // Endpoint Type 00070 #define CMDSTS_NBYTES(n) (((n)&0x3ff)<<16) // Number of bytes 00071 #define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff) // Buffer start address 00072 00073 #define BYTES_REMAINING(s) (((s)>>16)&0x3ff) // Bytes remaining after transfer 00074 00075 // USB Non-endpoint interrupt sources 00076 #define FRAME_INT (1UL<<30) 00077 #define DEV_INT (1UL<<31) 00078 00079 static volatile int epComplete = 0; 00080 00081 // One entry for a double-buffered logical endpoint in the endpoint 00082 // command/status list. Endpoint 0 is single buffered, out[1] is used 00083 // for the SETUP packet and in[1] is not used 00084 typedef __packed struct { 00085 uint32_t out[2]; 00086 uint32_t in[2]; 00087 } EP_COMMAND_STATUS; 00088 00089 typedef __packed struct { 00090 uint8_t out[MAX_PACKET_SIZE_EP0]; 00091 uint8_t in[MAX_PACKET_SIZE_EP0]; 00092 uint8_t setup[SETUP_PACKET_SIZE]; 00093 } CONTROL_TRANSFER; 00094 00095 typedef __packed struct { 00096 uint32_t maxPacket; 00097 uint32_t buffer[2]; 00098 uint32_t options; 00099 } EP_STATE; 00100 00101 static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS]; 00102 00103 // Pointer to the endpoint command/status list 00104 static EP_COMMAND_STATUS *ep = NULL; 00105 00106 // Pointer to endpoint 0 data (IN/OUT and SETUP) 00107 static CONTROL_TRANSFER *ct = NULL; 00108 00109 // Shadow DEVCMDSTAT register to avoid accidentally clearing flags or 00110 // initiating a remote wakeup event. 00111 static volatile uint32_t devCmdStat; 00112 00113 // Pointers used to allocate USB RAM 00114 static uint32_t usbRamPtr = USB_RAM_START; 00115 static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here 00116 00117 #define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m)) 00118 00119 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size); 00120 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) { 00121 if (size > 0) { 00122 do { 00123 *dst++ = *src++; 00124 } while (--size > 0); 00125 } 00126 } 00127 00128 00129 USBHAL::USBHAL(void) { 00130 NVIC_DisableIRQ(USB_IRQn); 00131 00132 // fill in callback array 00133 epCallback[0] = &USBHAL::EP1_OUT_callback; 00134 epCallback[1] = &USBHAL::EP1_IN_callback; 00135 epCallback[2] = &USBHAL::EP2_OUT_callback; 00136 epCallback[3] = &USBHAL::EP2_IN_callback; 00137 epCallback[4] = &USBHAL::EP3_OUT_callback; 00138 epCallback[5] = &USBHAL::EP3_IN_callback; 00139 epCallback[6] = &USBHAL::EP4_OUT_callback; 00140 epCallback[7] = &USBHAL::EP4_IN_callback; 00141 00142 // nUSB_CONNECT output 00143 LPC_IOCON->PIO0_6 = 0x00000001; 00144 00145 // Enable clocks (USB registers, USB RAM) 00146 LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM; 00147 00148 // Ensure device disconnected (DCON not set) 00149 LPC_USB->DEVCMDSTAT = 0; 00150 00151 // to ensure that the USB host sees the device as 00152 // disconnected if the target CPU is reset. 00153 wait(0.3); 00154 00155 // Reserve space in USB RAM for endpoint command/status list 00156 // Must be 256 byte aligned 00157 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256); 00158 ep = (EP_COMMAND_STATUS *)usbRamPtr; 00159 usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS); 00160 LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00; 00161 00162 // Reserve space in USB RAM for Endpoint 0 00163 // Must be 64 byte aligned 00164 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64); 00165 ct = (CONTROL_TRANSFER *)usbRamPtr; 00166 usbRamPtr += sizeof(CONTROL_TRANSFER); 00167 LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000; 00168 00169 // Setup command/status list for EP0 00170 ep[0].out[0] = 0; 00171 ep[0].in[0] = 0; 00172 ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup); 00173 00174 // Route all interrupts to IRQ, some can be routed to 00175 // USB_FIQ if you wish. 00176 LPC_USB->INTROUTING = 0; 00177 00178 // Set device address 0, enable USB device, no remote wakeup 00179 devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS; 00180 LPC_USB->DEVCMDSTAT = devCmdStat; 00181 00182 // Enable interrupts for device events and EP0 00183 LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT) | FRAME_INT; 00184 instance = this; 00185 00186 //attach IRQ handler and enable interrupts 00187 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr); 00188 } 00189 00190 USBHAL::~USBHAL(void) { 00191 // Ensure device disconnected (DCON not set) 00192 LPC_USB->DEVCMDSTAT = 0; 00193 // Disable USB interrupts 00194 NVIC_DisableIRQ(USB_IRQn); 00195 } 00196 00197 void USBHAL::connect(void) { 00198 NVIC_EnableIRQ(USB_IRQn); 00199 devCmdStat |= DCON; 00200 LPC_USB->DEVCMDSTAT = devCmdStat; 00201 } 00202 00203 void USBHAL::disconnect(void) { 00204 NVIC_DisableIRQ(USB_IRQn); 00205 devCmdStat &= ~DCON; 00206 LPC_USB->DEVCMDSTAT = devCmdStat; 00207 } 00208 00209 void USBHAL::configureDevice(void) { 00210 // Not required 00211 } 00212 00213 void USBHAL::unconfigureDevice(void) { 00214 // Not required 00215 } 00216 00217 void USBHAL::EP0setup(uint8_t *buffer) { 00218 // Copy setup packet data 00219 USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE); 00220 } 00221 00222 void USBHAL::EP0read(void) { 00223 // Start an endpoint 0 read 00224 00225 // The USB ISR will call USBDevice_EP0out() when a packet has been read, 00226 // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to 00227 // read the data. 00228 00229 ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \ 00230 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out); 00231 } 00232 00233 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { 00234 // Complete an endpoint 0 read 00235 uint32_t bytesRead; 00236 00237 // Find how many bytes were read 00238 bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]); 00239 00240 // Copy data 00241 USBMemCopy(buffer, ct->out, bytesRead); 00242 return bytesRead; 00243 } 00244 00245 00246 void USBHAL::EP0readStage(void) { 00247 // Not required 00248 } 00249 00250 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { 00251 // Start and endpoint 0 write 00252 00253 // The USB ISR will call USBDevice_EP0in() when the data has 00254 // been written, the USBDevice layer then calls 00255 // USBBusInterface_EP0getWriteResult() to complete the transaction. 00256 00257 // Copy data 00258 USBMemCopy(ct->in, buffer, size); 00259 00260 // Start transfer 00261 ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \ 00262 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in); 00263 } 00264 00265 00266 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { 00267 uint8_t bf = 0; 00268 uint32_t flags = 0; 00269 00270 //check which buffer must be filled 00271 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00272 // Double buffered 00273 if (LPC_USB->EPINUSE & EP(endpoint)) { 00274 bf = 1; 00275 } else { 00276 bf = 0; 00277 } 00278 } 00279 00280 // if isochronous endpoint, T = 1 00281 if(endpointState[endpoint].options & ISOCHRONOUS) 00282 { 00283 flags |= CMDSTS_T; 00284 } 00285 00286 //Active the endpoint for reading 00287 ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \ 00288 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags; 00289 return EP_PENDING; 00290 } 00291 00292 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) { 00293 00294 uint8_t bf = 0; 00295 00296 if (!(epComplete & EP(endpoint))) 00297 return EP_PENDING; 00298 else { 00299 epComplete &= ~EP(endpoint); 00300 00301 //check which buffer has been filled 00302 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00303 // Double buffered (here we read the previous buffer which was used) 00304 if (LPC_USB->EPINUSE & EP(endpoint)) { 00305 bf = 0; 00306 } else { 00307 bf = 1; 00308 } 00309 } 00310 00311 // Find how many bytes were read 00312 *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf])); 00313 00314 // Copy data 00315 USBMemCopy(data, ct->out, *bytesRead); 00316 return EP_COMPLETED; 00317 } 00318 } 00319 00320 void USBHAL::EP0getWriteResult(void) { 00321 // Not required 00322 } 00323 00324 void USBHAL::EP0stall(void) { 00325 ep[0].in[0] = CMDSTS_S; 00326 ep[0].out[0] = CMDSTS_S; 00327 } 00328 00329 void USBHAL::setAddress(uint8_t address) { 00330 devCmdStat &= ~DEV_ADDR_MASK; 00331 devCmdStat |= DEV_ADDR(address); 00332 LPC_USB->DEVCMDSTAT = devCmdStat; 00333 } 00334 00335 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { 00336 uint32_t flags = 0; 00337 uint32_t bf; 00338 00339 // Validate parameters 00340 if (data == NULL) { 00341 return EP_INVALID; 00342 } 00343 00344 if (endpoint > LAST_PHYSICAL_ENDPOINT) { 00345 return EP_INVALID; 00346 } 00347 00348 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) { 00349 return EP_INVALID; 00350 } 00351 00352 if (size > endpointState[endpoint].maxPacket) { 00353 return EP_INVALID; 00354 } 00355 00356 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00357 // Double buffered 00358 if (LPC_USB->EPINUSE & EP(endpoint)) { 00359 bf = 1; 00360 } else { 00361 bf = 0; 00362 } 00363 } else { 00364 // Single buffered 00365 bf = 0; 00366 } 00367 00368 // Check if already active 00369 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) { 00370 return EP_INVALID; 00371 } 00372 00373 // Check if stalled 00374 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) { 00375 return EP_STALLED; 00376 } 00377 00378 // Copy data to USB RAM 00379 USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size); 00380 00381 // Add options 00382 if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) { 00383 flags |= CMDSTS_RF; 00384 } 00385 00386 if (endpointState[endpoint].options & ISOCHRONOUS) { 00387 flags |= CMDSTS_T; 00388 } 00389 00390 // Add transfer 00391 ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \ 00392 endpointState[endpoint].buffer[bf]) \ 00393 | CMDSTS_NBYTES(size) | CMDSTS_A | flags; 00394 00395 return EP_PENDING; 00396 } 00397 00398 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { 00399 uint32_t bf; 00400 00401 // Validate parameters 00402 if (endpoint > LAST_PHYSICAL_ENDPOINT) { 00403 return EP_INVALID; 00404 } 00405 00406 if (OUT_EP(endpoint)) { 00407 return EP_INVALID; 00408 } 00409 00410 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00411 // Double buffered // TODO: FIX THIS 00412 if (LPC_USB->EPINUSE & EP(endpoint)) { 00413 bf = 1; 00414 } else { 00415 bf = 0; 00416 } 00417 } else { 00418 // Single buffered 00419 bf = 0; 00420 } 00421 00422 // Check if endpoint still active 00423 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) { 00424 return EP_PENDING; 00425 } 00426 00427 // Check if stalled 00428 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) { 00429 return EP_STALLED; 00430 } 00431 00432 return EP_COMPLETED; 00433 } 00434 00435 void USBHAL::stallEndpoint(uint8_t endpoint) { 00436 00437 // FIX: should this clear active bit? 00438 if (IN_EP(endpoint)) { 00439 ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S; 00440 ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S; 00441 } else { 00442 ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S; 00443 ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S; 00444 } 00445 } 00446 00447 void USBHAL::unstallEndpoint(uint8_t endpoint) { 00448 if (LPC_USB->EPBUFCFG & EP(endpoint)) { 00449 // Double buffered 00450 if (IN_EP(endpoint)) { 00451 ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0 00452 ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0 00453 00454 if (LPC_USB->EPINUSE & EP(endpoint)) { 00455 ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00456 } else { 00457 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00458 } 00459 } else { 00460 ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0 00461 ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0 00462 00463 if (LPC_USB->EPINUSE & EP(endpoint)) { 00464 ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00465 } else { 00466 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00467 } 00468 } 00469 } else { 00470 // Single buffered 00471 if (IN_EP(endpoint)) { 00472 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00473 } else { 00474 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0 00475 } 00476 } 00477 } 00478 00479 bool USBHAL::getEndpointStallState(unsigned char endpoint) { 00480 if (IN_EP(endpoint)) { 00481 if (LPC_USB->EPINUSE & EP(endpoint)) { 00482 if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) { 00483 return true; 00484 } 00485 } else { 00486 if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) { 00487 return true; 00488 } 00489 } 00490 } else { 00491 if (LPC_USB->EPINUSE & EP(endpoint)) { 00492 if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) { 00493 return true; 00494 } 00495 } else { 00496 if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) { 00497 return true; 00498 } 00499 } 00500 } 00501 00502 return false; 00503 } 00504 00505 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) { 00506 uint32_t tmpEpRamPtr; 00507 00508 if (endpoint > LAST_PHYSICAL_ENDPOINT) { 00509 return false; 00510 } 00511 00512 // Not applicable to the control endpoints 00513 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) { 00514 return false; 00515 } 00516 00517 // Allocate buffers in USB RAM 00518 tmpEpRamPtr = epRamPtr; 00519 00520 // Must be 64 byte aligned 00521 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64); 00522 00523 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) { 00524 // Out of memory 00525 return false; 00526 } 00527 00528 // Allocate first buffer 00529 endpointState[endpoint].buffer[0] = tmpEpRamPtr; 00530 tmpEpRamPtr += maxPacket; 00531 00532 if (!(options & SINGLE_BUFFERED)) { 00533 // Must be 64 byte aligned 00534 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64); 00535 00536 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) { 00537 // Out of memory 00538 return false; 00539 } 00540 00541 // Allocate second buffer 00542 endpointState[endpoint].buffer[1] = tmpEpRamPtr; 00543 tmpEpRamPtr += maxPacket; 00544 } 00545 00546 // Commit to this USB RAM allocation 00547 epRamPtr = tmpEpRamPtr; 00548 00549 // Remaining endpoint state values 00550 endpointState[endpoint].maxPacket = maxPacket; 00551 endpointState[endpoint].options = options; 00552 00553 // Enable double buffering if required 00554 if (options & SINGLE_BUFFERED) { 00555 LPC_USB->EPBUFCFG &= ~EP(endpoint); 00556 } else { 00557 // Double buffered 00558 LPC_USB->EPBUFCFG |= EP(endpoint); 00559 } 00560 00561 // Enable interrupt 00562 LPC_USB->INTEN |= EP(endpoint); 00563 00564 // Enable endpoint 00565 unstallEndpoint(endpoint); 00566 return true; 00567 } 00568 00569 void USBHAL::remoteWakeup(void) { 00570 // Clearing DSUS bit initiates a remote wakeup if the 00571 // device is currently enabled and suspended - otherwise 00572 // it has no effect. 00573 LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS; 00574 } 00575 00576 00577 static void disableEndpoints(void) { 00578 uint32_t logEp; 00579 00580 // Ref. Table 158 "When a bus reset is received, software 00581 // must set the disable bit of all endpoints to 1". 00582 00583 for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) { 00584 ep[logEp].out[0] = CMDSTS_D; 00585 ep[logEp].out[1] = CMDSTS_D; 00586 ep[logEp].in[0] = CMDSTS_D; 00587 ep[logEp].in[1] = CMDSTS_D; 00588 } 00589 00590 // Start of USB RAM for endpoints > 0 00591 epRamPtr = usbRamPtr; 00592 } 00593 00594 00595 00596 void USBHAL::_usbisr(void) { 00597 instance->usbisr(); 00598 } 00599 00600 void USBHAL::usbisr(void) { 00601 // Start of frame 00602 if (LPC_USB->INTSTAT & FRAME_INT) { 00603 // Clear SOF interrupt 00604 LPC_USB->INTSTAT = FRAME_INT; 00605 00606 // SOF event, read frame number 00607 SOF(FRAME_NR(LPC_USB->INFO)); 00608 } 00609 00610 // Device state 00611 if (LPC_USB->INTSTAT & DEV_INT) { 00612 LPC_USB->INTSTAT = DEV_INT; 00613 00614 if (LPC_USB->DEVCMDSTAT & DSUS_C) { 00615 // Suspend status changed 00616 LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C; 00617 if((LPC_USB->DEVCMDSTAT & DSUS) != 0) { 00618 suspendStateChanged(1); 00619 } 00620 } 00621 00622 if (LPC_USB->DEVCMDSTAT & DRES_C) { 00623 // Bus reset 00624 LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C; 00625 00626 suspendStateChanged(0); 00627 00628 // Disable endpoints > 0 00629 disableEndpoints(); 00630 00631 // Bus reset event 00632 busReset(); 00633 } 00634 } 00635 00636 // Endpoint 0 00637 if (LPC_USB->INTSTAT & EP(EP0OUT)) { 00638 // Clear EP0OUT/SETUP interrupt 00639 LPC_USB->INTSTAT = EP(EP0OUT); 00640 00641 // Check if SETUP 00642 if (LPC_USB->DEVCMDSTAT & SETUP) { 00643 // Clear Active and Stall bits for EP0 00644 // Documentation does not make it clear if we must use the 00645 // EPSKIP register to achieve this, Fig. 16 and NXP reference 00646 // code suggests we can just clear the Active bits - check with 00647 // NXP to be sure. 00648 ep[0].in[0] = 0; 00649 ep[0].out[0] = 0; 00650 00651 // Clear EP0IN interrupt 00652 LPC_USB->INTSTAT = EP(EP0IN); 00653 00654 // Clear SETUP (and INTONNAK_CI/O) in device status register 00655 LPC_USB->DEVCMDSTAT = devCmdStat | SETUP; 00656 00657 // EP0 SETUP event (SETUP data received) 00658 EP0setupCallback(); 00659 } else { 00660 // EP0OUT ACK event (OUT data received) 00661 EP0out(); 00662 } 00663 } 00664 00665 if (LPC_USB->INTSTAT & EP(EP0IN)) { 00666 // Clear EP0IN interrupt 00667 LPC_USB->INTSTAT = EP(EP0IN); 00668 00669 // EP0IN ACK event (IN data sent) 00670 EP0in(); 00671 } 00672 00673 for (uint8_t num = 2; num < 5*2; num++) { 00674 if (LPC_USB->INTSTAT & EP(num)) { 00675 LPC_USB->INTSTAT = EP(num); 00676 epComplete |= EP(num); 00677 if ((instance->*(epCallback[num - 2]))()) { 00678 epComplete &= ~EP(num); 00679 } 00680 } 00681 } 00682 } 00683 00684 #endif
Generated on Wed Jul 20 2022 00:01:16 by
