USB device stack

Dependents:   USBMSD_step1 USBMSD_step1_5 picossd_step1_2cs

Committer:
muraguchi
Date:
Wed Sep 15 16:31:51 2021 +0000
Revision:
73:72808bd55ce2
Parent:
71:53949e6131f6
AirioBase + 2 chip PicoSSD board

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Kojto 71:53949e6131f6 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
Kojto 71:53949e6131f6 2 *
Kojto 71:53949e6131f6 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
Kojto 71:53949e6131f6 4 * and associated documentation files (the "Software"), to deal in the Software without
Kojto 71:53949e6131f6 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
Kojto 71:53949e6131f6 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
Kojto 71:53949e6131f6 7 * Software is furnished to do so, subject to the following conditions:
Kojto 71:53949e6131f6 8 *
Kojto 71:53949e6131f6 9 * The above copyright notice and this permission notice shall be included in all copies or
Kojto 71:53949e6131f6 10 * substantial portions of the Software.
Kojto 71:53949e6131f6 11 *
Kojto 71:53949e6131f6 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
Kojto 71:53949e6131f6 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Kojto 71:53949e6131f6 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
Kojto 71:53949e6131f6 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Kojto 71:53949e6131f6 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Kojto 71:53949e6131f6 17 */
Kojto 71:53949e6131f6 18
Kojto 71:53949e6131f6 19 #if defined(TARGET_LPC11UXX) || defined(TARGET_LPC11U6X) || defined(TARGET_LPC1347) || defined(TARGET_LPC1549)
Kojto 71:53949e6131f6 20
Kojto 71:53949e6131f6 21 #if defined(TARGET_LPC1347) || defined(TARGET_LPC1549)
Kojto 71:53949e6131f6 22 #define USB_IRQ USB_IRQ_IRQn
Kojto 71:53949e6131f6 23 #else
Kojto 71:53949e6131f6 24 #define USB_IRQ USB_IRQn
Kojto 71:53949e6131f6 25 #endif
Kojto 71:53949e6131f6 26
Kojto 71:53949e6131f6 27 #include "USBHAL.h"
Kojto 71:53949e6131f6 28
Kojto 71:53949e6131f6 29 USBHAL * USBHAL::instance;
Kojto 71:53949e6131f6 30 #if defined(TARGET_LPC1549)
Kojto 71:53949e6131f6 31 static uint8_t usbmem[2048] __attribute__((aligned(2048)));
Kojto 71:53949e6131f6 32 #endif
Kojto 71:53949e6131f6 33
Kojto 71:53949e6131f6 34 // Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
Kojto 71:53949e6131f6 35 #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
Kojto 71:53949e6131f6 36
Kojto 71:53949e6131f6 37 // Convert physical endpoint number to register bit
Kojto 71:53949e6131f6 38 #define EP(endpoint) (1UL<<endpoint)
Kojto 71:53949e6131f6 39
Kojto 71:53949e6131f6 40 // Convert physical to logical
Kojto 71:53949e6131f6 41 #define PHY_TO_LOG(endpoint) ((endpoint)>>1)
Kojto 71:53949e6131f6 42
Kojto 71:53949e6131f6 43 // Get endpoint direction
Kojto 71:53949e6131f6 44 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
Kojto 71:53949e6131f6 45 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
Kojto 71:53949e6131f6 46
Kojto 71:53949e6131f6 47 // USB RAM
Kojto 71:53949e6131f6 48 #if defined(TARGET_LPC1549)
Kojto 71:53949e6131f6 49 #define USB_RAM_START ((uint32_t)usbmem)
Kojto 71:53949e6131f6 50 #define USB_RAM_SIZE sizeof(usbmem)
Kojto 71:53949e6131f6 51 #else
Kojto 71:53949e6131f6 52 #define USB_RAM_START (0x20004000)
Kojto 71:53949e6131f6 53 #define USB_RAM_SIZE (0x00000800)
Kojto 71:53949e6131f6 54 #endif
Kojto 71:53949e6131f6 55
Kojto 71:53949e6131f6 56 // SYSAHBCLKCTRL
Kojto 71:53949e6131f6 57 #if defined(TARGET_LPC1549)
Kojto 71:53949e6131f6 58 #define CLK_USB (1UL<<23)
Kojto 71:53949e6131f6 59 #else
Kojto 71:53949e6131f6 60 #define CLK_USB (1UL<<14)
Kojto 71:53949e6131f6 61 #define CLK_USBRAM (1UL<<27)
Kojto 71:53949e6131f6 62 #endif
Kojto 71:53949e6131f6 63
Kojto 71:53949e6131f6 64 // USB Information register
Kojto 71:53949e6131f6 65 #define FRAME_NR(a) ((a) & 0x7ff) // Frame number
Kojto 71:53949e6131f6 66
Kojto 71:53949e6131f6 67 // USB Device Command/Status register
Kojto 71:53949e6131f6 68 #define DEV_ADDR_MASK (0x7f) // Device address
Kojto 71:53949e6131f6 69 #define DEV_ADDR(a) ((a) & DEV_ADDR_MASK)
Kojto 71:53949e6131f6 70 #define DEV_EN (1UL<<7) // Device enable
Kojto 71:53949e6131f6 71 #define SETUP (1UL<<8) // SETUP token received
Kojto 71:53949e6131f6 72 #define PLL_ON (1UL<<9) // PLL enabled in suspend
Kojto 71:53949e6131f6 73 #define DCON (1UL<<16) // Device status - connect
Kojto 71:53949e6131f6 74 #define DSUS (1UL<<17) // Device status - suspend
Kojto 71:53949e6131f6 75 #define DCON_C (1UL<<24) // Connect change
Kojto 71:53949e6131f6 76 #define DSUS_C (1UL<<25) // Suspend change
Kojto 71:53949e6131f6 77 #define DRES_C (1UL<<26) // Reset change
Kojto 71:53949e6131f6 78 #define VBUSDEBOUNCED (1UL<<28) // Vbus detected
Kojto 71:53949e6131f6 79
Kojto 71:53949e6131f6 80 // Endpoint Command/Status list
Kojto 71:53949e6131f6 81 #define CMDSTS_A (1UL<<31) // Active
Kojto 71:53949e6131f6 82 #define CMDSTS_D (1UL<<30) // Disable
Kojto 71:53949e6131f6 83 #define CMDSTS_S (1UL<<29) // Stall
Kojto 71:53949e6131f6 84 #define CMDSTS_TR (1UL<<28) // Toggle Reset
Kojto 71:53949e6131f6 85 #define CMDSTS_RF (1UL<<27) // Rate Feedback mode
Kojto 71:53949e6131f6 86 #define CMDSTS_TV (1UL<<27) // Toggle Value
Kojto 71:53949e6131f6 87 #define CMDSTS_T (1UL<<26) // Endpoint Type
Kojto 71:53949e6131f6 88 #define CMDSTS_NBYTES(n) (((n)&0x3ff)<<16) // Number of bytes
Kojto 71:53949e6131f6 89 #define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff) // Buffer start address
Kojto 71:53949e6131f6 90
Kojto 71:53949e6131f6 91 #define BYTES_REMAINING(s) (((s)>>16)&0x3ff) // Bytes remaining after transfer
Kojto 71:53949e6131f6 92
Kojto 71:53949e6131f6 93 // USB Non-endpoint interrupt sources
Kojto 71:53949e6131f6 94 #define FRAME_INT (1UL<<30)
Kojto 71:53949e6131f6 95 #define DEV_INT (1UL<<31)
Kojto 71:53949e6131f6 96
Kojto 71:53949e6131f6 97 static volatile int epComplete = 0;
Kojto 71:53949e6131f6 98
Kojto 71:53949e6131f6 99 // One entry for a double-buffered logical endpoint in the endpoint
Kojto 71:53949e6131f6 100 // command/status list. Endpoint 0 is single buffered, out[1] is used
Kojto 71:53949e6131f6 101 // for the SETUP packet and in[1] is not used
Kojto 71:53949e6131f6 102 typedef struct {
Kojto 71:53949e6131f6 103 uint32_t out[2];
Kojto 71:53949e6131f6 104 uint32_t in[2];
Kojto 71:53949e6131f6 105 } PACKED EP_COMMAND_STATUS;
Kojto 71:53949e6131f6 106
Kojto 71:53949e6131f6 107 typedef struct {
Kojto 71:53949e6131f6 108 uint8_t out[MAX_PACKET_SIZE_EP0];
Kojto 71:53949e6131f6 109 uint8_t in[MAX_PACKET_SIZE_EP0];
Kojto 71:53949e6131f6 110 uint8_t setup[SETUP_PACKET_SIZE];
Kojto 71:53949e6131f6 111 } PACKED CONTROL_TRANSFER;
Kojto 71:53949e6131f6 112
Kojto 71:53949e6131f6 113 typedef struct {
Kojto 71:53949e6131f6 114 uint32_t maxPacket;
Kojto 71:53949e6131f6 115 uint32_t buffer[2];
Kojto 71:53949e6131f6 116 uint32_t options;
Kojto 71:53949e6131f6 117 } PACKED EP_STATE;
Kojto 71:53949e6131f6 118
Kojto 71:53949e6131f6 119 static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
Kojto 71:53949e6131f6 120
Kojto 71:53949e6131f6 121 // Pointer to the endpoint command/status list
Kojto 71:53949e6131f6 122 static EP_COMMAND_STATUS *ep = NULL;
Kojto 71:53949e6131f6 123
Kojto 71:53949e6131f6 124 // Pointer to endpoint 0 data (IN/OUT and SETUP)
Kojto 71:53949e6131f6 125 static CONTROL_TRANSFER *ct = NULL;
Kojto 71:53949e6131f6 126
Kojto 71:53949e6131f6 127 // Shadow DEVCMDSTAT register to avoid accidentally clearing flags or
Kojto 71:53949e6131f6 128 // initiating a remote wakeup event.
Kojto 71:53949e6131f6 129 static volatile uint32_t devCmdStat;
Kojto 71:53949e6131f6 130
Kojto 71:53949e6131f6 131 // Pointers used to allocate USB RAM
Kojto 71:53949e6131f6 132 static uint32_t usbRamPtr = USB_RAM_START;
Kojto 71:53949e6131f6 133 static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here
Kojto 71:53949e6131f6 134
Kojto 71:53949e6131f6 135 #define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m))
Kojto 71:53949e6131f6 136
Kojto 71:53949e6131f6 137 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size);
Kojto 71:53949e6131f6 138 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) {
Kojto 71:53949e6131f6 139 if (size > 0) {
Kojto 71:53949e6131f6 140 do {
Kojto 71:53949e6131f6 141 *dst++ = *src++;
Kojto 71:53949e6131f6 142 } while (--size > 0);
Kojto 71:53949e6131f6 143 }
Kojto 71:53949e6131f6 144 }
Kojto 71:53949e6131f6 145
Kojto 71:53949e6131f6 146
Kojto 71:53949e6131f6 147 USBHAL::USBHAL(void) {
Kojto 71:53949e6131f6 148 NVIC_DisableIRQ(USB_IRQ);
Kojto 71:53949e6131f6 149
Kojto 71:53949e6131f6 150 // fill in callback array
Kojto 71:53949e6131f6 151 epCallback[0] = &USBHAL::EP1_OUT_callback;
Kojto 71:53949e6131f6 152 epCallback[1] = &USBHAL::EP1_IN_callback;
Kojto 71:53949e6131f6 153 epCallback[2] = &USBHAL::EP2_OUT_callback;
Kojto 71:53949e6131f6 154 epCallback[3] = &USBHAL::EP2_IN_callback;
Kojto 71:53949e6131f6 155 epCallback[4] = &USBHAL::EP3_OUT_callback;
Kojto 71:53949e6131f6 156 epCallback[5] = &USBHAL::EP3_IN_callback;
Kojto 71:53949e6131f6 157 epCallback[6] = &USBHAL::EP4_OUT_callback;
Kojto 71:53949e6131f6 158 epCallback[7] = &USBHAL::EP4_IN_callback;
Kojto 71:53949e6131f6 159
Kojto 71:53949e6131f6 160 #if defined(TARGET_LPC1549)
Kojto 71:53949e6131f6 161 /* Set USB PLL input to system oscillator */
Kojto 71:53949e6131f6 162 LPC_SYSCON->USBPLLCLKSEL = 0x01;
Kojto 71:53949e6131f6 163
Kojto 71:53949e6131f6 164 /* Setup USB PLL (FCLKIN = 12MHz) * 4 = 48MHz
Kojto 71:53949e6131f6 165 MSEL = 3 (this is pre-decremented), PSEL = 1 (for P = 2)
Kojto 71:53949e6131f6 166 FCLKOUT = FCLKIN * (MSEL + 1) = 12MHz * 4 = 48MHz
Kojto 71:53949e6131f6 167 FCCO = FCLKOUT * 2 * P = 48MHz * 2 * 2 = 192MHz (within FCCO range) */
Kojto 71:53949e6131f6 168 LPC_SYSCON->USBPLLCTRL = (0x3 | (1UL << 6));
Kojto 71:53949e6131f6 169
Kojto 71:53949e6131f6 170 /* Powerup USB PLL */
Kojto 71:53949e6131f6 171 LPC_SYSCON->PDRUNCFG &= ~(CLK_USB);
Kojto 71:53949e6131f6 172
Kojto 71:53949e6131f6 173 /* Wait for PLL to lock */
Kojto 71:53949e6131f6 174 while(!(LPC_SYSCON->USBPLLSTAT & 0x01));
Kojto 71:53949e6131f6 175
Kojto 71:53949e6131f6 176 /* enable USB main clock */
Kojto 71:53949e6131f6 177 LPC_SYSCON->USBCLKSEL = 0x02;
Kojto 71:53949e6131f6 178 LPC_SYSCON->USBCLKDIV = 1;
Kojto 71:53949e6131f6 179
Kojto 71:53949e6131f6 180 /* Enable AHB clock to the USB block. */
Kojto 71:53949e6131f6 181 LPC_SYSCON->SYSAHBCLKCTRL1 |= CLK_USB;
Kojto 71:53949e6131f6 182
Kojto 71:53949e6131f6 183 /* power UP USB Phy */
Kojto 71:53949e6131f6 184 LPC_SYSCON->PDRUNCFG &= ~(1UL << 9);
Kojto 71:53949e6131f6 185
Kojto 71:53949e6131f6 186 /* Reset USB block */
Kojto 71:53949e6131f6 187 LPC_SYSCON->PRESETCTRL1 |= (CLK_USB);
Kojto 71:53949e6131f6 188 LPC_SYSCON->PRESETCTRL1 &= ~(CLK_USB);
Kojto 71:53949e6131f6 189
Kojto 71:53949e6131f6 190 #else
Kojto 71:53949e6131f6 191 #if defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501)
Kojto 71:53949e6131f6 192 // USB_VBUS input with pull-down
Kojto 71:53949e6131f6 193 LPC_IOCON->PIO0_3 = 0x00000009;
Kojto 71:53949e6131f6 194 #endif
Kojto 71:53949e6131f6 195
Kojto 71:53949e6131f6 196 // nUSB_CONNECT output
Kojto 71:53949e6131f6 197 LPC_IOCON->PIO0_6 = 0x00000001;
Kojto 71:53949e6131f6 198
Kojto 71:53949e6131f6 199 // Enable clocks (USB registers, USB RAM)
Kojto 71:53949e6131f6 200 LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
Kojto 71:53949e6131f6 201
Kojto 71:53949e6131f6 202 // Ensure device disconnected (DCON not set)
Kojto 71:53949e6131f6 203 LPC_USB->DEVCMDSTAT = 0;
Kojto 71:53949e6131f6 204 #endif
Kojto 71:53949e6131f6 205 // to ensure that the USB host sees the device as
Kojto 71:53949e6131f6 206 // disconnected if the target CPU is reset.
Kojto 71:53949e6131f6 207 wait(0.3);
Kojto 71:53949e6131f6 208
Kojto 71:53949e6131f6 209 // Reserve space in USB RAM for endpoint command/status list
Kojto 71:53949e6131f6 210 // Must be 256 byte aligned
Kojto 71:53949e6131f6 211 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256);
Kojto 71:53949e6131f6 212 ep = (EP_COMMAND_STATUS *)usbRamPtr;
Kojto 71:53949e6131f6 213 usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS);
Kojto 71:53949e6131f6 214 LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00;
Kojto 71:53949e6131f6 215
Kojto 71:53949e6131f6 216 // Reserve space in USB RAM for Endpoint 0
Kojto 71:53949e6131f6 217 // Must be 64 byte aligned
Kojto 71:53949e6131f6 218 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64);
Kojto 71:53949e6131f6 219 ct = (CONTROL_TRANSFER *)usbRamPtr;
Kojto 71:53949e6131f6 220 usbRamPtr += sizeof(CONTROL_TRANSFER);
Kojto 71:53949e6131f6 221 LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000;
Kojto 71:53949e6131f6 222
Kojto 71:53949e6131f6 223 // Setup command/status list for EP0
Kojto 71:53949e6131f6 224 ep[0].out[0] = 0;
Kojto 71:53949e6131f6 225 ep[0].in[0] = 0;
Kojto 71:53949e6131f6 226 ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup);
Kojto 71:53949e6131f6 227
Kojto 71:53949e6131f6 228 // Route all interrupts to IRQ, some can be routed to
Kojto 71:53949e6131f6 229 // USB_FIQ if you wish.
Kojto 71:53949e6131f6 230 LPC_USB->INTROUTING = 0;
Kojto 71:53949e6131f6 231
Kojto 71:53949e6131f6 232 // Set device address 0, enable USB device, no remote wakeup
Kojto 71:53949e6131f6 233 devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS;
Kojto 71:53949e6131f6 234 LPC_USB->DEVCMDSTAT = devCmdStat;
Kojto 71:53949e6131f6 235
Kojto 71:53949e6131f6 236 // Enable interrupts for device events and EP0
Kojto 71:53949e6131f6 237 LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT) | FRAME_INT;
Kojto 71:53949e6131f6 238 instance = this;
Kojto 71:53949e6131f6 239
Kojto 71:53949e6131f6 240 //attach IRQ handler and enable interrupts
Kojto 71:53949e6131f6 241 NVIC_SetVector(USB_IRQ, (uint32_t)&_usbisr);
Kojto 71:53949e6131f6 242 }
Kojto 71:53949e6131f6 243
Kojto 71:53949e6131f6 244 USBHAL::~USBHAL(void) {
Kojto 71:53949e6131f6 245 // Ensure device disconnected (DCON not set)
Kojto 71:53949e6131f6 246 LPC_USB->DEVCMDSTAT = 0;
Kojto 71:53949e6131f6 247 // Disable USB interrupts
Kojto 71:53949e6131f6 248 NVIC_DisableIRQ(USB_IRQ);
Kojto 71:53949e6131f6 249 }
Kojto 71:53949e6131f6 250
Kojto 71:53949e6131f6 251 void USBHAL::connect(void) {
Kojto 71:53949e6131f6 252 NVIC_EnableIRQ(USB_IRQ);
Kojto 71:53949e6131f6 253 devCmdStat |= DCON;
Kojto 71:53949e6131f6 254 LPC_USB->DEVCMDSTAT = devCmdStat;
Kojto 71:53949e6131f6 255 }
Kojto 71:53949e6131f6 256
Kojto 71:53949e6131f6 257 void USBHAL::disconnect(void) {
Kojto 71:53949e6131f6 258 NVIC_DisableIRQ(USB_IRQ);
Kojto 71:53949e6131f6 259 devCmdStat &= ~DCON;
Kojto 71:53949e6131f6 260 LPC_USB->DEVCMDSTAT = devCmdStat;
Kojto 71:53949e6131f6 261 }
Kojto 71:53949e6131f6 262
Kojto 71:53949e6131f6 263 void USBHAL::configureDevice(void) {
Kojto 71:53949e6131f6 264 // Not required
Kojto 71:53949e6131f6 265 }
Kojto 71:53949e6131f6 266
Kojto 71:53949e6131f6 267 void USBHAL::unconfigureDevice(void) {
Kojto 71:53949e6131f6 268 // Not required
Kojto 71:53949e6131f6 269 }
Kojto 71:53949e6131f6 270
Kojto 71:53949e6131f6 271 void USBHAL::EP0setup(uint8_t *buffer) {
Kojto 71:53949e6131f6 272 // Copy setup packet data
Kojto 71:53949e6131f6 273 USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
Kojto 71:53949e6131f6 274 }
Kojto 71:53949e6131f6 275
Kojto 71:53949e6131f6 276 void USBHAL::EP0read(void) {
Kojto 71:53949e6131f6 277 // Start an endpoint 0 read
Kojto 71:53949e6131f6 278
Kojto 71:53949e6131f6 279 // The USB ISR will call USBDevice_EP0out() when a packet has been read,
Kojto 71:53949e6131f6 280 // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
Kojto 71:53949e6131f6 281 // read the data.
Kojto 71:53949e6131f6 282
Kojto 71:53949e6131f6 283 ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
Kojto 71:53949e6131f6 284 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
Kojto 71:53949e6131f6 285 }
Kojto 71:53949e6131f6 286
Kojto 71:53949e6131f6 287 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
Kojto 71:53949e6131f6 288 // Complete an endpoint 0 read
Kojto 71:53949e6131f6 289 uint32_t bytesRead;
Kojto 71:53949e6131f6 290
Kojto 71:53949e6131f6 291 // Find how many bytes were read
Kojto 71:53949e6131f6 292 bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
Kojto 71:53949e6131f6 293
Kojto 71:53949e6131f6 294 // Copy data
Kojto 71:53949e6131f6 295 USBMemCopy(buffer, ct->out, bytesRead);
Kojto 71:53949e6131f6 296 return bytesRead;
Kojto 71:53949e6131f6 297 }
Kojto 71:53949e6131f6 298
Kojto 71:53949e6131f6 299
Kojto 71:53949e6131f6 300 void USBHAL::EP0readStage(void) {
Kojto 71:53949e6131f6 301 // Not required
Kojto 71:53949e6131f6 302 }
Kojto 71:53949e6131f6 303
Kojto 71:53949e6131f6 304 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
Kojto 71:53949e6131f6 305 // Start and endpoint 0 write
Kojto 71:53949e6131f6 306
Kojto 71:53949e6131f6 307 // The USB ISR will call USBDevice_EP0in() when the data has
Kojto 71:53949e6131f6 308 // been written, the USBDevice layer then calls
Kojto 71:53949e6131f6 309 // USBBusInterface_EP0getWriteResult() to complete the transaction.
Kojto 71:53949e6131f6 310
Kojto 71:53949e6131f6 311 // Copy data
Kojto 71:53949e6131f6 312 USBMemCopy(ct->in, buffer, size);
Kojto 71:53949e6131f6 313
Kojto 71:53949e6131f6 314 // Start transfer
Kojto 71:53949e6131f6 315 ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
Kojto 71:53949e6131f6 316 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
Kojto 71:53949e6131f6 317 }
Kojto 71:53949e6131f6 318
Kojto 71:53949e6131f6 319
Kojto 71:53949e6131f6 320 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
Kojto 71:53949e6131f6 321 uint8_t bf = 0;
Kojto 71:53949e6131f6 322 uint32_t flags = 0;
Kojto 71:53949e6131f6 323
Kojto 71:53949e6131f6 324 //check which buffer must be filled
Kojto 71:53949e6131f6 325 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Kojto 71:53949e6131f6 326 // Double buffered
Kojto 71:53949e6131f6 327 if (LPC_USB->EPINUSE & EP(endpoint)) {
Kojto 71:53949e6131f6 328 bf = 1;
Kojto 71:53949e6131f6 329 } else {
Kojto 71:53949e6131f6 330 bf = 0;
Kojto 71:53949e6131f6 331 }
Kojto 71:53949e6131f6 332 }
Kojto 71:53949e6131f6 333
Kojto 71:53949e6131f6 334 // if isochronous endpoint, T = 1
Kojto 71:53949e6131f6 335 if(endpointState[endpoint].options & ISOCHRONOUS)
Kojto 71:53949e6131f6 336 {
Kojto 71:53949e6131f6 337 flags |= CMDSTS_T;
Kojto 71:53949e6131f6 338 }
Kojto 71:53949e6131f6 339
Kojto 71:53949e6131f6 340 //Active the endpoint for reading
Kojto 71:53949e6131f6 341 ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
Kojto 71:53949e6131f6 342 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags;
Kojto 71:53949e6131f6 343 return EP_PENDING;
Kojto 71:53949e6131f6 344 }
Kojto 71:53949e6131f6 345
Kojto 71:53949e6131f6 346 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) {
Kojto 71:53949e6131f6 347
Kojto 71:53949e6131f6 348 uint8_t bf = 0;
Kojto 71:53949e6131f6 349
Kojto 71:53949e6131f6 350 if (!(epComplete & EP(endpoint)))
Kojto 71:53949e6131f6 351 return EP_PENDING;
Kojto 71:53949e6131f6 352 else {
Kojto 71:53949e6131f6 353 epComplete &= ~EP(endpoint);
Kojto 71:53949e6131f6 354
Kojto 71:53949e6131f6 355 //check which buffer has been filled
Kojto 71:53949e6131f6 356 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Kojto 71:53949e6131f6 357 // Double buffered (here we read the previous buffer which was used)
Kojto 71:53949e6131f6 358 if (LPC_USB->EPINUSE & EP(endpoint)) {
Kojto 71:53949e6131f6 359 bf = 0;
Kojto 71:53949e6131f6 360 } else {
Kojto 71:53949e6131f6 361 bf = 1;
Kojto 71:53949e6131f6 362 }
Kojto 71:53949e6131f6 363 }
Kojto 71:53949e6131f6 364
Kojto 71:53949e6131f6 365 // Find how many bytes were read
Kojto 71:53949e6131f6 366 *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf]));
Kojto 71:53949e6131f6 367
Kojto 71:53949e6131f6 368 // Copy data
Kojto 71:53949e6131f6 369 USBMemCopy(data, ct->out, *bytesRead);
Kojto 71:53949e6131f6 370 return EP_COMPLETED;
Kojto 71:53949e6131f6 371 }
Kojto 71:53949e6131f6 372 }
Kojto 71:53949e6131f6 373
Kojto 71:53949e6131f6 374 void USBHAL::EP0getWriteResult(void) {
Kojto 71:53949e6131f6 375 // Not required
Kojto 71:53949e6131f6 376 }
Kojto 71:53949e6131f6 377
Kojto 71:53949e6131f6 378 void USBHAL::EP0stall(void) {
Kojto 71:53949e6131f6 379 ep[0].in[0] = CMDSTS_S;
Kojto 71:53949e6131f6 380 ep[0].out[0] = CMDSTS_S;
Kojto 71:53949e6131f6 381 }
Kojto 71:53949e6131f6 382
Kojto 71:53949e6131f6 383 void USBHAL::setAddress(uint8_t address) {
Kojto 71:53949e6131f6 384 devCmdStat &= ~DEV_ADDR_MASK;
Kojto 71:53949e6131f6 385 devCmdStat |= DEV_ADDR(address);
Kojto 71:53949e6131f6 386 LPC_USB->DEVCMDSTAT = devCmdStat;
Kojto 71:53949e6131f6 387 }
Kojto 71:53949e6131f6 388
Kojto 71:53949e6131f6 389 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
Kojto 71:53949e6131f6 390 uint32_t flags = 0;
Kojto 71:53949e6131f6 391 uint32_t bf;
Kojto 71:53949e6131f6 392
Kojto 71:53949e6131f6 393 // Validate parameters
Kojto 71:53949e6131f6 394 if (data == NULL) {
Kojto 71:53949e6131f6 395 return EP_INVALID;
Kojto 71:53949e6131f6 396 }
Kojto 71:53949e6131f6 397
Kojto 71:53949e6131f6 398 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
Kojto 71:53949e6131f6 399 return EP_INVALID;
Kojto 71:53949e6131f6 400 }
Kojto 71:53949e6131f6 401
Kojto 71:53949e6131f6 402 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
Kojto 71:53949e6131f6 403 return EP_INVALID;
Kojto 71:53949e6131f6 404 }
Kojto 71:53949e6131f6 405
Kojto 71:53949e6131f6 406 if (size > endpointState[endpoint].maxPacket) {
Kojto 71:53949e6131f6 407 return EP_INVALID;
Kojto 71:53949e6131f6 408 }
Kojto 71:53949e6131f6 409
Kojto 71:53949e6131f6 410 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Kojto 71:53949e6131f6 411 // Double buffered
Kojto 71:53949e6131f6 412 if (LPC_USB->EPINUSE & EP(endpoint)) {
Kojto 71:53949e6131f6 413 bf = 1;
Kojto 71:53949e6131f6 414 } else {
Kojto 71:53949e6131f6 415 bf = 0;
Kojto 71:53949e6131f6 416 }
Kojto 71:53949e6131f6 417 } else {
Kojto 71:53949e6131f6 418 // Single buffered
Kojto 71:53949e6131f6 419 bf = 0;
Kojto 71:53949e6131f6 420 }
Kojto 71:53949e6131f6 421
Kojto 71:53949e6131f6 422 // Check if already active
Kojto 71:53949e6131f6 423 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
Kojto 71:53949e6131f6 424 return EP_INVALID;
Kojto 71:53949e6131f6 425 }
Kojto 71:53949e6131f6 426
Kojto 71:53949e6131f6 427 // Check if stalled
Kojto 71:53949e6131f6 428 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
Kojto 71:53949e6131f6 429 return EP_STALLED;
Kojto 71:53949e6131f6 430 }
Kojto 71:53949e6131f6 431
Kojto 71:53949e6131f6 432 // Copy data to USB RAM
Kojto 71:53949e6131f6 433 USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
Kojto 71:53949e6131f6 434
Kojto 71:53949e6131f6 435 // Add options
Kojto 71:53949e6131f6 436 if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) {
Kojto 71:53949e6131f6 437 flags |= CMDSTS_RF;
Kojto 71:53949e6131f6 438 }
Kojto 71:53949e6131f6 439
Kojto 71:53949e6131f6 440 if (endpointState[endpoint].options & ISOCHRONOUS) {
Kojto 71:53949e6131f6 441 flags |= CMDSTS_T;
Kojto 71:53949e6131f6 442 }
Kojto 71:53949e6131f6 443
Kojto 71:53949e6131f6 444 // Add transfer
Kojto 71:53949e6131f6 445 ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
Kojto 71:53949e6131f6 446 endpointState[endpoint].buffer[bf]) \
Kojto 71:53949e6131f6 447 | CMDSTS_NBYTES(size) | CMDSTS_A | flags;
Kojto 71:53949e6131f6 448
Kojto 71:53949e6131f6 449 return EP_PENDING;
Kojto 71:53949e6131f6 450 }
Kojto 71:53949e6131f6 451
Kojto 71:53949e6131f6 452 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
Kojto 71:53949e6131f6 453 uint32_t bf;
Kojto 71:53949e6131f6 454
Kojto 71:53949e6131f6 455 // Validate parameters
Kojto 71:53949e6131f6 456 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
Kojto 71:53949e6131f6 457 return EP_INVALID;
Kojto 71:53949e6131f6 458 }
Kojto 71:53949e6131f6 459
Kojto 71:53949e6131f6 460 if (OUT_EP(endpoint)) {
Kojto 71:53949e6131f6 461 return EP_INVALID;
Kojto 71:53949e6131f6 462 }
Kojto 71:53949e6131f6 463
Kojto 71:53949e6131f6 464 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Kojto 71:53949e6131f6 465 // Double buffered // TODO: FIX THIS
Kojto 71:53949e6131f6 466 if (LPC_USB->EPINUSE & EP(endpoint)) {
Kojto 71:53949e6131f6 467 bf = 1;
Kojto 71:53949e6131f6 468 } else {
Kojto 71:53949e6131f6 469 bf = 0;
Kojto 71:53949e6131f6 470 }
Kojto 71:53949e6131f6 471 } else {
Kojto 71:53949e6131f6 472 // Single buffered
Kojto 71:53949e6131f6 473 bf = 0;
Kojto 71:53949e6131f6 474 }
Kojto 71:53949e6131f6 475
Kojto 71:53949e6131f6 476 // Check if endpoint still active
Kojto 71:53949e6131f6 477 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
Kojto 71:53949e6131f6 478 return EP_PENDING;
Kojto 71:53949e6131f6 479 }
Kojto 71:53949e6131f6 480
Kojto 71:53949e6131f6 481 // Check if stalled
Kojto 71:53949e6131f6 482 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
Kojto 71:53949e6131f6 483 return EP_STALLED;
Kojto 71:53949e6131f6 484 }
Kojto 71:53949e6131f6 485
Kojto 71:53949e6131f6 486 return EP_COMPLETED;
Kojto 71:53949e6131f6 487 }
Kojto 71:53949e6131f6 488
Kojto 71:53949e6131f6 489 void USBHAL::stallEndpoint(uint8_t endpoint) {
Kojto 71:53949e6131f6 490
Kojto 71:53949e6131f6 491 // FIX: should this clear active bit?
Kojto 71:53949e6131f6 492 if (IN_EP(endpoint)) {
Kojto 71:53949e6131f6 493 ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
Kojto 71:53949e6131f6 494 ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
Kojto 71:53949e6131f6 495 } else {
Kojto 71:53949e6131f6 496 ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
Kojto 71:53949e6131f6 497 ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
Kojto 71:53949e6131f6 498 }
Kojto 71:53949e6131f6 499 }
Kojto 71:53949e6131f6 500
Kojto 71:53949e6131f6 501 void USBHAL::unstallEndpoint(uint8_t endpoint) {
Kojto 71:53949e6131f6 502 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Kojto 71:53949e6131f6 503 // Double buffered
Kojto 71:53949e6131f6 504 if (IN_EP(endpoint)) {
Kojto 71:53949e6131f6 505 ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0
Kojto 71:53949e6131f6 506 ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0
Kojto 71:53949e6131f6 507
Kojto 71:53949e6131f6 508 if (LPC_USB->EPINUSE & EP(endpoint)) {
Kojto 71:53949e6131f6 509 ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Kojto 71:53949e6131f6 510 } else {
Kojto 71:53949e6131f6 511 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Kojto 71:53949e6131f6 512 }
Kojto 71:53949e6131f6 513 } else {
Kojto 71:53949e6131f6 514 ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0
Kojto 71:53949e6131f6 515 ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0
Kojto 71:53949e6131f6 516
Kojto 71:53949e6131f6 517 if (LPC_USB->EPINUSE & EP(endpoint)) {
Kojto 71:53949e6131f6 518 ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Kojto 71:53949e6131f6 519 } else {
Kojto 71:53949e6131f6 520 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Kojto 71:53949e6131f6 521 }
Kojto 71:53949e6131f6 522 }
Kojto 71:53949e6131f6 523 } else {
Kojto 71:53949e6131f6 524 // Single buffered
Kojto 71:53949e6131f6 525 if (IN_EP(endpoint)) {
Kojto 71:53949e6131f6 526 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Kojto 71:53949e6131f6 527 } else {
Kojto 71:53949e6131f6 528 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Kojto 71:53949e6131f6 529 }
Kojto 71:53949e6131f6 530 }
Kojto 71:53949e6131f6 531 }
Kojto 71:53949e6131f6 532
Kojto 71:53949e6131f6 533 bool USBHAL::getEndpointStallState(unsigned char endpoint) {
Kojto 71:53949e6131f6 534 if (IN_EP(endpoint)) {
Kojto 71:53949e6131f6 535 if (LPC_USB->EPINUSE & EP(endpoint)) {
Kojto 71:53949e6131f6 536 if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) {
Kojto 71:53949e6131f6 537 return true;
Kojto 71:53949e6131f6 538 }
Kojto 71:53949e6131f6 539 } else {
Kojto 71:53949e6131f6 540 if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) {
Kojto 71:53949e6131f6 541 return true;
Kojto 71:53949e6131f6 542 }
Kojto 71:53949e6131f6 543 }
Kojto 71:53949e6131f6 544 } else {
Kojto 71:53949e6131f6 545 if (LPC_USB->EPINUSE & EP(endpoint)) {
Kojto 71:53949e6131f6 546 if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) {
Kojto 71:53949e6131f6 547 return true;
Kojto 71:53949e6131f6 548 }
Kojto 71:53949e6131f6 549 } else {
Kojto 71:53949e6131f6 550 if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) {
Kojto 71:53949e6131f6 551 return true;
Kojto 71:53949e6131f6 552 }
Kojto 71:53949e6131f6 553 }
Kojto 71:53949e6131f6 554 }
Kojto 71:53949e6131f6 555
Kojto 71:53949e6131f6 556 return false;
Kojto 71:53949e6131f6 557 }
Kojto 71:53949e6131f6 558
Kojto 71:53949e6131f6 559 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) {
Kojto 71:53949e6131f6 560 uint32_t tmpEpRamPtr;
Kojto 71:53949e6131f6 561
Kojto 71:53949e6131f6 562 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
Kojto 71:53949e6131f6 563 return false;
Kojto 71:53949e6131f6 564 }
Kojto 71:53949e6131f6 565
Kojto 71:53949e6131f6 566 // Not applicable to the control endpoints
Kojto 71:53949e6131f6 567 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
Kojto 71:53949e6131f6 568 return false;
Kojto 71:53949e6131f6 569 }
Kojto 71:53949e6131f6 570
Kojto 71:53949e6131f6 571 // Allocate buffers in USB RAM
Kojto 71:53949e6131f6 572 tmpEpRamPtr = epRamPtr;
Kojto 71:53949e6131f6 573
Kojto 71:53949e6131f6 574 // Must be 64 byte aligned
Kojto 71:53949e6131f6 575 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
Kojto 71:53949e6131f6 576
Kojto 71:53949e6131f6 577 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
Kojto 71:53949e6131f6 578 // Out of memory
Kojto 71:53949e6131f6 579 return false;
Kojto 71:53949e6131f6 580 }
Kojto 71:53949e6131f6 581
Kojto 71:53949e6131f6 582 // Allocate first buffer
Kojto 71:53949e6131f6 583 endpointState[endpoint].buffer[0] = tmpEpRamPtr;
Kojto 71:53949e6131f6 584 tmpEpRamPtr += maxPacket;
Kojto 71:53949e6131f6 585
Kojto 71:53949e6131f6 586 if (!(options & SINGLE_BUFFERED)) {
Kojto 71:53949e6131f6 587 // Must be 64 byte aligned
Kojto 71:53949e6131f6 588 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
Kojto 71:53949e6131f6 589
Kojto 71:53949e6131f6 590 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
Kojto 71:53949e6131f6 591 // Out of memory
Kojto 71:53949e6131f6 592 return false;
Kojto 71:53949e6131f6 593 }
Kojto 71:53949e6131f6 594
Kojto 71:53949e6131f6 595 // Allocate second buffer
Kojto 71:53949e6131f6 596 endpointState[endpoint].buffer[1] = tmpEpRamPtr;
Kojto 71:53949e6131f6 597 tmpEpRamPtr += maxPacket;
Kojto 71:53949e6131f6 598 }
Kojto 71:53949e6131f6 599
Kojto 71:53949e6131f6 600 // Commit to this USB RAM allocation
Kojto 71:53949e6131f6 601 epRamPtr = tmpEpRamPtr;
Kojto 71:53949e6131f6 602
Kojto 71:53949e6131f6 603 // Remaining endpoint state values
Kojto 71:53949e6131f6 604 endpointState[endpoint].maxPacket = maxPacket;
Kojto 71:53949e6131f6 605 endpointState[endpoint].options = options;
Kojto 71:53949e6131f6 606
Kojto 71:53949e6131f6 607 // Enable double buffering if required
Kojto 71:53949e6131f6 608 if (options & SINGLE_BUFFERED) {
Kojto 71:53949e6131f6 609 LPC_USB->EPBUFCFG &= ~EP(endpoint);
Kojto 71:53949e6131f6 610 } else {
Kojto 71:53949e6131f6 611 // Double buffered
Kojto 71:53949e6131f6 612 LPC_USB->EPBUFCFG |= EP(endpoint);
Kojto 71:53949e6131f6 613 }
Kojto 71:53949e6131f6 614
Kojto 71:53949e6131f6 615 // Enable interrupt
Kojto 71:53949e6131f6 616 LPC_USB->INTEN |= EP(endpoint);
Kojto 71:53949e6131f6 617
Kojto 71:53949e6131f6 618 // Enable endpoint
Kojto 71:53949e6131f6 619 unstallEndpoint(endpoint);
Kojto 71:53949e6131f6 620 return true;
Kojto 71:53949e6131f6 621 }
Kojto 71:53949e6131f6 622
Kojto 71:53949e6131f6 623 void USBHAL::remoteWakeup(void) {
Kojto 71:53949e6131f6 624 // Clearing DSUS bit initiates a remote wakeup if the
Kojto 71:53949e6131f6 625 // device is currently enabled and suspended - otherwise
Kojto 71:53949e6131f6 626 // it has no effect.
Kojto 71:53949e6131f6 627 LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
Kojto 71:53949e6131f6 628 }
Kojto 71:53949e6131f6 629
Kojto 71:53949e6131f6 630
Kojto 71:53949e6131f6 631 static void disableEndpoints(void) {
Kojto 71:53949e6131f6 632 uint32_t logEp;
Kojto 71:53949e6131f6 633
Kojto 71:53949e6131f6 634 // Ref. Table 158 "When a bus reset is received, software
Kojto 71:53949e6131f6 635 // must set the disable bit of all endpoints to 1".
Kojto 71:53949e6131f6 636
Kojto 71:53949e6131f6 637 for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) {
Kojto 71:53949e6131f6 638 ep[logEp].out[0] = CMDSTS_D;
Kojto 71:53949e6131f6 639 ep[logEp].out[1] = CMDSTS_D;
Kojto 71:53949e6131f6 640 ep[logEp].in[0] = CMDSTS_D;
Kojto 71:53949e6131f6 641 ep[logEp].in[1] = CMDSTS_D;
Kojto 71:53949e6131f6 642 }
Kojto 71:53949e6131f6 643
Kojto 71:53949e6131f6 644 // Start of USB RAM for endpoints > 0
Kojto 71:53949e6131f6 645 epRamPtr = usbRamPtr;
Kojto 71:53949e6131f6 646 }
Kojto 71:53949e6131f6 647
Kojto 71:53949e6131f6 648
Kojto 71:53949e6131f6 649
Kojto 71:53949e6131f6 650 void USBHAL::_usbisr(void) {
Kojto 71:53949e6131f6 651 instance->usbisr();
Kojto 71:53949e6131f6 652 }
Kojto 71:53949e6131f6 653
Kojto 71:53949e6131f6 654 void USBHAL::usbisr(void) {
Kojto 71:53949e6131f6 655 // Start of frame
Kojto 71:53949e6131f6 656 if (LPC_USB->INTSTAT & FRAME_INT) {
Kojto 71:53949e6131f6 657 // Clear SOF interrupt
Kojto 71:53949e6131f6 658 LPC_USB->INTSTAT = FRAME_INT;
Kojto 71:53949e6131f6 659
Kojto 71:53949e6131f6 660 // SOF event, read frame number
Kojto 71:53949e6131f6 661 SOF(FRAME_NR(LPC_USB->INFO));
Kojto 71:53949e6131f6 662 }
Kojto 71:53949e6131f6 663
Kojto 71:53949e6131f6 664 // Device state
Kojto 71:53949e6131f6 665 if (LPC_USB->INTSTAT & DEV_INT) {
Kojto 71:53949e6131f6 666 LPC_USB->INTSTAT = DEV_INT;
Kojto 71:53949e6131f6 667
Kojto 71:53949e6131f6 668 if (LPC_USB->DEVCMDSTAT & DSUS_C) {
Kojto 71:53949e6131f6 669 // Suspend status changed
Kojto 71:53949e6131f6 670 LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
Kojto 71:53949e6131f6 671 if (LPC_USB->DEVCMDSTAT & DSUS) {
Kojto 71:53949e6131f6 672 suspendStateChanged(1);
Kojto 71:53949e6131f6 673 } else {
Kojto 71:53949e6131f6 674 suspendStateChanged(0);
Kojto 71:53949e6131f6 675 }
Kojto 71:53949e6131f6 676 }
Kojto 71:53949e6131f6 677
Kojto 71:53949e6131f6 678 if (LPC_USB->DEVCMDSTAT & DRES_C) {
Kojto 71:53949e6131f6 679 // Bus reset
Kojto 71:53949e6131f6 680 LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
Kojto 71:53949e6131f6 681
Kojto 71:53949e6131f6 682 // Disable endpoints > 0
Kojto 71:53949e6131f6 683 disableEndpoints();
Kojto 71:53949e6131f6 684
Kojto 71:53949e6131f6 685 // Bus reset event
Kojto 71:53949e6131f6 686 busReset();
Kojto 71:53949e6131f6 687 }
Kojto 71:53949e6131f6 688 }
Kojto 71:53949e6131f6 689
Kojto 71:53949e6131f6 690 // Endpoint 0
Kojto 71:53949e6131f6 691 if (LPC_USB->INTSTAT & EP(EP0OUT)) {
Kojto 71:53949e6131f6 692 // Clear EP0OUT/SETUP interrupt
Kojto 71:53949e6131f6 693 LPC_USB->INTSTAT = EP(EP0OUT);
Kojto 71:53949e6131f6 694
Kojto 71:53949e6131f6 695 // Check if SETUP
Kojto 71:53949e6131f6 696 if (LPC_USB->DEVCMDSTAT & SETUP) {
Kojto 71:53949e6131f6 697 // Clear Active and Stall bits for EP0
Kojto 71:53949e6131f6 698 // Documentation does not make it clear if we must use the
Kojto 71:53949e6131f6 699 // EPSKIP register to achieve this, Fig. 16 and NXP reference
Kojto 71:53949e6131f6 700 // code suggests we can just clear the Active bits - check with
Kojto 71:53949e6131f6 701 // NXP to be sure.
Kojto 71:53949e6131f6 702 ep[0].in[0] = 0;
Kojto 71:53949e6131f6 703 ep[0].out[0] = 0;
Kojto 71:53949e6131f6 704
Kojto 71:53949e6131f6 705 // Clear EP0IN interrupt
Kojto 71:53949e6131f6 706 LPC_USB->INTSTAT = EP(EP0IN);
Kojto 71:53949e6131f6 707
Kojto 71:53949e6131f6 708 // Clear SETUP (and INTONNAK_CI/O) in device status register
Kojto 71:53949e6131f6 709 LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
Kojto 71:53949e6131f6 710
Kojto 71:53949e6131f6 711 // EP0 SETUP event (SETUP data received)
Kojto 71:53949e6131f6 712 EP0setupCallback();
Kojto 71:53949e6131f6 713 } else {
Kojto 71:53949e6131f6 714 // EP0OUT ACK event (OUT data received)
Kojto 71:53949e6131f6 715 EP0out();
Kojto 71:53949e6131f6 716 }
Kojto 71:53949e6131f6 717 }
Kojto 71:53949e6131f6 718
Kojto 71:53949e6131f6 719 if (LPC_USB->INTSTAT & EP(EP0IN)) {
Kojto 71:53949e6131f6 720 // Clear EP0IN interrupt
Kojto 71:53949e6131f6 721 LPC_USB->INTSTAT = EP(EP0IN);
Kojto 71:53949e6131f6 722
Kojto 71:53949e6131f6 723 // EP0IN ACK event (IN data sent)
Kojto 71:53949e6131f6 724 EP0in();
Kojto 71:53949e6131f6 725 }
Kojto 71:53949e6131f6 726
Kojto 71:53949e6131f6 727 for (uint8_t num = 2; num < 5*2; num++) {
Kojto 71:53949e6131f6 728 if (LPC_USB->INTSTAT & EP(num)) {
Kojto 71:53949e6131f6 729 LPC_USB->INTSTAT = EP(num);
Kojto 71:53949e6131f6 730 epComplete |= EP(num);
Kojto 71:53949e6131f6 731 if ((instance->*(epCallback[num - 2]))()) {
Kojto 71:53949e6131f6 732 epComplete &= ~EP(num);
Kojto 71:53949e6131f6 733 }
Kojto 71:53949e6131f6 734 }
Kojto 71:53949e6131f6 735 }
Kojto 71:53949e6131f6 736 }
Kojto 71:53949e6131f6 737
Kojto 71:53949e6131f6 738 #endif