The preloaded firmware shipped on the mBot.

Dependencies:   mbed

Fork of Official_mBot by Fred Parker

Committer:
jeffknaggs
Date:
Tue Nov 25 14:49:40 2014 +0000
Revision:
1:ffd9a51e7d35
Parent:
0:865d42c46692
Initial commit.

Who changed what in which revision?

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