USB device stack

Dependents:   mbed-mX-USB-TEST1 USBMSD_SD_HID_HelloWorld HidTest MIDI_usb_bridge ... more

Legacy Warning

This is an mbed 2 library. To learn more about mbed OS 5, visit the docs.

Pull requests against this repository are no longer supported. Please raise against mbed OS 5 as documented above.

Committer:
Kojto
Date:
Thu Jul 27 12:14:04 2017 +0100
Revision:
71:53949e6131f6
Update libraries

Fixes the previous commmit, as some devices were not copied. USBDevice contains
now targets directory with all targets implementations

Who changed what in which revision?

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