USB device stack - modified
Fork of USBDevice by
Embed:
(wiki syntax)
Show/hide line numbers
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 { 00087 uint32_t out[2]; 00088 uint32_t in[2]; 00089 } EP_COMMAND_STATUS; 00090 00091 typedef __packed struct 00092 { 00093 uint8_t out[MAX_PACKET_SIZE_EP0]; 00094 uint8_t in[MAX_PACKET_SIZE_EP0]; 00095 uint8_t setup[SETUP_PACKET_SIZE]; 00096 } CONTROL_TRANSFER; 00097 00098 typedef __packed struct 00099 { 00100 uint32_t maxPacket; 00101 uint32_t buffer[2]; 00102 uint32_t options; 00103 } EP_STATE; 00104 00105 static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS]; 00106 00107 // Pointer to the endpoint command/status list 00108 static EP_COMMAND_STATUS *ep = NULL; 00109 00110 // Pointer to endpoint 0 data (IN/OUT and SETUP) 00111 static CONTROL_TRANSFER *ct = NULL; 00112 00113 // Shadow DEVCMDSTAT register to avoid accidentally clearing flags or 00114 // initiating a remote wakeup event. 00115 static volatile uint32_t devCmdStat; 00116 00117 // Pointers used to allocate USB RAM 00118 static uint32_t usbRamPtr = USB_RAM_START; 00119 static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here 00120 00121 #define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m)) 00122 00123 void USBMemCopy( uint8_t *dst, uint8_t *src, uint32_t size ); 00124 void USBMemCopy( uint8_t *dst, uint8_t *src, uint32_t size ) 00125 { 00126 if ( size > 0 ) 00127 { 00128 do 00129 { 00130 *dst++ = *src++; 00131 } 00132 while ( --size > 0 ); 00133 } 00134 } 00135 00136 00137 USBHAL::USBHAL( void ) 00138 { 00139 NVIC_DisableIRQ( USB_IRQn ); 00140 #ifndef USB_ERRATA_WORKAROUND 00141 // control the CONNECT pin and VBUS as stdIO rather than by the peripheral 00142 // http://www.nxp.com/documents/errata_sheet/ES_LPC11U1X.pdf - BS 00143 // nUSB_CONNECT output 00144 LPC_IOCON->PIO0_6 = 0x00000001; 00145 #endif 00146 // Enable clocks (USB registers, USB RAM) 00147 LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM; 00148 // Ensure device disconnected (DCON not set) 00149 LPC_USB->DEVCMDSTAT = 0; 00150 // to ensure that the USB host sees the device as 00151 // disconnected if the target CPU is reset. 00152 wait( 0.3 ); 00153 // Reserve space in USB RAM for endpoint command/status list 00154 // Must be 256 byte aligned 00155 usbRamPtr = ROUND_UP_TO_MULTIPLE( usbRamPtr, 256 ); 00156 ep = ( EP_COMMAND_STATUS * )usbRamPtr; 00157 usbRamPtr += ( sizeof( EP_COMMAND_STATUS ) * NUMBER_OF_LOGICAL_ENDPOINTS ); 00158 LPC_USB->EPLISTSTART = ( uint32_t )( ep ) & 0xffffff00; 00159 // Reserve space in USB RAM for Endpoint 0 00160 // Must be 64 byte aligned 00161 usbRamPtr = ROUND_UP_TO_MULTIPLE( usbRamPtr, 64 ); 00162 ct = ( CONTROL_TRANSFER * )usbRamPtr; 00163 usbRamPtr += sizeof( CONTROL_TRANSFER ); 00164 LPC_USB->DATABUFSTART = ( uint32_t )( ct ) & 0xffc00000; 00165 // Setup command/status list for EP0 00166 ep[0].out[0] = 0; 00167 ep[0].in[0] = 0; 00168 ep[0].out[1] = CMDSTS_ADDRESS_OFFSET( ( uint32_t )ct->setup ); 00169 // Route all interrupts to IRQ, some can be routed to 00170 // USB_FIQ if you wish. 00171 LPC_USB->INTROUTING = 0; 00172 // Set device address 0, enable USB device, no remote wakeup 00173 devCmdStat = DEV_ADDR( 0 ) | DEV_EN | DSUS; 00174 LPC_USB->DEVCMDSTAT = devCmdStat; 00175 // Enable interrupts for device events and EP0 00176 LPC_USB->INTEN = DEV_INT | EP( EP0IN ) | EP( EP0OUT ) | FRAME_INT; 00177 instance = this; 00178 //attach IRQ handler and enable interrupts 00179 NVIC_SetVector( USB_IRQn, ( uint32_t )&_usbisr ); 00180 NVIC_EnableIRQ( USB_IRQn ); 00181 } 00182 00183 USBHAL::~USBHAL( void ) 00184 { 00185 // Ensure device disconnected (DCON not set) 00186 LPC_USB->DEVCMDSTAT = 0; 00187 // Disable USB interrupts 00188 NVIC_DisableIRQ( USB_IRQn ); 00189 } 00190 00191 void USBHAL::connect( void ) 00192 { 00193 devCmdStat |= DCON; 00194 LPC_USB->DEVCMDSTAT = devCmdStat; 00195 } 00196 00197 void USBHAL::disconnect( void ) 00198 { 00199 devCmdStat &= ~DCON; 00200 LPC_USB->DEVCMDSTAT = devCmdStat; 00201 } 00202 00203 #ifndef USB_ERRATA_WORKAROUND 00204 bool USBHAL::vbusDetected( void ) 00205 { 00206 return ( LPC_USB->DEVCMDSTAT & ( 1 << 28 ) ) ? 1 : 0; 00207 } 00208 #endif 00209 00210 void USBHAL::configureDevice( void ) 00211 { 00212 } 00213 00214 void USBHAL::unconfigureDevice( void ) 00215 { 00216 } 00217 00218 void USBHAL::EP0setup( uint8_t *buffer ) 00219 { 00220 // Copy setup packet data 00221 USBMemCopy( buffer, ct->setup, SETUP_PACKET_SIZE ); 00222 } 00223 00224 void USBHAL::EP0read( void ) 00225 { 00226 // Start an endpoint 0 read 00227 // The USB ISR will call USBDevice_EP0out() when a packet has been read, 00228 // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to 00229 // read the data. 00230 ep[0].out[0] = CMDSTS_A | CMDSTS_NBYTES( MAX_PACKET_SIZE_EP0 ) \ 00231 | CMDSTS_ADDRESS_OFFSET( ( uint32_t )ct->out ); 00232 } 00233 00234 uint32_t USBHAL::EP0getReadResult( uint8_t *buffer ) 00235 { 00236 // Complete an endpoint 0 read 00237 uint32_t bytesRead; 00238 // Find how many bytes were read 00239 bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING( ep[0].out[0] ); 00240 // Copy data 00241 USBMemCopy( buffer, ct->out, bytesRead ); 00242 return bytesRead; 00243 } 00244 00245 void USBHAL::EP0write( uint8_t *buffer, uint32_t size ) 00246 { 00247 // Start and endpoint 0 write 00248 // The USB ISR will call USBDevice_EP0in() when the data has 00249 // been written, the USBDevice layer then calls 00250 // USBBusInterface_EP0getWriteResult() to complete the transaction. 00251 // Copy data 00252 USBMemCopy( ct->in, buffer, size ); 00253 // Start transfer 00254 ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES( size ) \ 00255 | CMDSTS_ADDRESS_OFFSET( ( uint32_t )ct->in ); 00256 } 00257 00258 00259 EP_STATUS USBHAL::endpointRead( uint8_t endpoint, uint32_t maximumSize ) 00260 { 00261 uint8_t bf = 0; 00262 uint32_t flags = 0; 00263 00264 //check which buffer must be filled 00265 if ( LPC_USB->EPBUFCFG & EP( endpoint ) ) 00266 { 00267 // Double buffered 00268 if ( LPC_USB->EPINUSE & EP( endpoint ) ) 00269 { 00270 bf = 1; 00271 } 00272 else 00273 { 00274 bf = 0; 00275 } 00276 } 00277 00278 // if isochronous endpoint, T = 1 00279 if( endpointState[endpoint].options & ISOCHRONOUS ) 00280 { 00281 flags |= CMDSTS_T; 00282 } 00283 00284 //Active the endpoint for reading 00285 ep[PHY_TO_LOG( endpoint )].out[bf] = CMDSTS_A | CMDSTS_NBYTES( maximumSize ) \ 00286 | CMDSTS_ADDRESS_OFFSET( ( uint32_t )ct->out ) | flags; 00287 return EP_PENDING; 00288 } 00289 00290 EP_STATUS USBHAL::endpointReadResult( uint8_t endpoint, uint8_t *data, uint32_t *bytesRead ) 00291 { 00292 uint8_t bf = 0; 00293 00294 if ( !( epComplete & EP( endpoint ) ) ) 00295 { 00296 return EP_PENDING; 00297 } 00298 else 00299 { 00300 epComplete &= ~EP( endpoint ); 00301 00302 //check which buffer has been filled 00303 if ( LPC_USB->EPBUFCFG & EP( endpoint ) ) 00304 { 00305 // Double buffered (here we read the previous buffer which was used) 00306 if ( LPC_USB->EPINUSE & EP( endpoint ) ) 00307 { 00308 bf = 0; 00309 } 00310 else 00311 { 00312 bf = 1; 00313 } 00314 } 00315 00316 // Find how many bytes were read 00317 *bytesRead = ( uint32_t ) ( endpointState[endpoint].maxPacket - BYTES_REMAINING( ep[PHY_TO_LOG( endpoint )].out[bf] ) ); 00318 // Copy data 00319 USBMemCopy( data, ct->out, *bytesRead ); 00320 return EP_COMPLETED; 00321 } 00322 } 00323 00324 void USBHAL::EP0getWriteResult( void ) 00325 { 00326 // Complete an endpoint 0 write 00327 // Nothing required for this target 00328 return; 00329 } 00330 00331 void USBHAL::EP0stall( void ) 00332 { 00333 ep[0].in[0] = CMDSTS_S; 00334 ep[0].out[0] = CMDSTS_S; 00335 } 00336 00337 void USBHAL::setAddress( uint8_t address ) 00338 { 00339 devCmdStat &= ~DEV_ADDR_MASK; 00340 devCmdStat |= DEV_ADDR( address ); 00341 LPC_USB->DEVCMDSTAT = devCmdStat; 00342 } 00343 00344 EP_STATUS USBHAL::endpointWrite( uint8_t endpoint, uint8_t *data, uint32_t size ) 00345 { 00346 uint32_t flags = 0; 00347 uint32_t bf; 00348 00349 // Validate parameters 00350 if ( data == NULL ) 00351 { 00352 return EP_INVALID; 00353 } 00354 00355 if ( endpoint > LAST_PHYSICAL_ENDPOINT ) 00356 { 00357 return EP_INVALID; 00358 } 00359 00360 if ( ( endpoint == EP0IN ) || ( endpoint == EP0OUT ) ) 00361 { 00362 return EP_INVALID; 00363 } 00364 00365 if ( size > endpointState[endpoint].maxPacket ) 00366 { 00367 return EP_INVALID; 00368 } 00369 00370 if ( LPC_USB->EPBUFCFG & EP( endpoint ) ) 00371 { 00372 // Double buffered 00373 if ( LPC_USB->EPINUSE & EP( endpoint ) ) 00374 { 00375 bf = 1; 00376 } 00377 else 00378 { 00379 bf = 0; 00380 } 00381 } 00382 else 00383 { 00384 // Single buffered 00385 bf = 0; 00386 } 00387 00388 // Check if already active 00389 if ( ep[PHY_TO_LOG( endpoint )].in[bf] & CMDSTS_A ) 00390 { 00391 return EP_INVALID; 00392 } 00393 00394 // Check if stalled 00395 if ( ep[PHY_TO_LOG( endpoint )].in[bf] & CMDSTS_S ) 00396 { 00397 return EP_STALLED; 00398 } 00399 00400 // Copy data to USB RAM 00401 USBMemCopy( ( uint8_t * )endpointState[endpoint].buffer[bf], data, size ); 00402 00403 // Add options 00404 if ( endpointState[endpoint].options & RATE_FEEDBACK_MODE ) 00405 { 00406 flags |= CMDSTS_RF; 00407 } 00408 00409 if ( endpointState[endpoint].options & ISOCHRONOUS ) 00410 { 00411 flags |= CMDSTS_T; 00412 } 00413 00414 // Add transfer 00415 ep[PHY_TO_LOG( endpoint )].in[bf] = CMDSTS_ADDRESS_OFFSET( \ 00416 endpointState[endpoint].buffer[bf] ) \ 00417 | CMDSTS_NBYTES( size ) | CMDSTS_A | flags; 00418 return EP_PENDING; 00419 } 00420 00421 EP_STATUS USBHAL::endpointWriteResult( uint8_t endpoint ) 00422 { 00423 uint32_t bf; 00424 // Validate parameters 00425 00426 if ( endpoint > LAST_PHYSICAL_ENDPOINT ) 00427 { 00428 return EP_INVALID; 00429 } 00430 00431 if ( OUT_EP( endpoint ) ) 00432 { 00433 return EP_INVALID; 00434 } 00435 00436 if ( LPC_USB->EPBUFCFG & EP( endpoint ) ) 00437 { 00438 // Double buffered // TODO: FIX THIS 00439 if ( LPC_USB->EPINUSE & EP( endpoint ) ) 00440 { 00441 bf = 1; 00442 } 00443 else 00444 { 00445 bf = 0; 00446 } 00447 } 00448 else 00449 { 00450 // Single buffered 00451 bf = 0; 00452 } 00453 00454 // Check if endpoint still active 00455 if ( ep[PHY_TO_LOG( endpoint )].in[bf] & CMDSTS_A ) 00456 { 00457 return EP_PENDING; 00458 } 00459 00460 // Check if stalled 00461 if ( ep[PHY_TO_LOG( endpoint )].in[bf] & CMDSTS_S ) 00462 { 00463 return EP_STALLED; 00464 } 00465 00466 return EP_COMPLETED; 00467 } 00468 00469 void USBHAL::stallEndpoint( uint8_t endpoint ) 00470 { 00471 // TODO: should this clear active bit? 00472 if ( IN_EP( endpoint ) ) 00473 { 00474 ep[PHY_TO_LOG( endpoint )].in[0] |= CMDSTS_S; 00475 ep[PHY_TO_LOG( endpoint )].in[1] |= CMDSTS_S; 00476 } 00477 else 00478 { 00479 ep[PHY_TO_LOG( endpoint )].out[0] |= CMDSTS_S; 00480 ep[PHY_TO_LOG( endpoint )].out[1] |= CMDSTS_S; 00481 } 00482 } 00483 00484 void USBHAL::unstallEndpoint( uint8_t endpoint ) 00485 { 00486 if ( LPC_USB->EPBUFCFG & EP( endpoint ) ) 00487 { 00488 // Double buffered 00489 if ( IN_EP( endpoint ) ) 00490 { 00491 ep[PHY_TO_LOG( endpoint )].in[0] = 0; // S = 0 00492 ep[PHY_TO_LOG( endpoint )].in[1] = 0; // S = 0 00493 00494 if ( LPC_USB->EPINUSE & EP( endpoint ) ) 00495 { 00496 ep[PHY_TO_LOG( endpoint )].in[1] = CMDSTS_TR; // S =0, TR=1, TV = 0 00497 } 00498 else 00499 { 00500 ep[PHY_TO_LOG( endpoint )].in[0] = CMDSTS_TR; // S =0, TR=1, TV = 0 00501 } 00502 } 00503 else 00504 { 00505 ep[PHY_TO_LOG( endpoint )].out[0] = 0; // S = 0 00506 ep[PHY_TO_LOG( endpoint )].out[1] = 0; // S = 0 00507 00508 if ( LPC_USB->EPINUSE & EP( endpoint ) ) 00509 { 00510 ep[PHY_TO_LOG( endpoint )].out[1] = CMDSTS_TR; // S =0, TR=1, TV = 0 00511 } 00512 else 00513 { 00514 ep[PHY_TO_LOG( endpoint )].out[0] = CMDSTS_TR; // S =0, TR=1, TV = 0 00515 } 00516 } 00517 } 00518 else 00519 { 00520 // Single buffered 00521 if ( IN_EP( endpoint ) ) 00522 { 00523 ep[PHY_TO_LOG( endpoint )].in[0] = CMDSTS_TR; // S=0, TR=1, TV = 0 00524 } 00525 else 00526 { 00527 ep[PHY_TO_LOG( endpoint )].out[0] = CMDSTS_TR; // S=0, TR=1, TV = 0 00528 } 00529 } 00530 } 00531 00532 bool USBHAL::getEndpointStallState( unsigned char endpoint ) 00533 { 00534 if ( IN_EP( endpoint ) ) 00535 { 00536 if ( LPC_USB->EPINUSE & EP( endpoint ) ) 00537 { 00538 if ( ep[PHY_TO_LOG( endpoint )].in[1] & CMDSTS_S ) 00539 { 00540 return true; 00541 } 00542 } 00543 else 00544 { 00545 if ( ep[PHY_TO_LOG( endpoint )].in[0] & CMDSTS_S ) 00546 { 00547 return true; 00548 } 00549 } 00550 } 00551 else 00552 { 00553 if ( LPC_USB->EPINUSE & EP( endpoint ) ) 00554 { 00555 if ( ep[PHY_TO_LOG( endpoint )].out[1] & CMDSTS_S ) 00556 { 00557 return true; 00558 } 00559 } 00560 else 00561 { 00562 if ( ep[PHY_TO_LOG( endpoint )].out[0] & CMDSTS_S ) 00563 { 00564 return true; 00565 } 00566 } 00567 } 00568 00569 return false; 00570 } 00571 00572 bool USBHAL::realiseEndpoint( uint8_t endpoint, uint32_t maxPacket, uint32_t options ) 00573 { 00574 uint32_t tmpEpRamPtr; 00575 00576 if ( endpoint > LAST_PHYSICAL_ENDPOINT ) 00577 { 00578 return false; 00579 } 00580 00581 // Not applicable to the control endpoints 00582 if ( ( endpoint == EP0IN ) || ( endpoint == EP0OUT ) ) 00583 { 00584 return false; 00585 } 00586 00587 // Allocate buffers in USB RAM 00588 tmpEpRamPtr = epRamPtr; 00589 // Must be 64 byte aligned 00590 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE( tmpEpRamPtr, 64 ); 00591 00592 if ( ( tmpEpRamPtr + maxPacket ) > ( USB_RAM_START + USB_RAM_SIZE ) ) 00593 { 00594 // Out of memory 00595 return false; 00596 } 00597 00598 // Allocate first buffer 00599 endpointState[endpoint].buffer[0] = tmpEpRamPtr; 00600 tmpEpRamPtr += maxPacket; 00601 00602 if ( !( options & SINGLE_BUFFERED ) ) 00603 { 00604 // Must be 64 byte aligned 00605 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE( tmpEpRamPtr, 64 ); 00606 00607 if ( ( tmpEpRamPtr + maxPacket ) > ( USB_RAM_START + USB_RAM_SIZE ) ) 00608 { 00609 // Out of memory 00610 return false; 00611 } 00612 00613 // Allocate second buffer 00614 endpointState[endpoint].buffer[1] = tmpEpRamPtr; 00615 tmpEpRamPtr += maxPacket; 00616 } 00617 00618 // Commit to this USB RAM allocation 00619 epRamPtr = tmpEpRamPtr; 00620 // Remaining endpoint state values 00621 endpointState[endpoint].maxPacket = maxPacket; 00622 endpointState[endpoint].options = options; 00623 00624 // Enable double buffering if required 00625 if ( options & SINGLE_BUFFERED ) 00626 { 00627 LPC_USB->EPBUFCFG &= ~EP( endpoint ); 00628 } 00629 else 00630 { 00631 // Double buffered 00632 LPC_USB->EPBUFCFG |= EP( endpoint ); 00633 } 00634 00635 // Enable interrupt 00636 LPC_USB->INTEN |= EP( endpoint ); 00637 // Enable endpoint 00638 unstallEndpoint( endpoint ); 00639 return true; 00640 } 00641 00642 void USBHAL::remoteWakeup( void ) 00643 { 00644 // Clearing DSUS bit initiates a remote wakeup if the 00645 // device is currently enabled and suspended - otherwise 00646 // it has no effect. 00647 LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS; 00648 } 00649 00650 00651 static void disableEndpoints( void ) 00652 { 00653 uint32_t logEp; 00654 00655 // Ref. Table 158 "When a bus reset is received, software 00656 // must set the disable bit of all endpoints to 1". 00657 00658 for ( logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++ ) 00659 { 00660 ep[logEp].out[0] = CMDSTS_D; 00661 ep[logEp].out[1] = CMDSTS_D; 00662 ep[logEp].in[0] = CMDSTS_D; 00663 ep[logEp].in[1] = CMDSTS_D; 00664 } 00665 00666 // Start of USB RAM for endpoints > 0 00667 epRamPtr = usbRamPtr; 00668 } 00669 00670 00671 00672 void USBHAL::_usbisr( void ) 00673 { 00674 instance->usbisr(); 00675 } 00676 00677 void USBHAL::usbisr( void ) 00678 { 00679 // Start of frame 00680 if ( LPC_USB->INTSTAT & FRAME_INT ) 00681 { 00682 // Clear SOF interrupt 00683 LPC_USB->INTSTAT = FRAME_INT; 00684 // SOF event, read frame number 00685 SOF( FRAME_NR( LPC_USB->INFO ) ); 00686 } 00687 00688 // Device state 00689 if ( LPC_USB->INTSTAT & DEV_INT ) 00690 { 00691 LPC_USB->INTSTAT = DEV_INT; 00692 00693 if ( LPC_USB->DEVCMDSTAT & DSUS_C ) 00694 { 00695 // Suspend status changed 00696 LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C; 00697 00698 if( ( LPC_USB->DEVCMDSTAT & DSUS ) != 0 ) 00699 { 00700 suspendStateChanged( 1 ); 00701 } 00702 } 00703 00704 if ( LPC_USB->DEVCMDSTAT & DRES_C ) 00705 { 00706 // Bus reset 00707 LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C; 00708 suspendStateChanged( 0 ); 00709 // Disable endpoints > 0 00710 disableEndpoints(); 00711 // Bus reset event 00712 busReset(); 00713 } 00714 } 00715 00716 // Endpoint 0 00717 if ( LPC_USB->INTSTAT & EP( EP0OUT ) ) 00718 { 00719 // Clear EP0OUT/SETUP interrupt 00720 LPC_USB->INTSTAT = EP( EP0OUT ); 00721 00722 // Check if SETUP 00723 if ( LPC_USB->DEVCMDSTAT & SETUP ) 00724 { 00725 // Clear Active and Stall bits for EP0 00726 // Documentation does not make it clear if we must use the 00727 // EPSKIP register to achieve this, Fig. 16 and NXP reference 00728 // code suggests we can just clear the Active bits - check with 00729 // NXP to be sure. 00730 ep[0].in[0] = 0; 00731 ep[0].out[0] = 0; 00732 // Clear EP0IN interrupt 00733 LPC_USB->INTSTAT = EP( EP0IN ); 00734 // Clear SETUP (and INTONNAK_CI/O) in device status register 00735 LPC_USB->DEVCMDSTAT = devCmdStat | SETUP; 00736 // EP0 SETUP event (SETUP data received) 00737 EP0setupCallback(); 00738 } 00739 else 00740 { 00741 // EP0OUT ACK event (OUT data received) 00742 EP0out(); 00743 } 00744 } 00745 00746 if ( LPC_USB->INTSTAT & EP( EP0IN ) ) 00747 { 00748 // Clear EP0IN interrupt 00749 LPC_USB->INTSTAT = EP( EP0IN ); 00750 // EP0IN ACK event (IN data sent) 00751 EP0in(); 00752 } 00753 00754 if ( LPC_USB->INTSTAT & EP( EP1IN ) ) 00755 { 00756 // Clear EP1IN interrupt 00757 LPC_USB->INTSTAT = EP( EP1IN ); 00758 epComplete |= EP( EP1IN ); 00759 00760 if ( EP1_IN_callback() ) 00761 { 00762 epComplete &= ~EP( EP1IN ); 00763 } 00764 } 00765 00766 if ( LPC_USB->INTSTAT & EP( EP1OUT ) ) 00767 { 00768 // Clear EP1OUT interrupt 00769 LPC_USB->INTSTAT = EP( EP1OUT ); 00770 epComplete |= EP( EP1OUT ); 00771 00772 if ( EP1_OUT_callback() ) 00773 { 00774 epComplete &= ~EP( EP1OUT ); 00775 } 00776 } 00777 00778 if ( LPC_USB->INTSTAT & EP( EP2IN ) ) 00779 { 00780 // Clear EPBULK_IN interrupt 00781 LPC_USB->INTSTAT = EP( EP2IN ); 00782 epComplete |= EP( EP2IN ); 00783 00784 if ( EP2_IN_callback() ) 00785 { 00786 epComplete &= ~EP( EP2IN ); 00787 } 00788 } 00789 00790 if ( LPC_USB->INTSTAT & EP( EP2OUT ) ) 00791 { 00792 // Clear EPBULK_OUT interrupt 00793 LPC_USB->INTSTAT = EP( EP2OUT ); 00794 epComplete |= EP( EP2OUT ); 00795 00796 //Call callback function. If true, clear epComplete 00797 if ( EP2_OUT_callback() ) 00798 { 00799 epComplete &= ~EP( EP2OUT ); 00800 } 00801 } 00802 00803 if ( LPC_USB->INTSTAT & EP( EP3IN ) ) 00804 { 00805 // Clear EP3_IN interrupt 00806 LPC_USB->INTSTAT = EP( EP3IN ); 00807 epComplete |= EP( EP3IN ); 00808 00809 if ( EP3_IN_callback() ) 00810 { 00811 epComplete &= ~EP( EP3IN ); 00812 } 00813 } 00814 00815 if ( LPC_USB->INTSTAT & EP( EP3OUT ) ) 00816 { 00817 // Clear EP3_OUT interrupt 00818 LPC_USB->INTSTAT = EP( EP3OUT ); 00819 epComplete |= EP( EP3OUT ); 00820 00821 //Call callback function. If true, clear epComplete 00822 if ( EP3_OUT_callback() ) 00823 { 00824 epComplete &= ~EP( EP3OUT ); 00825 } 00826 } 00827 } 00828 00829 #endif 00830
Generated on Sat Jul 16 2022 03:17:41 by 1.7.2