Fork of the official USBDevice library

Fork of USBDevice by mbed official

Committer:
screamer
Date:
Fri Apr 28 17:01:10 2017 +0000
Branch:
device-files
Revision:
76:f0fd8d911b24
Parent:
USBDevice/USBHAL_LPC11U.cpp@73:8d28a0cb7b43
Changed the layout of USBDevice implementation for various targets to match mbed-os/targets. This also reduces the amount of files being compiled as USBDevice code for other targets is not compiled.

Who changed what in which revision?

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