USBMSD test for GR-PEACH

Dependencies:   USBDevice USBMSD_SD mbed

Fork of USBMSD_SD_HelloWorld_Mbed by Samuel Mokrani

Committer:
samux
Date:
Wed Nov 16 17:17:42 2011 +0000
Revision:
11:a26e7b7a1221
GOOD COMMIT: msd and hid work even on MAC...

Who changed what in which revision?

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