USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Sun Dec 11 15:22:50 2011 +0000
Revision:
18:08b207d10056
all is working: rename...

Who changed what in which revision?

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