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