USB device stack

Dependents:   mbed-mX-USB-TEST1 USBMSD_SD_HID_HelloWorld HidTest MIDI_usb_bridge ... more

Legacy Warning

This is an mbed 2 library. To learn more about mbed OS 5, visit the docs.

Pull requests against this repository are no longer supported. Please raise against mbed OS 5 as documented above.

Committer:
Kojto
Date:
Thu Jul 27 12:14:04 2017 +0100
Revision:
71:53949e6131f6
Update libraries

Fixes the previous commmit, as some devices were not copied. USBDevice contains
now targets directory with all targets implementations

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Kojto 71:53949e6131f6 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
Kojto 71:53949e6131f6 2 *
Kojto 71:53949e6131f6 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
Kojto 71:53949e6131f6 4 * and associated documentation files (the "Software"), to deal in the Software without
Kojto 71:53949e6131f6 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
Kojto 71:53949e6131f6 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
Kojto 71:53949e6131f6 7 * Software is furnished to do so, subject to the following conditions:
Kojto 71:53949e6131f6 8 *
Kojto 71:53949e6131f6 9 * The above copyright notice and this permission notice shall be included in all copies or
Kojto 71:53949e6131f6 10 * substantial portions of the Software.
Kojto 71:53949e6131f6 11 *
Kojto 71:53949e6131f6 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
Kojto 71:53949e6131f6 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Kojto 71:53949e6131f6 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
Kojto 71:53949e6131f6 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Kojto 71:53949e6131f6 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Kojto 71:53949e6131f6 17 */
Kojto 71:53949e6131f6 18
Kojto 71:53949e6131f6 19 #if defined(TARGET_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