Sensor reporting over USB CDC

Dependencies:   MAG3110 MMA8451Q SLCD- TSI USBDevice mbed

Committer:
wue
Date:
Wed Apr 16 12:20:12 2014 +0000
Revision:
0:7b58cdacf811
Sensor reporting over USB CDC

Who changed what in which revision?

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