Preliminary main mbed library for nexpaq development

Committer:
nexpaq
Date:
Fri Nov 04 20:54:50 2016 +0000
Revision:
1:d96dbedaebdb
Parent:
0:6c56fb4bc5f0
Removed extra directories for other platforms

Who changed what in which revision?

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