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 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
