USB Mouse (relative) example for mbed NXP LPC11U24 beta

Committer:
chris
Date:
Wed Nov 09 15:55:10 2011 +0000
Revision:
1:e089be2a6aa1
Parent:
0:163560051396
removed include for <math.h> that is already included by mbed.h

Who changed what in which revision?

UserRevisionLine numberNew contents of line
chris 0:163560051396 1 /* USBBusInterface_LPC17_LPC23.c */
chris 0:163560051396 2 /* USB Bus Interface for NXP LPC1768 and LPC2368 */
chris 0:163560051396 3 /* Copyright (c) 2011 ARM Limited. All rights reserved. */
chris 0:163560051396 4
chris 0:163560051396 5 #ifdef TARGET_LPC1768
chris 0:163560051396 6
chris 0:163560051396 7 #include "USBBusInterface.h"
chris 0:163560051396 8 #include "USBEvents.h"
chris 0:163560051396 9
chris 0:163560051396 10
chris 0:163560051396 11 /* Get endpoint direction */
chris 0:163560051396 12 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
chris 0:163560051396 13 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
chris 0:163560051396 14
chris 0:163560051396 15 /* Convert physical endpoint number to register bit */
chris 0:163560051396 16 #define EP(endpoint) (1UL<<endpoint)
chris 0:163560051396 17
chris 0:163560051396 18 /* Power Control for Peripherals register */
chris 0:163560051396 19 #define PCUSB (1UL<<31)
chris 0:163560051396 20
chris 0:163560051396 21 /* USB Clock Control register */
chris 0:163560051396 22 #define DEV_CLK_EN (1UL<<1)
chris 0:163560051396 23 #define AHB_CLK_EN (1UL<<4)
chris 0:163560051396 24
chris 0:163560051396 25 /* USB Clock Status register */
chris 0:163560051396 26 #define DEV_CLK_ON (1UL<<1)
chris 0:163560051396 27 #define AHB_CLK_ON (1UL<<4)
chris 0:163560051396 28
chris 0:163560051396 29 /* USB Device Interupt registers */
chris 0:163560051396 30 #define FRAME (1UL<<0)
chris 0:163560051396 31 #define EP_FAST (1UL<<1)
chris 0:163560051396 32 #define EP_SLOW (1UL<<2)
chris 0:163560051396 33 #define DEV_STAT (1UL<<3)
chris 0:163560051396 34 #define CCEMPTY (1UL<<4)
chris 0:163560051396 35 #define CDFULL (1UL<<5)
chris 0:163560051396 36 #define RxENDPKT (1UL<<6)
chris 0:163560051396 37 #define TxENDPKT (1UL<<7)
chris 0:163560051396 38 #define EP_RLZED (1UL<<8)
chris 0:163560051396 39 #define ERR_INT (1UL<<9)
chris 0:163560051396 40
chris 0:163560051396 41 /* USB Control register */
chris 0:163560051396 42 #define RD_EN (1<<0)
chris 0:163560051396 43 #define WR_EN (1<<1)
chris 0:163560051396 44 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
chris 0:163560051396 45
chris 0:163560051396 46 /* USB Receive Packet Length register */
chris 0:163560051396 47 #define DV (1UL<<10)
chris 0:163560051396 48 #define PKT_RDY (1UL<<11)
chris 0:163560051396 49 #define PKT_LNGTH_MASK (0x3ff)
chris 0:163560051396 50
chris 0:163560051396 51 /* Serial Interface Engine (SIE) */
chris 0:163560051396 52 #define SIE_WRITE (0x01)
chris 0:163560051396 53 #define SIE_READ (0x02)
chris 0:163560051396 54 #define SIE_COMMAND (0x05)
chris 0:163560051396 55 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
chris 0:163560051396 56
chris 0:163560051396 57 /* SIE Command codes */
chris 0:163560051396 58 #define SIE_CMD_SET_ADDRESS (0xD0)
chris 0:163560051396 59 #define SIE_CMD_CONFIGURE_DEVICE (0xD8)
chris 0:163560051396 60 #define SIE_CMD_SET_MODE (0xF3)
chris 0:163560051396 61 #define SIE_CMD_READ_FRAME_NUMBER (0xF5)
chris 0:163560051396 62 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
chris 0:163560051396 63 #define SIE_CMD_SET_DEVICE_STATUS (0xFE)
chris 0:163560051396 64 #define SIE_CMD_GET_DEVICE_STATUS (0xFE)
chris 0:163560051396 65 #define SIE_CMD_GET_ERROR_CODE (0xFF)
chris 0:163560051396 66 #define SIE_CMD_READ_ERROR_STATUS (0xFB)
chris 0:163560051396 67
chris 0:163560051396 68 #define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint)
chris 0:163560051396 69 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
chris 0:163560051396 70 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint)
chris 0:163560051396 71
chris 0:163560051396 72 #define SIE_CMD_CLEAR_BUFFER (0xF2)
chris 0:163560051396 73 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
chris 0:163560051396 74
chris 0:163560051396 75 /* SIE Device Status register */
chris 0:163560051396 76 #define SIE_DS_CON (1<<0)
chris 0:163560051396 77 #define SIE_DS_CON_CH (1<<1)
chris 0:163560051396 78 #define SIE_DS_SUS (1<<2)
chris 0:163560051396 79 #define SIE_DS_SUS_CH (1<<3)
chris 0:163560051396 80 #define SIE_DS_RST (1<<4)
chris 0:163560051396 81
chris 0:163560051396 82 /* SIE Device Set Address register */
chris 0:163560051396 83 #define SIE_DSA_DEV_EN (1<<7)
chris 0:163560051396 84
chris 0:163560051396 85 /* SIE Configue Device register */
chris 0:163560051396 86 #define SIE_CONF_DEVICE (1<<0)
chris 0:163560051396 87
chris 0:163560051396 88 /* Select Endpoint register */
chris 0:163560051396 89 #define SIE_SE_FE (1<<0)
chris 0:163560051396 90 #define SIE_SE_ST (1<<1)
chris 0:163560051396 91 #define SIE_SE_STP (1<<2)
chris 0:163560051396 92 #define SIE_SE_PO (1<<3)
chris 0:163560051396 93 #define SIE_SE_EPN (1<<4)
chris 0:163560051396 94 #define SIE_SE_B_1_FULL (1<<5)
chris 0:163560051396 95 #define SIE_SE_B_2_FULL (1<<6)
chris 0:163560051396 96
chris 0:163560051396 97 /* Set Endpoint Status command */
chris 0:163560051396 98 #define SIE_SES_ST (1<<0)
chris 0:163560051396 99 #define SIE_SES_DA (1<<5)
chris 0:163560051396 100 #define SIE_SES_RF_MO (1<<6)
chris 0:163560051396 101 #define SIE_SES_CND_ST (1<<7)
chris 0:163560051396 102
chris 0:163560051396 103 static uint32_t endpointStallState;
chris 0:163560051396 104
chris 0:163560051396 105 static int epComplete = 0;
chris 0:163560051396 106 /*
chris 0:163560051396 107 * Serial Interface Engine commands
chris 0:163560051396 108 */
chris 0:163560051396 109
chris 0:163560051396 110 static void SIECommand(uint32_t command)
chris 0:163560051396 111 {
chris 0:163560051396 112 /* The command phase of a SIE transaction */
chris 0:163560051396 113 LPC_USB->USBDevIntClr = CCEMPTY;
chris 0:163560051396 114 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
chris 0:163560051396 115 while (!(LPC_USB->USBDevIntSt & CCEMPTY));
chris 0:163560051396 116 }
chris 0:163560051396 117
chris 0:163560051396 118 static void SIEWriteData(uint8_t data)
chris 0:163560051396 119 {
chris 0:163560051396 120 /* The data write phase of a SIE transaction */
chris 0:163560051396 121 LPC_USB->USBDevIntClr = CCEMPTY;
chris 0:163560051396 122 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
chris 0:163560051396 123 while (!(LPC_USB->USBDevIntSt & CCEMPTY));
chris 0:163560051396 124 }
chris 0:163560051396 125
chris 0:163560051396 126 static uint8_t SIEReadData(uint32_t command)
chris 0:163560051396 127 {
chris 0:163560051396 128 /* The data read phase of a SIE transaction */
chris 0:163560051396 129 LPC_USB->USBDevIntClr = CDFULL;
chris 0:163560051396 130 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
chris 0:163560051396 131 while (!(LPC_USB->USBDevIntSt & CDFULL));
chris 0:163560051396 132 return (uint8_t)LPC_USB->USBCmdData;
chris 0:163560051396 133 }
chris 0:163560051396 134
chris 0:163560051396 135 static void SIEsetDeviceStatus(uint8_t status)
chris 0:163560051396 136 {
chris 0:163560051396 137 /* Write SIE device status register */
chris 0:163560051396 138 SIECommand(SIE_CMD_SET_DEVICE_STATUS);
chris 0:163560051396 139 SIEWriteData(status);
chris 0:163560051396 140 }
chris 0:163560051396 141
chris 0:163560051396 142 static uint8_t SIEgetDeviceStatus(void)
chris 0:163560051396 143 {
chris 0:163560051396 144 /* Read SIE device status register */
chris 0:163560051396 145 SIECommand(SIE_CMD_GET_DEVICE_STATUS);
chris 0:163560051396 146 return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
chris 0:163560051396 147 }
chris 0:163560051396 148
chris 0:163560051396 149 void SIEsetAddress(uint8_t address)
chris 0:163560051396 150 {
chris 0:163560051396 151 /* Write SIE device address register */
chris 0:163560051396 152 SIECommand(SIE_CMD_SET_ADDRESS);
chris 0:163560051396 153 SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
chris 0:163560051396 154 }
chris 0:163560051396 155
chris 0:163560051396 156 static uint8_t SIEselectEndpoint(uint8_t endpoint)
chris 0:163560051396 157 {
chris 0:163560051396 158 /* SIE select endpoint command */
chris 0:163560051396 159 SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
chris 0:163560051396 160 return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
chris 0:163560051396 161 }
chris 0:163560051396 162
chris 0:163560051396 163 static uint8_t SIEclearBuffer(void)
chris 0:163560051396 164 {
chris 0:163560051396 165 /* SIE clear buffer command */
chris 0:163560051396 166 SIECommand(SIE_CMD_CLEAR_BUFFER);
chris 0:163560051396 167 return SIEReadData(SIE_CMD_CLEAR_BUFFER);
chris 0:163560051396 168 }
chris 0:163560051396 169
chris 0:163560051396 170 static void SIEvalidateBuffer(void)
chris 0:163560051396 171 {
chris 0:163560051396 172 /* SIE validate buffer command */
chris 0:163560051396 173 SIECommand(SIE_CMD_VALIDATE_BUFFER);
chris 0:163560051396 174 }
chris 0:163560051396 175
chris 0:163560051396 176 static void SIEsetEndpointStatus(uint8_t endpoint, uint8_t status)
chris 0:163560051396 177 {
chris 0:163560051396 178 /* SIE set endpoint status command */
chris 0:163560051396 179 SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
chris 0:163560051396 180 SIEWriteData(status);
chris 0:163560051396 181 }
chris 0:163560051396 182
chris 0:163560051396 183 static uint16_t SIEgetFrameNumber(void) __attribute__ ((unused));
chris 0:163560051396 184 static uint16_t SIEgetFrameNumber(void)
chris 0:163560051396 185 {
chris 0:163560051396 186 /* Read current frame number */
chris 0:163560051396 187 uint16_t lowByte;
chris 0:163560051396 188 uint16_t highByte;
chris 0:163560051396 189
chris 0:163560051396 190 SIECommand(SIE_CMD_READ_FRAME_NUMBER);
chris 0:163560051396 191 lowByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
chris 0:163560051396 192 highByte = SIEReadData(SIE_CMD_READ_FRAME_NUMBER);
chris 0:163560051396 193
chris 0:163560051396 194 return (highByte << 8) | lowByte;
chris 0:163560051396 195 }
chris 0:163560051396 196
chris 0:163560051396 197 static void SIEconfigureDevice(void)
chris 0:163560051396 198 {
chris 0:163560051396 199 /* SIE Configure device command */
chris 0:163560051396 200 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
chris 0:163560051396 201 SIEWriteData(SIE_CONF_DEVICE);
chris 0:163560051396 202 }
chris 0:163560051396 203
chris 0:163560051396 204 static void SIEunconfigureDevice(void)
chris 0:163560051396 205 {
chris 0:163560051396 206 /* SIE Configure device command */
chris 0:163560051396 207 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
chris 0:163560051396 208 SIEWriteData(0);
chris 0:163560051396 209 }
chris 0:163560051396 210
chris 0:163560051396 211 static void SIEconnect(void)
chris 0:163560051396 212 {
chris 0:163560051396 213 /* Connect USB device */
chris 0:163560051396 214 uint8_t status;
chris 0:163560051396 215
chris 0:163560051396 216 status = SIEgetDeviceStatus();
chris 0:163560051396 217 SIEsetDeviceStatus(status | SIE_DS_CON);
chris 0:163560051396 218 }
chris 0:163560051396 219
chris 0:163560051396 220
chris 0:163560051396 221 static void SIEdisconnect(void)
chris 0:163560051396 222 {
chris 0:163560051396 223 /* Disconnect USB device */
chris 0:163560051396 224 uint8_t status;
chris 0:163560051396 225
chris 0:163560051396 226 status = SIEgetDeviceStatus();
chris 0:163560051396 227 SIEsetDeviceStatus(status & ~SIE_DS_CON);
chris 0:163560051396 228 }
chris 0:163560051396 229
chris 0:163560051396 230 /*
chris 0:163560051396 231 * Endpoint commands
chris 0:163560051396 232 */
chris 0:163560051396 233
chris 0:163560051396 234 static uint8_t selectEndpointClearInterrupt(uint8_t endpoint)
chris 0:163560051396 235 {
chris 0:163560051396 236 /* Implemented using using EP_INT_CLR. */
chris 0:163560051396 237 LPC_USB->USBEpIntClr = EP(endpoint);
chris 0:163560051396 238 while (!(LPC_USB->USBDevIntSt & CDFULL));
chris 0:163560051396 239 return (uint8_t)LPC_USB->USBCmdData;
chris 0:163560051396 240 }
chris 0:163560051396 241
chris 0:163560051396 242 static void stallEndpoint(uint8_t endpoint)
chris 0:163560051396 243 {
chris 0:163560051396 244 /* Stall an endpoint */
chris 0:163560051396 245 if ( (endpoint==EP0IN) || (endpoint==EP0OUT) )
chris 0:163560051396 246 {
chris 0:163560051396 247 /* Conditionally stall both control endpoints */
chris 0:163560051396 248 SIEsetEndpointStatus(EP0OUT, SIE_SES_CND_ST);
chris 0:163560051396 249 }
chris 0:163560051396 250 else
chris 0:163560051396 251 {
chris 0:163560051396 252 SIEsetEndpointStatus(endpoint, SIE_SES_ST);
chris 0:163560051396 253
chris 0:163560051396 254 /* Update stall state */
chris 0:163560051396 255 endpointStallState |= EP(endpoint);
chris 0:163560051396 256 }
chris 0:163560051396 257 }
chris 0:163560051396 258
chris 0:163560051396 259 static void unstallEndpoint(uint8_t endpoint)
chris 0:163560051396 260 {
chris 0:163560051396 261 /* Unstall an endpoint. The endpoint will also be reinitialised */
chris 0:163560051396 262 SIEsetEndpointStatus(endpoint, 0);
chris 0:163560051396 263
chris 0:163560051396 264 /* Update stall state */
chris 0:163560051396 265 endpointStallState &= ~EP(endpoint);
chris 0:163560051396 266 }
chris 0:163560051396 267
chris 0:163560051396 268 static bool getEndpointStallState(uint8_t endpoint)
chris 0:163560051396 269 {
chris 0:163560051396 270 /* Returns true if endpoint stalled */
chris 0:163560051396 271 return endpointStallState & EP(endpoint);
chris 0:163560051396 272 }
chris 0:163560051396 273
chris 0:163560051396 274 static void realiseEndpoint(uint8_t endpoint, uint32_t maxPacket)
chris 0:163560051396 275 {
chris 0:163560051396 276 /* Realise an endpoint */
chris 0:163560051396 277 LPC_USB->USBDevIntClr = EP_RLZED;
chris 0:163560051396 278 LPC_USB->USBReEp |= EP(endpoint);
chris 0:163560051396 279 LPC_USB->USBEpInd = endpoint;
chris 0:163560051396 280 LPC_USB->USBMaxPSize = maxPacket;
chris 0:163560051396 281
chris 0:163560051396 282 while (!(LPC_USB->USBDevIntSt & EP_RLZED));
chris 0:163560051396 283 LPC_USB->USBDevIntClr = EP_RLZED;
chris 0:163560051396 284
chris 0:163560051396 285 /* Clear stall state */
chris 0:163560051396 286 endpointStallState &= ~EP(endpoint);
chris 0:163560051396 287 }
chris 0:163560051396 288
chris 0:163560051396 289 static void enableEndpointEvent(uint8_t endpoint)
chris 0:163560051396 290 {
chris 0:163560051396 291 /* Enable an endpoint interrupt */
chris 0:163560051396 292 LPC_USB->USBEpIntEn |= EP(endpoint);
chris 0:163560051396 293 }
chris 0:163560051396 294
chris 0:163560051396 295 static void disableEndpointEvent(uint8_t endpoint) __attribute__ ((unused));
chris 0:163560051396 296 static void disableEndpointEvent(uint8_t endpoint)
chris 0:163560051396 297 {
chris 0:163560051396 298 /* Disable an endpoint interrupt */
chris 0:163560051396 299 LPC_USB->USBEpIntEn &= ~EP(endpoint);
chris 0:163560051396 300 }
chris 0:163560051396 301
chris 0:163560051396 302 static volatile uint32_t __attribute__((used)) dummyRead;
chris 0:163560051396 303
chris 0:163560051396 304 static uint32_t endpointRead(uint8_t endpoint, uint8_t *buffer)
chris 0:163560051396 305 {
chris 0:163560051396 306 /* Read from an OUT endpoint */
chris 0:163560051396 307 uint32_t size;
chris 0:163560051396 308 uint32_t i;
chris 0:163560051396 309 uint32_t data;
chris 0:163560051396 310 uint8_t offset;
chris 0:163560051396 311
chris 0:163560051396 312 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
chris 0:163560051396 313 while (!(LPC_USB->USBRxPLen & PKT_RDY));
chris 0:163560051396 314
chris 0:163560051396 315 size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
chris 0:163560051396 316
chris 0:163560051396 317 offset = 0;
chris 0:163560051396 318
chris 0:163560051396 319 if (size > 0)
chris 0:163560051396 320 {
chris 0:163560051396 321 for (i=0; i<size; i++)
chris 0:163560051396 322 {
chris 0:163560051396 323 if (offset==0)
chris 0:163560051396 324 {
chris 0:163560051396 325 /* Fetch up to four bytes of data as a word */
chris 0:163560051396 326 data = LPC_USB->USBRxData;
chris 0:163560051396 327 }
chris 0:163560051396 328
chris 0:163560051396 329 /* extract a byte */
chris 0:163560051396 330 *buffer++ = data>>offset;
chris 0:163560051396 331
chris 0:163560051396 332 /* move on to the next byte */
chris 0:163560051396 333 offset = (offset + 8) % 32;
chris 0:163560051396 334 }
chris 0:163560051396 335 }
chris 0:163560051396 336 else
chris 0:163560051396 337 {
chris 0:163560051396 338 dummyRead = LPC_USB->USBRxData;
chris 0:163560051396 339 }
chris 0:163560051396 340
chris 0:163560051396 341 SIEselectEndpoint(endpoint);
chris 0:163560051396 342 SIEclearBuffer();
chris 0:163560051396 343 return size;
chris 0:163560051396 344 }
chris 0:163560051396 345
chris 0:163560051396 346 static void endpointWrite(uint8_t endpoint, uint8_t *buffer, uint32_t size)
chris 0:163560051396 347 {
chris 0:163560051396 348 /* Write to an IN endpoint */
chris 0:163560051396 349 uint32_t temp, data;
chris 0:163560051396 350 uint8_t offset;
chris 0:163560051396 351
chris 0:163560051396 352 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
chris 0:163560051396 353
chris 0:163560051396 354 LPC_USB->USBTxPLen = size;
chris 0:163560051396 355 offset = 0;
chris 0:163560051396 356 data = 0;
chris 0:163560051396 357
chris 0:163560051396 358 if (size>0)
chris 0:163560051396 359 {
chris 0:163560051396 360 do {
chris 0:163560051396 361 /* Fetch next data byte into a word-sized temporary variable */
chris 0:163560051396 362 temp = *buffer++;
chris 0:163560051396 363
chris 0:163560051396 364 /* Add to current data word */
chris 0:163560051396 365 temp = temp << offset;
chris 0:163560051396 366 data = data | temp;
chris 0:163560051396 367
chris 0:163560051396 368 /* move on to the next byte */
chris 0:163560051396 369 offset = (offset + 8) % 32;
chris 0:163560051396 370 size--;
chris 0:163560051396 371
chris 0:163560051396 372 if ((offset==0) || (size==0))
chris 0:163560051396 373 {
chris 0:163560051396 374 /* Write the word to the endpoint */
chris 0:163560051396 375 LPC_USB->USBTxData = data;
chris 0:163560051396 376 data = 0;
chris 0:163560051396 377 }
chris 0:163560051396 378 } while (size>0);
chris 0:163560051396 379 }
chris 0:163560051396 380 else
chris 0:163560051396 381 {
chris 0:163560051396 382 LPC_USB->USBTxData = 0;
chris 0:163560051396 383 }
chris 0:163560051396 384
chris 0:163560051396 385 /* Clear WR_EN to cover zero length packet case */
chris 0:163560051396 386 LPC_USB->USBCtrl=0;
chris 0:163560051396 387
chris 0:163560051396 388 SIEselectEndpoint(endpoint);
chris 0:163560051396 389 SIEvalidateBuffer();
chris 0:163560051396 390 }
chris 0:163560051396 391
chris 0:163560051396 392 /*
chris 0:163560051396 393 * USBBusInterface API
chris 0:163560051396 394 */
chris 0:163560051396 395
chris 0:163560051396 396 bool USBBusInterface_init(void)
chris 0:163560051396 397 {
chris 0:163560051396 398 /* Disable IRQ */
chris 0:163560051396 399 NVIC_DisableIRQ(USB_IRQn);
chris 0:163560051396 400
chris 0:163560051396 401 /* Enable power to USB device controller */
chris 0:163560051396 402 LPC_SC->PCONP |= PCUSB;
chris 0:163560051396 403
chris 0:163560051396 404 /* Enable USB clocks */
chris 0:163560051396 405 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
chris 0:163560051396 406 while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
chris 0:163560051396 407
chris 0:163560051396 408 /* Configure pins P0.29 and P0.30 to be USB D+ and USB D- */
chris 0:163560051396 409 LPC_PINCON->PINSEL1 &= 0xc3ffffff;
chris 0:163560051396 410 LPC_PINCON->PINSEL1 |= 0x14000000;
chris 0:163560051396 411
chris 0:163560051396 412 /* Disconnect USB device */
chris 0:163560051396 413 SIEdisconnect();
chris 0:163560051396 414
chris 0:163560051396 415 /* Configure pin P2.9 to be Connect */
chris 0:163560051396 416 LPC_PINCON->PINSEL4 &= 0xfffcffff;
chris 0:163560051396 417 LPC_PINCON->PINSEL4 |= 0x00040000;
chris 0:163560051396 418
chris 0:163560051396 419 /* Connect must be low for at least 2.5uS */
chris 0:163560051396 420 wait(0.3);
chris 0:163560051396 421
chris 0:163560051396 422 /* Set the maximum packet size for the control endpoints */
chris 0:163560051396 423 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0);
chris 0:163560051396 424 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0);
chris 0:163560051396 425
chris 0:163560051396 426 /* Attach IRQ */
chris 0:163560051396 427 NVIC_EnableIRQ(USB_IRQn);
chris 0:163560051396 428
chris 0:163560051396 429 /* Enable interrupts for device events and EP0 */
chris 0:163560051396 430 LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT;
chris 0:163560051396 431 enableEndpointEvent(EP0IN);
chris 0:163560051396 432 enableEndpointEvent(EP0OUT);
chris 0:163560051396 433 return true;
chris 0:163560051396 434 }
chris 0:163560051396 435
chris 0:163560051396 436 void USBBusInterface_uninit(void)
chris 0:163560051396 437 {
chris 0:163560051396 438 /* Ensure device disconnected */
chris 0:163560051396 439 SIEdisconnect();
chris 0:163560051396 440
chris 0:163560051396 441 /* Disable USB interrupts */
chris 0:163560051396 442 NVIC_DisableIRQ(USB_IRQn);
chris 0:163560051396 443 }
chris 0:163560051396 444
chris 0:163560051396 445 void USBBusInterface_connect(void)
chris 0:163560051396 446 {
chris 0:163560051396 447 /* Connect USB device */
chris 0:163560051396 448 SIEconnect();
chris 0:163560051396 449 }
chris 0:163560051396 450
chris 0:163560051396 451 void USBBusInterface_disconnect(void)
chris 0:163560051396 452 {
chris 0:163560051396 453 /* Disconnect USB device */
chris 0:163560051396 454 SIEdisconnect();
chris 0:163560051396 455 }
chris 0:163560051396 456
chris 0:163560051396 457 void USBBusInterface_configureDevice(void)
chris 0:163560051396 458 {
chris 0:163560051396 459 SIEconfigureDevice();
chris 0:163560051396 460 }
chris 0:163560051396 461
chris 0:163560051396 462 void USBBusInterface_unconfigureDevice(void)
chris 0:163560051396 463 {
chris 0:163560051396 464 SIEunconfigureDevice();
chris 0:163560051396 465 }
chris 0:163560051396 466
chris 0:163560051396 467 void USBBusInterface_setAddress(uint8_t address)
chris 0:163560051396 468 {
chris 0:163560051396 469 SIEsetAddress(address);
chris 0:163560051396 470 }
chris 0:163560051396 471
chris 0:163560051396 472 void USBBusInterface_EP0setup(uint8_t *buffer)
chris 0:163560051396 473 {
chris 0:163560051396 474 endpointRead(EP0OUT, buffer);
chris 0:163560051396 475 }
chris 0:163560051396 476
chris 0:163560051396 477 void USBBusInterface_EP0read(void)
chris 0:163560051396 478 {
chris 0:163560051396 479 /* Not required */
chris 0:163560051396 480 }
chris 0:163560051396 481
chris 0:163560051396 482 uint32_t USBBusInterface_EP0getReadResult(uint8_t *buffer)
chris 0:163560051396 483 {
chris 0:163560051396 484 return endpointRead(EP0OUT, buffer);
chris 0:163560051396 485 }
chris 0:163560051396 486
chris 0:163560051396 487 void USBBusInterface_EP0write(uint8_t *buffer, uint32_t size)
chris 0:163560051396 488 {
chris 0:163560051396 489 endpointWrite(EP0IN, buffer, size);
chris 0:163560051396 490 }
chris 0:163560051396 491
chris 0:163560051396 492 void USBBusInterface_EP0getWriteResult(void)
chris 0:163560051396 493 {
chris 0:163560051396 494 /* Not required */
chris 0:163560051396 495 }
chris 0:163560051396 496
chris 0:163560051396 497 void USBBusInterface_EP0stall(void)
chris 0:163560051396 498 {
chris 0:163560051396 499 /* This will stall both control endpoints */
chris 0:163560051396 500 stallEndpoint(EP0OUT);
chris 0:163560051396 501 }
chris 0:163560051396 502
chris 0:163560051396 503 EP_STATUS USBBusInterface_endpointRead(uint8_t endpoint, uint8_t *data, uint32_t maximumSize)
chris 0:163560051396 504 {
chris 0:163560051396 505 if (getEndpointStallState(endpoint))
chris 0:163560051396 506 {
chris 0:163560051396 507 return EP_STALLED;
chris 0:163560051396 508 }
chris 0:163560051396 509
chris 0:163560051396 510 return EP_PENDING;
chris 0:163560051396 511 }
chris 0:163560051396 512
chris 0:163560051396 513 EP_STATUS USBBusInterface_endpointReadResult(uint8_t endpoint, uint32_t *bytesRead)
chris 0:163560051396 514 {
chris 0:163560051396 515 return EP_PENDING;
chris 0:163560051396 516 }
chris 0:163560051396 517
chris 0:163560051396 518 EP_STATUS USBBusInterface_endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size)
chris 0:163560051396 519 {
chris 0:163560051396 520 if (getEndpointStallState(endpoint))
chris 0:163560051396 521 {
chris 0:163560051396 522 return EP_STALLED;
chris 0:163560051396 523 }
chris 0:163560051396 524
chris 0:163560051396 525 epComplete &= EP(endpoint);
chris 0:163560051396 526
chris 0:163560051396 527 endpointWrite(endpoint, data, size);
chris 0:163560051396 528 return EP_PENDING;
chris 0:163560051396 529 }
chris 0:163560051396 530
chris 0:163560051396 531 EP_STATUS USBBusInterface_endpointWriteResult(uint8_t endpoint)
chris 0:163560051396 532 {
chris 0:163560051396 533 if (epComplete & EP(endpoint))
chris 0:163560051396 534 {
chris 0:163560051396 535 epComplete &= ~EP(endpoint);
chris 0:163560051396 536 return EP_COMPLETED;
chris 0:163560051396 537 }
chris 0:163560051396 538
chris 0:163560051396 539 return EP_PENDING;
chris 0:163560051396 540 }
chris 0:163560051396 541
chris 0:163560051396 542 bool USBBusInterface_realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags)
chris 0:163560051396 543 {
chris 0:163560051396 544 realiseEndpoint(endpoint, maxPacket);
chris 0:163560051396 545 enableEndpointEvent(endpoint);
chris 0:163560051396 546 return true;
chris 0:163560051396 547 }
chris 0:163560051396 548
chris 0:163560051396 549 void USBBusInterface_stallEndpoint(uint8_t endpoint)
chris 0:163560051396 550 {
chris 0:163560051396 551 stallEndpoint(endpoint);
chris 0:163560051396 552 }
chris 0:163560051396 553
chris 0:163560051396 554 void USBBusInterface_unstallEndpoint(uint8_t endpoint)
chris 0:163560051396 555 {
chris 0:163560051396 556 unstallEndpoint(endpoint);
chris 0:163560051396 557 }
chris 0:163560051396 558
chris 0:163560051396 559 bool USBBusInterface_getEndpointStallState(uint8_t endpoint)
chris 0:163560051396 560 {
chris 0:163560051396 561 return getEndpointStallState(endpoint);
chris 0:163560051396 562 }
chris 0:163560051396 563
chris 0:163560051396 564 void USBBusInterface_remoteWakeup(void)
chris 0:163560051396 565 {
chris 0:163560051396 566 /* Remote wakeup */
chris 0:163560051396 567 uint8_t status;
chris 0:163560051396 568
chris 0:163560051396 569 /* Enable USB clocks */
chris 0:163560051396 570 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
chris 0:163560051396 571 while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
chris 0:163560051396 572
chris 0:163560051396 573 status = SIEgetDeviceStatus();
chris 0:163560051396 574 SIEsetDeviceStatus(status & ~SIE_DS_SUS);
chris 0:163560051396 575 }
chris 0:163560051396 576
chris 0:163560051396 577 /*
chris 0:163560051396 578 * USB interrupt handler
chris 0:163560051396 579 */
chris 0:163560051396 580
chris 0:163560051396 581 extern "C"
chris 0:163560051396 582 {
chris 0:163560051396 583 void USB_IRQHandler(void)
chris 0:163560051396 584 {
chris 0:163560051396 585 uint8_t devStat;
chris 0:163560051396 586
chris 0:163560051396 587 if (LPC_USB->USBDevIntSt & FRAME)
chris 0:163560051396 588 {
chris 0:163560051396 589 /* Start of frame event */
chris 0:163560051396 590 USBDevice_SOF(SIEgetFrameNumber());
chris 0:163560051396 591 /* Clear interrupt status flag */
chris 0:163560051396 592 LPC_USB->USBDevIntClr = FRAME;
chris 0:163560051396 593 }
chris 0:163560051396 594
chris 0:163560051396 595 if (LPC_USB->USBDevIntSt & DEV_STAT)
chris 0:163560051396 596 {
chris 0:163560051396 597 /* Device Status interrupt */
chris 0:163560051396 598 /* Must clear the interrupt status flag before reading the device status from the SIE */
chris 0:163560051396 599 LPC_USB->USBDevIntClr = DEV_STAT;
chris 0:163560051396 600
chris 0:163560051396 601 /* Read device status from SIE */
chris 0:163560051396 602 devStat = SIEgetDeviceStatus();
chris 0:163560051396 603
chris 0:163560051396 604 if (devStat & SIE_DS_RST)
chris 0:163560051396 605 {
chris 0:163560051396 606 /* Bus reset */
chris 0:163560051396 607 USBDevice_busReset();
chris 0:163560051396 608 }
chris 0:163560051396 609 }
chris 0:163560051396 610
chris 0:163560051396 611 if (LPC_USB->USBDevIntSt & EP_SLOW)
chris 0:163560051396 612 {
chris 0:163560051396 613 /* (Slow) Endpoint Interrupt */
chris 0:163560051396 614
chris 0:163560051396 615 /* Process each endpoint interrupt */
chris 0:163560051396 616 if (LPC_USB->USBEpIntSt & EP(EP0OUT))
chris 0:163560051396 617 {
chris 0:163560051396 618 if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP)
chris 0:163560051396 619 {
chris 0:163560051396 620 /* this is a setup packet */
chris 0:163560051396 621 USBDevice_EP0setup();
chris 0:163560051396 622 }
chris 0:163560051396 623 else
chris 0:163560051396 624 {
chris 0:163560051396 625 USBDevice_EP0out();
chris 0:163560051396 626 }
chris 0:163560051396 627 }
chris 0:163560051396 628
chris 0:163560051396 629 if (LPC_USB->USBEpIntSt & EP(EP0IN))
chris 0:163560051396 630 {
chris 0:163560051396 631 selectEndpointClearInterrupt(EP0IN);
chris 0:163560051396 632 USBDevice_EP0in();
chris 0:163560051396 633 }
chris 0:163560051396 634
chris 0:163560051396 635 /* TODO: This should cover all endpoints, not just EP1,2,3:*/
chris 0:163560051396 636 if (LPC_USB->USBEpIntSt & EP(EP1IN))
chris 0:163560051396 637 {
chris 0:163560051396 638 selectEndpointClearInterrupt(EP1IN);
chris 0:163560051396 639 epComplete |= EP(EP1IN);
chris 0:163560051396 640 }
chris 0:163560051396 641
chris 0:163560051396 642 if (LPC_USB->USBEpIntSt & EP(EP1OUT))
chris 0:163560051396 643 {
chris 0:163560051396 644 selectEndpointClearInterrupt(EP1OUT);
chris 0:163560051396 645 epComplete |= EP(EP1OUT);
chris 0:163560051396 646 }
chris 0:163560051396 647
chris 0:163560051396 648 if (LPC_USB->USBEpIntSt & EP(EP2IN))
chris 0:163560051396 649 {
chris 0:163560051396 650 selectEndpointClearInterrupt(EP2IN);
chris 0:163560051396 651 epComplete |= EP(EP2IN);
chris 0:163560051396 652 }
chris 0:163560051396 653
chris 0:163560051396 654 if (LPC_USB->USBEpIntSt & EP(EP2OUT))
chris 0:163560051396 655 {
chris 0:163560051396 656 selectEndpointClearInterrupt(EP2OUT);
chris 0:163560051396 657 epComplete |= EP(EP2OUT);
chris 0:163560051396 658 }
chris 0:163560051396 659
chris 0:163560051396 660 if (LPC_USB->USBEpIntSt & EP(EP3IN))
chris 0:163560051396 661 {
chris 0:163560051396 662 selectEndpointClearInterrupt(EP3IN);
chris 0:163560051396 663 epComplete |= EP(EP3IN);
chris 0:163560051396 664 }
chris 0:163560051396 665
chris 0:163560051396 666 if (LPC_USB->USBEpIntSt & EP(EP3OUT))
chris 0:163560051396 667 {
chris 0:163560051396 668 selectEndpointClearInterrupt(EP3OUT);
chris 0:163560051396 669 epComplete |= EP(EP3OUT);
chris 0:163560051396 670 }
chris 0:163560051396 671
chris 0:163560051396 672 /* Clear interrupt status flag */
chris 0:163560051396 673 /* EP_SLOW and EP_FAST interrupt bits should be cleared after the corresponding endpoint interrupts are cleared. */
chris 0:163560051396 674 LPC_USB->USBDevIntClr = EP_SLOW;
chris 0:163560051396 675 }
chris 0:163560051396 676 }
chris 0:163560051396 677 }
chris 0:163560051396 678
chris 0:163560051396 679 #endif