works!

Dependencies:   mbed

Committer:
kchhouk
Date:
Fri Feb 21 21:03:41 2020 +0000
Revision:
2:5e5cdc3504fe
Parent:
1:6e512faaa17c
Added the functionality of scanf

Who changed what in which revision?

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