EA BaseBoard, playing wav, PC see\'s SD-card through USB port.

Dependencies:   mbed

Committer:
Lerche
Date:
Tue Nov 22 05:45:58 2011 +0000
Revision:
0:fef366d2ed20
Thanks to those who provided EA_WavPlayer and USB_MSC

Who changed what in which revision?

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