I changed one line of code in the file with path name: USBDeviceHT/targets/TARGET_Maxim

Fork of USBDeviceHT by Helmut Tschemernjak

Committer:
Helmut64
Date:
Mon Feb 05 10:22:57 2018 +0000
Revision:
0:a3ea811f80f2
Inital checkin after copied from mbed.

Who changed what in which revision?

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