USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Fri Nov 11 15:22:53 2011 +0000
Revision:
2:27a7e7f8d399
we have 2MB with the sdcard!!

Who changed what in which revision?

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