USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Tue Dec 06 12:07:12 2011 +0000
Revision:
14:757226626acb
protection enabled when usb cable plugged. filesystem has no access when plugged

Who changed what in which revision?

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