USB device stack - modified

Dependents:   shaun_larada

Fork of USBDevice by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_LPC11U.cpp Source File

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