max4146x_comp

Dependencies:   MAX14690

Committer:
sdivarci
Date:
Sun Oct 25 20:10:02 2020 +0000
Revision:
0:0061165683ee
sdivarci

Who changed what in which revision?

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