A copy of the mbed USBDevice with USBSerial library

Dependents:   STM32L0_LoRa Smartage STM32L0_LoRa Turtle_RadioShuttle

Committer:
Helmut Tschemernjak
Date:
Thu Jan 31 20:56:55 2019 +0100
Revision:
7:8a5cc0d9bfa2
Parent:
0:a3ea811f80f2
fixed compiler warnings

Who changed what in which revision?

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