USB device stack with Nucleo F401RE support. NOTE: the default clock config needs to be changed to in order for USB to work.

Fork of USBDevice by Tomas Cerskus

Slightly modified original USBDevice library to support F401RE.

On F401RE the data pins of your USB connector should be attached to PA12 (D+) and PA11(D-). It is also required to connect the +5V USB line to PA9.

F401RE requires 48MHz clock for USB. Therefore in order for this to work you will need to change the default clock settings:

Clock settings for USB

#include "stm32f4xx_hal.h"

RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 7;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
    error("RTC error: LSI clock initialization failed."); 
}

NOTE: Changing the clock frequency might affect the behavior of other libraries. I only tested the Serial library.

UPDATE: Clock settings should not to be changed anymore! Looks like the newer mbed library has the required clock enabled.

Committer:
tolaipner
Date:
Sun Mar 30 07:30:18 2014 +0000
Revision:
24:4ed3e25c3edc
Parent:
12:6030a12b6c62
Added Nucleo F401RE support

Who changed what in which revision?

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