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