USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Fri Nov 11 15:22:53 2011 +0000
Revision:
2:27a7e7f8d399
we have 2MB with the sdcard!!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 2:27a7e7f8d399 1 // USBBusInterface_LPC11U.c
samux 2:27a7e7f8d399 2 // USB Bus Interface for NXP LPC11Uxx
samux 2:27a7e7f8d399 3 // Copyright (c) 2011 ARM Limited. All rights reserved.
samux 2:27a7e7f8d399 4
samux 2:27a7e7f8d399 5 // Reference:
samux 2:27a7e7f8d399 6 // NXP UM10462 LPC11U1x User manual Rev. 1 � 14 April 2011
samux 2:27a7e7f8d399 7
samux 2:27a7e7f8d399 8 #ifdef TARGET_LPC11U24
samux 2:27a7e7f8d399 9
samux 2:27a7e7f8d399 10 #include "USBBusInterface.h"
samux 2:27a7e7f8d399 11
samux 2:27a7e7f8d399 12 USBHAL * USBHAL::instance;
samux 2:27a7e7f8d399 13
samux 2:27a7e7f8d399 14
samux 2:27a7e7f8d399 15 // Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
samux 2:27a7e7f8d399 16 #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
samux 2:27a7e7f8d399 17
samux 2:27a7e7f8d399 18 // Convert physical endpoint number to register bit
samux 2:27a7e7f8d399 19 #define EP(endpoint) (1UL<<endpoint)
samux 2:27a7e7f8d399 20
samux 2:27a7e7f8d399 21 // Convert physical to logical
samux 2:27a7e7f8d399 22 #define PHY_TO_LOG(endpoint) ((endpoint)>>1)
samux 2:27a7e7f8d399 23
samux 2:27a7e7f8d399 24 // Get endpoint direction
samux 2:27a7e7f8d399 25 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
samux 2:27a7e7f8d399 26 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
samux 2:27a7e7f8d399 27
samux 2:27a7e7f8d399 28 // USB RAM
samux 2:27a7e7f8d399 29 #define USB_RAM_START (0x20004000)
samux 2:27a7e7f8d399 30 #define USB_RAM_SIZE (0x00000800)
samux 2:27a7e7f8d399 31
samux 2:27a7e7f8d399 32 // SYSAHBCLKCTRL
samux 2:27a7e7f8d399 33 #define CLK_USB (1UL<<14)
samux 2:27a7e7f8d399 34 #define CLK_USBRAM (1UL<<27)
samux 2:27a7e7f8d399 35
samux 2:27a7e7f8d399 36 // USB Information register
samux 2:27a7e7f8d399 37 #define FRAME_NR(a) ((a) & 0x7ff) // Frame number
samux 2:27a7e7f8d399 38
samux 2:27a7e7f8d399 39 // USB Device Command/Status register
samux 2:27a7e7f8d399 40 #define DEV_ADDR_MASK (0x7f) // Device address
samux 2:27a7e7f8d399 41 #define DEV_ADDR(a) ((a) & DEV_ADDR_MASK)
samux 2:27a7e7f8d399 42 #define DEV_EN (1UL<<7) // Device enable
samux 2:27a7e7f8d399 43 #define SETUP (1UL<<8) // SETUP token received
samux 2:27a7e7f8d399 44 #define PLL_ON (1UL<<9) // PLL enabled in suspend
samux 2:27a7e7f8d399 45 #define DCON (1UL<<16) // Device status - connect
samux 2:27a7e7f8d399 46 #define DSUS (1UL<<17) // Device status - suspend
samux 2:27a7e7f8d399 47 #define DCON_C (1UL<<24) // Connect change
samux 2:27a7e7f8d399 48 #define DSUS_C (1UL<<25) // Suspend change
samux 2:27a7e7f8d399 49 #define DRES_C (1UL<<26) // Reset change
samux 2:27a7e7f8d399 50 #define VBUSDEBOUNCED (1UL<<28) // Vbus detected
samux 2:27a7e7f8d399 51
samux 2:27a7e7f8d399 52 // Endpoint Command/Status list
samux 2:27a7e7f8d399 53 #define CMDSTS_A (1UL<<31) // Active
samux 2:27a7e7f8d399 54 #define CMDSTS_D (1UL<<30) // Disable
samux 2:27a7e7f8d399 55 #define CMDSTS_S (1UL<<29) // Stall
samux 2:27a7e7f8d399 56 #define CMDSTS_TR (1UL<<28) // Toggle Reset
samux 2:27a7e7f8d399 57 #define CMDSTS_RF (1UL<<27) // Rate Feedback mode
samux 2:27a7e7f8d399 58 #define CMDSTS_TV (1UL<<27) // Toggle Value
samux 2:27a7e7f8d399 59 #define CMDSTS_T (1UL<<26) // Endpoint Type
samux 2:27a7e7f8d399 60 #define CMDSTS_NBYTES(n) (((n)&0x3ff)<<16) // Number of bytes
samux 2:27a7e7f8d399 61 #define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff) // Buffer start address
samux 2:27a7e7f8d399 62
samux 2:27a7e7f8d399 63 #define BYTES_REMAINING(s) (((s)>>16)&0x3ff) // Bytes remaining after transfer
samux 2:27a7e7f8d399 64
samux 2:27a7e7f8d399 65 // USB Non-endpoint interrupt sources
samux 2:27a7e7f8d399 66 #define FRAME_INT (1UL<<30)
samux 2:27a7e7f8d399 67 #define DEV_INT (1UL<<31)
samux 2:27a7e7f8d399 68
samux 2:27a7e7f8d399 69 static int epComplete = 0;
samux 2:27a7e7f8d399 70
samux 2:27a7e7f8d399 71 // One entry for a double-buffered logical endpoint in the endpoint
samux 2:27a7e7f8d399 72 // command/status list. Endpoint 0 is single buffered, out[1] is used
samux 2:27a7e7f8d399 73 // for the SETUP packet and in[1] is not used
samux 2:27a7e7f8d399 74 typedef __packed struct {
samux 2:27a7e7f8d399 75 uint32_t out[2];
samux 2:27a7e7f8d399 76 uint32_t in[2];
samux 2:27a7e7f8d399 77 } EP_COMMAND_STATUS;
samux 2:27a7e7f8d399 78
samux 2:27a7e7f8d399 79 typedef __packed struct {
samux 2:27a7e7f8d399 80 uint8_t out[MAX_PACKET_SIZE_EP0];
samux 2:27a7e7f8d399 81 uint8_t in[MAX_PACKET_SIZE_EP0];
samux 2:27a7e7f8d399 82 uint8_t setup[SETUP_PACKET_SIZE];
samux 2:27a7e7f8d399 83 } CONTROL_TRANSFER;
samux 2:27a7e7f8d399 84
samux 2:27a7e7f8d399 85 typedef __packed struct {
samux 2:27a7e7f8d399 86 uint32_t maxPacket;
samux 2:27a7e7f8d399 87 uint32_t buffer[2];
samux 2:27a7e7f8d399 88 uint32_t options;
samux 2:27a7e7f8d399 89 } EP_STATE;
samux 2:27a7e7f8d399 90
samux 2:27a7e7f8d399 91 static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
samux 2:27a7e7f8d399 92
samux 2:27a7e7f8d399 93 // Pointer to the endpoint command/status list
samux 2:27a7e7f8d399 94 static EP_COMMAND_STATUS *ep = NULL;
samux 2:27a7e7f8d399 95
samux 2:27a7e7f8d399 96 // Pointer to endpoint 0 data (IN/OUT and SETUP)
samux 2:27a7e7f8d399 97 static CONTROL_TRANSFER *ct = NULL;
samux 2:27a7e7f8d399 98
samux 2:27a7e7f8d399 99 // Shadow DEVCMDSTAT register to avoid accidentally clearing flags or
samux 2:27a7e7f8d399 100 // initiating a remote wakeup event.
samux 2:27a7e7f8d399 101 static volatile uint32_t devCmdStat;
samux 2:27a7e7f8d399 102
samux 2:27a7e7f8d399 103 // Pointers used to allocate USB RAM
samux 2:27a7e7f8d399 104 static uint32_t usbRamPtr = USB_RAM_START;
samux 2:27a7e7f8d399 105 static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here
samux 2:27a7e7f8d399 106
samux 2:27a7e7f8d399 107 #define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m))
samux 2:27a7e7f8d399 108
samux 2:27a7e7f8d399 109 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size);
samux 2:27a7e7f8d399 110 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) {
samux 2:27a7e7f8d399 111 if (size > 0) {
samux 2:27a7e7f8d399 112 do {
samux 2:27a7e7f8d399 113 *dst++ = *src++;
samux 2:27a7e7f8d399 114 } while (--size > 0);
samux 2:27a7e7f8d399 115 }
samux 2:27a7e7f8d399 116 }
samux 2:27a7e7f8d399 117
samux 2:27a7e7f8d399 118
samux 2:27a7e7f8d399 119 USBHAL::USBHAL(void) {
samux 2:27a7e7f8d399 120 NVIC_DisableIRQ(USB_IRQn);
samux 2:27a7e7f8d399 121
samux 2:27a7e7f8d399 122 // nUSB_CONNECT output
samux 2:27a7e7f8d399 123 LPC_IOCON->PIO0_6 = 0x00000001;
samux 2:27a7e7f8d399 124
samux 2:27a7e7f8d399 125 // Enable clocks (USB registers, USB RAM)
samux 2:27a7e7f8d399 126 LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
samux 2:27a7e7f8d399 127
samux 2:27a7e7f8d399 128 // Ensure device disconnected (DCON not set)
samux 2:27a7e7f8d399 129 LPC_USB->DEVCMDSTAT = 0;
samux 2:27a7e7f8d399 130
samux 2:27a7e7f8d399 131 // to ensure that the USB host sees the device as
samux 2:27a7e7f8d399 132 // disconnected if the target CPU is reset.
samux 2:27a7e7f8d399 133 wait(0.3);
samux 2:27a7e7f8d399 134
samux 2:27a7e7f8d399 135 // Reserve space in USB RAM for endpoint command/status list
samux 2:27a7e7f8d399 136 // Must be 256 byte aligned
samux 2:27a7e7f8d399 137 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256);
samux 2:27a7e7f8d399 138 ep = (EP_COMMAND_STATUS *)usbRamPtr;
samux 2:27a7e7f8d399 139 usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS);
samux 2:27a7e7f8d399 140 LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00;
samux 2:27a7e7f8d399 141
samux 2:27a7e7f8d399 142 // Reserve space in USB RAM for Endpoint 0
samux 2:27a7e7f8d399 143 // Must be 64 byte aligned
samux 2:27a7e7f8d399 144 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64);
samux 2:27a7e7f8d399 145 ct = (CONTROL_TRANSFER *)usbRamPtr;
samux 2:27a7e7f8d399 146 usbRamPtr += sizeof(CONTROL_TRANSFER);
samux 2:27a7e7f8d399 147 LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000;
samux 2:27a7e7f8d399 148
samux 2:27a7e7f8d399 149 // Setup command/status list for EP0
samux 2:27a7e7f8d399 150 ep[0].out[0] = 0;
samux 2:27a7e7f8d399 151 ep[0].in[0] = 0;
samux 2:27a7e7f8d399 152 ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup);
samux 2:27a7e7f8d399 153
samux 2:27a7e7f8d399 154 // Route all interrupts to IRQ, some can be routed to
samux 2:27a7e7f8d399 155 // USB_FIQ if you wish.
samux 2:27a7e7f8d399 156 LPC_USB->INTROUTING = 0;
samux 2:27a7e7f8d399 157
samux 2:27a7e7f8d399 158 // Set device address 0, enable USB device, no remote wakeup
samux 2:27a7e7f8d399 159 devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS;
samux 2:27a7e7f8d399 160 LPC_USB->DEVCMDSTAT = devCmdStat;
samux 2:27a7e7f8d399 161
samux 2:27a7e7f8d399 162 // Enable interrupts for device events and EP0
samux 2:27a7e7f8d399 163 LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT);
samux 2:27a7e7f8d399 164 instance = this;
samux 2:27a7e7f8d399 165
samux 2:27a7e7f8d399 166 //attach IRQ handler and enable interrupts
samux 2:27a7e7f8d399 167 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
samux 2:27a7e7f8d399 168 NVIC_EnableIRQ(USB_IRQn);
samux 2:27a7e7f8d399 169 }
samux 2:27a7e7f8d399 170
samux 2:27a7e7f8d399 171 USBHAL::~USBHAL(void) {
samux 2:27a7e7f8d399 172 // Ensure device disconnected (DCON not set)
samux 2:27a7e7f8d399 173 LPC_USB->DEVCMDSTAT = 0;
samux 2:27a7e7f8d399 174
samux 2:27a7e7f8d399 175 // Disable USB interrupts
samux 2:27a7e7f8d399 176 NVIC_DisableIRQ(USB_IRQn);
samux 2:27a7e7f8d399 177 }
samux 2:27a7e7f8d399 178
samux 2:27a7e7f8d399 179 void USBHAL::connect(void) {
samux 2:27a7e7f8d399 180 devCmdStat |= DCON;
samux 2:27a7e7f8d399 181 LPC_USB->DEVCMDSTAT = devCmdStat;
samux 2:27a7e7f8d399 182 }
samux 2:27a7e7f8d399 183
samux 2:27a7e7f8d399 184 void USBHAL::disconnect(void) {
samux 2:27a7e7f8d399 185 devCmdStat &= ~DCON;
samux 2:27a7e7f8d399 186 LPC_USB->DEVCMDSTAT = devCmdStat;
samux 2:27a7e7f8d399 187 }
samux 2:27a7e7f8d399 188
samux 2:27a7e7f8d399 189 void USBHAL::configureDevice(void) {
samux 2:27a7e7f8d399 190 }
samux 2:27a7e7f8d399 191
samux 2:27a7e7f8d399 192 void USBHAL::unconfigureDevice(void) {
samux 2:27a7e7f8d399 193 }
samux 2:27a7e7f8d399 194
samux 2:27a7e7f8d399 195 void USBHAL::EP0setup(uint8_t *buffer) {
samux 2:27a7e7f8d399 196 // Copy setup packet data
samux 2:27a7e7f8d399 197 USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
samux 2:27a7e7f8d399 198 }
samux 2:27a7e7f8d399 199
samux 2:27a7e7f8d399 200 void USBHAL::EP0read(void) {
samux 2:27a7e7f8d399 201 // Start an endpoint 0 read
samux 2:27a7e7f8d399 202
samux 2:27a7e7f8d399 203 // The USB ISR will call USBDevice_EP0out() when a packet has been read,
samux 2:27a7e7f8d399 204 // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
samux 2:27a7e7f8d399 205 // read the data.
samux 2:27a7e7f8d399 206
samux 2:27a7e7f8d399 207 ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
samux 2:27a7e7f8d399 208 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
samux 2:27a7e7f8d399 209 }
samux 2:27a7e7f8d399 210
samux 2:27a7e7f8d399 211 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
samux 2:27a7e7f8d399 212 // Complete an endpoint 0 read
samux 2:27a7e7f8d399 213 uint32_t bytesRead;
samux 2:27a7e7f8d399 214
samux 2:27a7e7f8d399 215 // Find how many bytes were read
samux 2:27a7e7f8d399 216 bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
samux 2:27a7e7f8d399 217
samux 2:27a7e7f8d399 218 // Copy data
samux 2:27a7e7f8d399 219 USBMemCopy(buffer, ct->out, bytesRead);
samux 2:27a7e7f8d399 220 return bytesRead;
samux 2:27a7e7f8d399 221 }
samux 2:27a7e7f8d399 222
samux 2:27a7e7f8d399 223 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
samux 2:27a7e7f8d399 224 // Start and endpoint 0 write
samux 2:27a7e7f8d399 225
samux 2:27a7e7f8d399 226 // The USB ISR will call USBDevice_EP0in() when the data has
samux 2:27a7e7f8d399 227 // been written, the USBDevice layer then calls
samux 2:27a7e7f8d399 228 // USBBusInterface_EP0getWriteResult() to complete the transaction.
samux 2:27a7e7f8d399 229
samux 2:27a7e7f8d399 230 // Copy data
samux 2:27a7e7f8d399 231 USBMemCopy(ct->in, buffer, size);
samux 2:27a7e7f8d399 232
samux 2:27a7e7f8d399 233 // Start transfer
samux 2:27a7e7f8d399 234 ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
samux 2:27a7e7f8d399 235 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
samux 2:27a7e7f8d399 236 }
samux 2:27a7e7f8d399 237
samux 2:27a7e7f8d399 238
samux 2:27a7e7f8d399 239 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
samux 2:27a7e7f8d399 240 uint8_t bf = 0;
samux 2:27a7e7f8d399 241
samux 2:27a7e7f8d399 242 //check which buffer must be filled
samux 2:27a7e7f8d399 243 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
samux 2:27a7e7f8d399 244 // Double buffered
samux 2:27a7e7f8d399 245 if (LPC_USB->EPINUSE & EP(endpoint)) {
samux 2:27a7e7f8d399 246 bf = 1;
samux 2:27a7e7f8d399 247 } else {
samux 2:27a7e7f8d399 248 bf = 0;
samux 2:27a7e7f8d399 249 }
samux 2:27a7e7f8d399 250 }
samux 2:27a7e7f8d399 251
samux 2:27a7e7f8d399 252 //Active the endpoint for reading
samux 2:27a7e7f8d399 253 ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
samux 2:27a7e7f8d399 254 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
samux 2:27a7e7f8d399 255 return EP_PENDING;
samux 2:27a7e7f8d399 256 }
samux 2:27a7e7f8d399 257
samux 2:27a7e7f8d399 258 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) {
samux 2:27a7e7f8d399 259
samux 2:27a7e7f8d399 260 uint8_t bf = 0;
samux 2:27a7e7f8d399 261
samux 2:27a7e7f8d399 262 if (!(epComplete & EP(endpoint)))
samux 2:27a7e7f8d399 263 return EP_PENDING;
samux 2:27a7e7f8d399 264 else {
samux 2:27a7e7f8d399 265 epComplete &= ~EP(endpoint);
samux 2:27a7e7f8d399 266
samux 2:27a7e7f8d399 267 //check which buffer has been filled
samux 2:27a7e7f8d399 268 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
samux 2:27a7e7f8d399 269 // Double buffered (here we read the previous buffer which was used)
samux 2:27a7e7f8d399 270 if (LPC_USB->EPINUSE & EP(endpoint)) {
samux 2:27a7e7f8d399 271 bf = 0;
samux 2:27a7e7f8d399 272 } else {
samux 2:27a7e7f8d399 273 bf = 1;
samux 2:27a7e7f8d399 274 }
samux 2:27a7e7f8d399 275 }
samux 2:27a7e7f8d399 276
samux 2:27a7e7f8d399 277 // Find how many bytes were read
samux 2:27a7e7f8d399 278 *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf]));
samux 2:27a7e7f8d399 279
samux 2:27a7e7f8d399 280 // Copy data
samux 2:27a7e7f8d399 281 USBMemCopy(data, ct->out, *bytesRead);
samux 2:27a7e7f8d399 282 return EP_COMPLETED;
samux 2:27a7e7f8d399 283 }
samux 2:27a7e7f8d399 284 }
samux 2:27a7e7f8d399 285
samux 2:27a7e7f8d399 286 void USBHAL::EP0getWriteResult(void) {
samux 2:27a7e7f8d399 287 // Complete an endpoint 0 write
samux 2:27a7e7f8d399 288
samux 2:27a7e7f8d399 289 // Nothing required for this target
samux 2:27a7e7f8d399 290 return;
samux 2:27a7e7f8d399 291 }
samux 2:27a7e7f8d399 292
samux 2:27a7e7f8d399 293 void USBHAL::EP0stall(void) {
samux 2:27a7e7f8d399 294 ep[0].in[0] = CMDSTS_S;
samux 2:27a7e7f8d399 295 ep[0].out[0] = CMDSTS_S;
samux 2:27a7e7f8d399 296 }
samux 2:27a7e7f8d399 297
samux 2:27a7e7f8d399 298 void USBHAL::setAddress(uint8_t address) {
samux 2:27a7e7f8d399 299 devCmdStat &= ~DEV_ADDR_MASK;
samux 2:27a7e7f8d399 300 devCmdStat |= DEV_ADDR(address);
samux 2:27a7e7f8d399 301 LPC_USB->DEVCMDSTAT = devCmdStat;
samux 2:27a7e7f8d399 302 }
samux 2:27a7e7f8d399 303
samux 2:27a7e7f8d399 304 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
samux 2:27a7e7f8d399 305 uint32_t flags = 0;
samux 2:27a7e7f8d399 306 uint32_t bf;
samux 2:27a7e7f8d399 307
samux 2:27a7e7f8d399 308 // Validate parameters
samux 2:27a7e7f8d399 309 if (data == NULL) {
samux 2:27a7e7f8d399 310 return EP_INVALID;
samux 2:27a7e7f8d399 311 }
samux 2:27a7e7f8d399 312
samux 2:27a7e7f8d399 313 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
samux 2:27a7e7f8d399 314 return EP_INVALID;
samux 2:27a7e7f8d399 315 }
samux 2:27a7e7f8d399 316
samux 2:27a7e7f8d399 317 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
samux 2:27a7e7f8d399 318 return EP_INVALID;
samux 2:27a7e7f8d399 319 }
samux 2:27a7e7f8d399 320
samux 2:27a7e7f8d399 321 if (size > endpointState[endpoint].maxPacket) {
samux 2:27a7e7f8d399 322 return EP_INVALID;
samux 2:27a7e7f8d399 323 }
samux 2:27a7e7f8d399 324
samux 2:27a7e7f8d399 325 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
samux 2:27a7e7f8d399 326 // Double buffered
samux 2:27a7e7f8d399 327 if (LPC_USB->EPINUSE & EP(endpoint)) {
samux 2:27a7e7f8d399 328 bf = 1;
samux 2:27a7e7f8d399 329 } else {
samux 2:27a7e7f8d399 330 bf = 0;
samux 2:27a7e7f8d399 331 }
samux 2:27a7e7f8d399 332 } else {
samux 2:27a7e7f8d399 333 // Single buffered
samux 2:27a7e7f8d399 334 bf = 0;
samux 2:27a7e7f8d399 335 }
samux 2:27a7e7f8d399 336
samux 2:27a7e7f8d399 337 // Check if already active
samux 2:27a7e7f8d399 338 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
samux 2:27a7e7f8d399 339 return EP_INVALID;
samux 2:27a7e7f8d399 340 }
samux 2:27a7e7f8d399 341
samux 2:27a7e7f8d399 342 // Check if stalled
samux 2:27a7e7f8d399 343 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
samux 2:27a7e7f8d399 344 return EP_STALLED;
samux 2:27a7e7f8d399 345 }
samux 2:27a7e7f8d399 346
samux 2:27a7e7f8d399 347 // Copy data to USB RAM
samux 2:27a7e7f8d399 348 USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
samux 2:27a7e7f8d399 349
samux 2:27a7e7f8d399 350 // Add options
samux 2:27a7e7f8d399 351 if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) {
samux 2:27a7e7f8d399 352 flags |= CMDSTS_RF;
samux 2:27a7e7f8d399 353 }
samux 2:27a7e7f8d399 354
samux 2:27a7e7f8d399 355 if (endpointState[endpoint].options & ISOCHRONOUS) {
samux 2:27a7e7f8d399 356 flags |= CMDSTS_T;
samux 2:27a7e7f8d399 357 }
samux 2:27a7e7f8d399 358
samux 2:27a7e7f8d399 359 // Add transfer
samux 2:27a7e7f8d399 360 ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
samux 2:27a7e7f8d399 361 endpointState[endpoint].buffer[bf]) \
samux 2:27a7e7f8d399 362 | CMDSTS_NBYTES(size) | CMDSTS_A | flags;
samux 2:27a7e7f8d399 363
samux 2:27a7e7f8d399 364 return EP_PENDING;
samux 2:27a7e7f8d399 365 }
samux 2:27a7e7f8d399 366
samux 2:27a7e7f8d399 367 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
samux 2:27a7e7f8d399 368 uint32_t bf;
samux 2:27a7e7f8d399 369 // Validate parameters
samux 2:27a7e7f8d399 370
samux 2:27a7e7f8d399 371 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
samux 2:27a7e7f8d399 372 return EP_INVALID;
samux 2:27a7e7f8d399 373 }
samux 2:27a7e7f8d399 374
samux 2:27a7e7f8d399 375 if (OUT_EP(endpoint)) {
samux 2:27a7e7f8d399 376 return EP_INVALID;
samux 2:27a7e7f8d399 377 }
samux 2:27a7e7f8d399 378
samux 2:27a7e7f8d399 379 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
samux 2:27a7e7f8d399 380 // Double buffered // TODO: FIX THIS
samux 2:27a7e7f8d399 381 if (LPC_USB->EPINUSE & EP(endpoint)) {
samux 2:27a7e7f8d399 382 bf = 1;
samux 2:27a7e7f8d399 383 } else {
samux 2:27a7e7f8d399 384 bf = 0;
samux 2:27a7e7f8d399 385 }
samux 2:27a7e7f8d399 386 } else {
samux 2:27a7e7f8d399 387 // Single buffered
samux 2:27a7e7f8d399 388 bf = 0;
samux 2:27a7e7f8d399 389 }
samux 2:27a7e7f8d399 390
samux 2:27a7e7f8d399 391 // Check if endpoint still active
samux 2:27a7e7f8d399 392 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
samux 2:27a7e7f8d399 393 return EP_PENDING;
samux 2:27a7e7f8d399 394 }
samux 2:27a7e7f8d399 395
samux 2:27a7e7f8d399 396 // Check if stalled
samux 2:27a7e7f8d399 397 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
samux 2:27a7e7f8d399 398 return EP_STALLED;
samux 2:27a7e7f8d399 399 }
samux 2:27a7e7f8d399 400
samux 2:27a7e7f8d399 401 return EP_COMPLETED;
samux 2:27a7e7f8d399 402 }
samux 2:27a7e7f8d399 403
samux 2:27a7e7f8d399 404 void USBHAL::stallEndpoint(uint8_t endpoint) {
samux 2:27a7e7f8d399 405
samux 2:27a7e7f8d399 406 // TODO: should this clear active bit?
samux 2:27a7e7f8d399 407
samux 2:27a7e7f8d399 408 if (IN_EP(endpoint)) {
samux 2:27a7e7f8d399 409 ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
samux 2:27a7e7f8d399 410 ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
samux 2:27a7e7f8d399 411 } else {
samux 2:27a7e7f8d399 412 ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
samux 2:27a7e7f8d399 413 ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
samux 2:27a7e7f8d399 414 }
samux 2:27a7e7f8d399 415 }
samux 2:27a7e7f8d399 416
samux 2:27a7e7f8d399 417 void USBHAL::unstallEndpoint(uint8_t endpoint) {
samux 2:27a7e7f8d399 418 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
samux 2:27a7e7f8d399 419 // Double buffered
samux 2:27a7e7f8d399 420 if (IN_EP(endpoint)) {
samux 2:27a7e7f8d399 421 ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0
samux 2:27a7e7f8d399 422 ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0
samux 2:27a7e7f8d399 423
samux 2:27a7e7f8d399 424 if (LPC_USB->EPINUSE & EP(endpoint)) {
samux 2:27a7e7f8d399 425 ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
samux 2:27a7e7f8d399 426 } else {
samux 2:27a7e7f8d399 427 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
samux 2:27a7e7f8d399 428 }
samux 2:27a7e7f8d399 429 } else {
samux 2:27a7e7f8d399 430 ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0
samux 2:27a7e7f8d399 431 ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0
samux 2:27a7e7f8d399 432
samux 2:27a7e7f8d399 433 if (LPC_USB->EPINUSE & EP(endpoint)) {
samux 2:27a7e7f8d399 434 ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S =0, TR=1, TV = 0
samux 2:27a7e7f8d399 435 } else {
samux 2:27a7e7f8d399 436 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S =0, TR=1, TV = 0
samux 2:27a7e7f8d399 437 }
samux 2:27a7e7f8d399 438 }
samux 2:27a7e7f8d399 439 } else {
samux 2:27a7e7f8d399 440 // Single buffered
samux 2:27a7e7f8d399 441 if (IN_EP(endpoint)) {
samux 2:27a7e7f8d399 442 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
samux 2:27a7e7f8d399 443 } else {
samux 2:27a7e7f8d399 444 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S=0, TR=1, TV = 0
samux 2:27a7e7f8d399 445 }
samux 2:27a7e7f8d399 446 }
samux 2:27a7e7f8d399 447 }
samux 2:27a7e7f8d399 448
samux 2:27a7e7f8d399 449 bool USBHAL::getEndpointStallState(unsigned char endpoint) {
samux 2:27a7e7f8d399 450 if (IN_EP(endpoint)) {
samux 2:27a7e7f8d399 451 if (LPC_USB->EPINUSE & EP(endpoint)) {
samux 2:27a7e7f8d399 452 if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) {
samux 2:27a7e7f8d399 453 return true;
samux 2:27a7e7f8d399 454 }
samux 2:27a7e7f8d399 455 } else {
samux 2:27a7e7f8d399 456 if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) {
samux 2:27a7e7f8d399 457 return true;
samux 2:27a7e7f8d399 458 }
samux 2:27a7e7f8d399 459 }
samux 2:27a7e7f8d399 460 } else {
samux 2:27a7e7f8d399 461 if (LPC_USB->EPINUSE & EP(endpoint)) {
samux 2:27a7e7f8d399 462 if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) {
samux 2:27a7e7f8d399 463 return true;
samux 2:27a7e7f8d399 464 }
samux 2:27a7e7f8d399 465 } else {
samux 2:27a7e7f8d399 466 if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) {
samux 2:27a7e7f8d399 467 return true;
samux 2:27a7e7f8d399 468 }
samux 2:27a7e7f8d399 469 }
samux 2:27a7e7f8d399 470 }
samux 2:27a7e7f8d399 471
samux 2:27a7e7f8d399 472 return false;
samux 2:27a7e7f8d399 473 }
samux 2:27a7e7f8d399 474
samux 2:27a7e7f8d399 475 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) {
samux 2:27a7e7f8d399 476 uint32_t tmpEpRamPtr;
samux 2:27a7e7f8d399 477
samux 2:27a7e7f8d399 478 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
samux 2:27a7e7f8d399 479 return false;
samux 2:27a7e7f8d399 480 }
samux 2:27a7e7f8d399 481
samux 2:27a7e7f8d399 482 // Not applicable to the control endpoints
samux 2:27a7e7f8d399 483 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
samux 2:27a7e7f8d399 484 return false;
samux 2:27a7e7f8d399 485 }
samux 2:27a7e7f8d399 486
samux 2:27a7e7f8d399 487 // Allocate buffers in USB RAM
samux 2:27a7e7f8d399 488 tmpEpRamPtr = epRamPtr;
samux 2:27a7e7f8d399 489
samux 2:27a7e7f8d399 490 // Must be 64 byte aligned
samux 2:27a7e7f8d399 491 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
samux 2:27a7e7f8d399 492
samux 2:27a7e7f8d399 493 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
samux 2:27a7e7f8d399 494 // Out of memory
samux 2:27a7e7f8d399 495 return false;
samux 2:27a7e7f8d399 496 }
samux 2:27a7e7f8d399 497
samux 2:27a7e7f8d399 498 // Allocate first buffer
samux 2:27a7e7f8d399 499 endpointState[endpoint].buffer[0] = tmpEpRamPtr;
samux 2:27a7e7f8d399 500 tmpEpRamPtr += maxPacket;
samux 2:27a7e7f8d399 501
samux 2:27a7e7f8d399 502 if (!(options & SINGLE_BUFFERED)) {
samux 2:27a7e7f8d399 503 // Must be 64 byte aligned
samux 2:27a7e7f8d399 504 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
samux 2:27a7e7f8d399 505
samux 2:27a7e7f8d399 506 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
samux 2:27a7e7f8d399 507 // Out of memory
samux 2:27a7e7f8d399 508 return false;
samux 2:27a7e7f8d399 509 }
samux 2:27a7e7f8d399 510
samux 2:27a7e7f8d399 511 // Allocate second buffer
samux 2:27a7e7f8d399 512 endpointState[endpoint].buffer[1] = tmpEpRamPtr;
samux 2:27a7e7f8d399 513 tmpEpRamPtr += maxPacket;
samux 2:27a7e7f8d399 514 }
samux 2:27a7e7f8d399 515
samux 2:27a7e7f8d399 516 // Commit to this USB RAM allocation
samux 2:27a7e7f8d399 517 epRamPtr = tmpEpRamPtr;
samux 2:27a7e7f8d399 518
samux 2:27a7e7f8d399 519 // Remaining endpoint state values
samux 2:27a7e7f8d399 520 endpointState[endpoint].maxPacket = maxPacket;
samux 2:27a7e7f8d399 521 endpointState[endpoint].options = options;
samux 2:27a7e7f8d399 522
samux 2:27a7e7f8d399 523 // Enable double buffering if required
samux 2:27a7e7f8d399 524 if (options & SINGLE_BUFFERED) {
samux 2:27a7e7f8d399 525 LPC_USB->EPBUFCFG &= ~EP(endpoint);
samux 2:27a7e7f8d399 526 } else {
samux 2:27a7e7f8d399 527 // Double buffered
samux 2:27a7e7f8d399 528 LPC_USB->EPBUFCFG |= EP(endpoint);
samux 2:27a7e7f8d399 529 }
samux 2:27a7e7f8d399 530
samux 2:27a7e7f8d399 531 // Enable interrupt
samux 2:27a7e7f8d399 532 LPC_USB->INTEN |= EP(endpoint);
samux 2:27a7e7f8d399 533
samux 2:27a7e7f8d399 534 // Enable endpoint
samux 2:27a7e7f8d399 535 unstallEndpoint(endpoint);
samux 2:27a7e7f8d399 536 return true;
samux 2:27a7e7f8d399 537 }
samux 2:27a7e7f8d399 538
samux 2:27a7e7f8d399 539 void USBHAL::remoteWakeup(void) {
samux 2:27a7e7f8d399 540 // Clearing DSUS bit initiates a remote wakeup if the
samux 2:27a7e7f8d399 541 // device is currently enabled and suspended - otherwise
samux 2:27a7e7f8d399 542 // it has no effect.
samux 2:27a7e7f8d399 543 LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
samux 2:27a7e7f8d399 544 }
samux 2:27a7e7f8d399 545
samux 2:27a7e7f8d399 546
samux 2:27a7e7f8d399 547 static void disableEndpoints(void) {
samux 2:27a7e7f8d399 548 uint32_t logEp;
samux 2:27a7e7f8d399 549
samux 2:27a7e7f8d399 550 // Ref. Table 158 "When a bus reset is received, software
samux 2:27a7e7f8d399 551 // must set the disable bit of all endpoints to 1".
samux 2:27a7e7f8d399 552
samux 2:27a7e7f8d399 553 for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) {
samux 2:27a7e7f8d399 554 ep[logEp].out[0] = CMDSTS_D;
samux 2:27a7e7f8d399 555 ep[logEp].out[1] = CMDSTS_D;
samux 2:27a7e7f8d399 556 ep[logEp].in[0] = CMDSTS_D;
samux 2:27a7e7f8d399 557 ep[logEp].in[1] = CMDSTS_D;
samux 2:27a7e7f8d399 558 }
samux 2:27a7e7f8d399 559
samux 2:27a7e7f8d399 560 // Start of USB RAM for endpoints > 0
samux 2:27a7e7f8d399 561 epRamPtr = usbRamPtr;
samux 2:27a7e7f8d399 562 }
samux 2:27a7e7f8d399 563
samux 2:27a7e7f8d399 564
samux 2:27a7e7f8d399 565
samux 2:27a7e7f8d399 566 void USBHAL::_usbisr(void) {
samux 2:27a7e7f8d399 567 instance->usbisr();
samux 2:27a7e7f8d399 568 }
samux 2:27a7e7f8d399 569
samux 2:27a7e7f8d399 570
samux 2:27a7e7f8d399 571 void USBHAL::usbisr(void) {
samux 2:27a7e7f8d399 572 // Start of frame
samux 2:27a7e7f8d399 573 if (LPC_USB->INTSTAT & FRAME_INT) {
samux 2:27a7e7f8d399 574 // Clear SOF interrupt
samux 2:27a7e7f8d399 575 LPC_USB->INTSTAT = FRAME_INT;
samux 2:27a7e7f8d399 576
samux 2:27a7e7f8d399 577 // SOF event, read frame number
samux 2:27a7e7f8d399 578 SOF(FRAME_NR(LPC_USB->INFO));
samux 2:27a7e7f8d399 579 }
samux 2:27a7e7f8d399 580
samux 2:27a7e7f8d399 581 // Device state
samux 2:27a7e7f8d399 582 if (LPC_USB->INTSTAT & DEV_INT) {
samux 2:27a7e7f8d399 583 LPC_USB->INTSTAT = DEV_INT;
samux 2:27a7e7f8d399 584
samux 2:27a7e7f8d399 585 if (LPC_USB->DEVCMDSTAT & DCON_C) {
samux 2:27a7e7f8d399 586 // Connect status changed
samux 2:27a7e7f8d399 587 LPC_USB->DEVCMDSTAT = devCmdStat | DCON_C;
samux 2:27a7e7f8d399 588
samux 2:27a7e7f8d399 589 connectStateChanged((LPC_USB->DEVCMDSTAT & DCON) != 0);
samux 2:27a7e7f8d399 590 }
samux 2:27a7e7f8d399 591
samux 2:27a7e7f8d399 592 if (LPC_USB->DEVCMDSTAT & DSUS_C) {
samux 2:27a7e7f8d399 593 // Suspend status changed
samux 2:27a7e7f8d399 594 LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
samux 2:27a7e7f8d399 595
samux 2:27a7e7f8d399 596 suspendStateChanged((LPC_USB->DEVCMDSTAT & DSUS) != 0);
samux 2:27a7e7f8d399 597 }
samux 2:27a7e7f8d399 598
samux 2:27a7e7f8d399 599 if (LPC_USB->DEVCMDSTAT & DRES_C) {
samux 2:27a7e7f8d399 600 // Bus reset
samux 2:27a7e7f8d399 601 LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
samux 2:27a7e7f8d399 602
samux 2:27a7e7f8d399 603 // Disable endpoints > 0
samux 2:27a7e7f8d399 604 disableEndpoints();
samux 2:27a7e7f8d399 605
samux 2:27a7e7f8d399 606 // Bus reset event
samux 2:27a7e7f8d399 607 busReset();
samux 2:27a7e7f8d399 608 }
samux 2:27a7e7f8d399 609 }
samux 2:27a7e7f8d399 610
samux 2:27a7e7f8d399 611 // Endpoint 0
samux 2:27a7e7f8d399 612 if (LPC_USB->INTSTAT & EP(EP0OUT)) {
samux 2:27a7e7f8d399 613 // Clear EP0OUT/SETUP interrupt
samux 2:27a7e7f8d399 614 LPC_USB->INTSTAT = EP(EP0OUT);
samux 2:27a7e7f8d399 615
samux 2:27a7e7f8d399 616 // Check if SETUP
samux 2:27a7e7f8d399 617 if (LPC_USB->DEVCMDSTAT & SETUP) {
samux 2:27a7e7f8d399 618 // Clear Active and Stall bits for EP0
samux 2:27a7e7f8d399 619 // Documentation does not make it clear if we must use the
samux 2:27a7e7f8d399 620 // EPSKIP register to achieve this, Fig. 16 and NXP reference
samux 2:27a7e7f8d399 621 // code suggests we can just clear the Active bits - check with
samux 2:27a7e7f8d399 622 // NXP to be sure.
samux 2:27a7e7f8d399 623 ep[0].in[0] = 0;
samux 2:27a7e7f8d399 624 ep[0].out[0] = 0;
samux 2:27a7e7f8d399 625
samux 2:27a7e7f8d399 626 // Clear EP0IN interrupt
samux 2:27a7e7f8d399 627 LPC_USB->INTSTAT = EP(EP0IN);
samux 2:27a7e7f8d399 628
samux 2:27a7e7f8d399 629 // Clear SETUP (and INTONNAK_CI/O) in device status register
samux 2:27a7e7f8d399 630 LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
samux 2:27a7e7f8d399 631
samux 2:27a7e7f8d399 632 // EP0 SETUP event (SETUP data received)
samux 2:27a7e7f8d399 633 EP0setupCallback();
samux 2:27a7e7f8d399 634 } else {
samux 2:27a7e7f8d399 635 // EP0OUT ACK event (OUT data received)
samux 2:27a7e7f8d399 636 EP0out();
samux 2:27a7e7f8d399 637 }
samux 2:27a7e7f8d399 638 }
samux 2:27a7e7f8d399 639
samux 2:27a7e7f8d399 640 if (LPC_USB->INTSTAT & EP(EP0IN)) {
samux 2:27a7e7f8d399 641 // Clear EP0IN interrupt
samux 2:27a7e7f8d399 642 LPC_USB->INTSTAT = EP(EP0IN);
samux 2:27a7e7f8d399 643
samux 2:27a7e7f8d399 644 // EP0IN ACK event (IN data sent)
samux 2:27a7e7f8d399 645 EP0in();
samux 2:27a7e7f8d399 646 }
samux 2:27a7e7f8d399 647
samux 2:27a7e7f8d399 648 if (LPC_USB->INTSTAT & EP(EP1IN)) {
samux 2:27a7e7f8d399 649 // Clear EP1IN interrupt
samux 2:27a7e7f8d399 650 LPC_USB->INTSTAT = EP(EP1IN);
samux 2:27a7e7f8d399 651 epComplete |= EP(EP1IN);
samux 2:27a7e7f8d399 652 if(EP1_IN_callback())
samux 2:27a7e7f8d399 653 epComplete &= ~EP(EP1IN);
samux 2:27a7e7f8d399 654 }
samux 2:27a7e7f8d399 655
samux 2:27a7e7f8d399 656 if (LPC_USB->INTSTAT & EP(EP1OUT)) {
samux 2:27a7e7f8d399 657 // Clear EP1OUT interrupt
samux 2:27a7e7f8d399 658 LPC_USB->INTSTAT = EP(EP1OUT);
samux 2:27a7e7f8d399 659 epComplete |= EP(EP1OUT);
samux 2:27a7e7f8d399 660 if(EP1_OUT_callback())
samux 2:27a7e7f8d399 661 epComplete &= ~EP(EP1OUT);
samux 2:27a7e7f8d399 662 }
samux 2:27a7e7f8d399 663
samux 2:27a7e7f8d399 664 if (LPC_USB->INTSTAT & EP(EP2IN)) {
samux 2:27a7e7f8d399 665 // Clear EPBULK_IN interrupt
samux 2:27a7e7f8d399 666 LPC_USB->INTSTAT = EP(EP2IN);
samux 2:27a7e7f8d399 667 epComplete |= EP(EP2IN);
samux 2:27a7e7f8d399 668 if(EP2_IN_callback())
samux 2:27a7e7f8d399 669 epComplete &= ~EP(EP2IN);
samux 2:27a7e7f8d399 670 }
samux 2:27a7e7f8d399 671
samux 2:27a7e7f8d399 672 if (LPC_USB->INTSTAT & EP(EP2OUT)) {
samux 2:27a7e7f8d399 673 // Clear EPBULK_OUT interrupt
samux 2:27a7e7f8d399 674 LPC_USB->INTSTAT = EP(EP2OUT);
samux 2:27a7e7f8d399 675 epComplete |= EP(EP2OUT);
samux 2:27a7e7f8d399 676 //Call callback function. If true, clear epComplete
samux 2:27a7e7f8d399 677 if(EP2_OUT_callback())
samux 2:27a7e7f8d399 678 epComplete &= ~EP(EP2OUT);
samux 2:27a7e7f8d399 679 }
samux 2:27a7e7f8d399 680
samux 2:27a7e7f8d399 681 if (LPC_USB->INTSTAT & EP(EP3IN)) {
samux 2:27a7e7f8d399 682 // Clear EP3_IN interrupt
samux 2:27a7e7f8d399 683 LPC_USB->INTSTAT = EP(EP3IN);
samux 2:27a7e7f8d399 684 epComplete |= EP(EP3IN);
samux 2:27a7e7f8d399 685 if(EP3_IN_callback())
samux 2:27a7e7f8d399 686 epComplete &= ~EP(EP3IN);
samux 2:27a7e7f8d399 687 }
samux 2:27a7e7f8d399 688
samux 2:27a7e7f8d399 689 if (LPC_USB->INTSTAT & EP(EP3OUT)) {
samux 2:27a7e7f8d399 690 // Clear EP3_OUT interrupt
samux 2:27a7e7f8d399 691 LPC_USB->INTSTAT = EP(EP3OUT);
samux 2:27a7e7f8d399 692 epComplete |= EP(EP3OUT);
samux 2:27a7e7f8d399 693 //Call callback function. If true, clear epComplete
samux 2:27a7e7f8d399 694 if(EP3_OUT_callback())
samux 2:27a7e7f8d399 695 epComplete &= ~EP(EP3OUT);
samux 2:27a7e7f8d399 696 }
samux 2:27a7e7f8d399 697 }
samux 2:27a7e7f8d399 698
samux 2:27a7e7f8d399 699 #endif