Committer:
chris
Date:
Fri Oct 21 23:02:16 2011 +0000
Revision:
1:4d08e0ebf5dd
Parent:
0:e98d1c2b16c6

        

Who changed what in which revision?

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