Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 /**
Pawel Zarembski 0:01f31e923fe2 2 * @file usbd_LPC11Uxx.c
Pawel Zarembski 0:01f31e923fe2 3 * @brief
Pawel Zarembski 0:01f31e923fe2 4 *
Pawel Zarembski 0:01f31e923fe2 5 * DAPLink Interface Firmware
Pawel Zarembski 0:01f31e923fe2 6 * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved
Pawel Zarembski 0:01f31e923fe2 7 * SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 8 *
Pawel Zarembski 0:01f31e923fe2 9 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 10 * not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 11 * You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 12 *
Pawel Zarembski 0:01f31e923fe2 13 * http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 14 *
Pawel Zarembski 0:01f31e923fe2 15 * Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 16 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 17 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 18 * See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 19 * limitations under the License.
Pawel Zarembski 0:01f31e923fe2 20 */
Pawel Zarembski 0:01f31e923fe2 21
Pawel Zarembski 0:01f31e923fe2 22 #include "rl_usb.h"
Pawel Zarembski 0:01f31e923fe2 23 #include "LPC11Uxx.h"
Pawel Zarembski 0:01f31e923fe2 24 #include "compiler.h"
Pawel Zarembski 0:01f31e923fe2 25 #include "util.h"
Pawel Zarembski 0:01f31e923fe2 26
Pawel Zarembski 0:01f31e923fe2 27 #define __NO_USB_LIB_C
Pawel Zarembski 0:01f31e923fe2 28 #include "usb_config.c"
Pawel Zarembski 0:01f31e923fe2 29
Pawel Zarembski 0:01f31e923fe2 30
Pawel Zarembski 0:01f31e923fe2 31 #define BUF_ACTIVE (1UL << 31)
Pawel Zarembski 0:01f31e923fe2 32 #define EP_DISABLED (1UL << 30)
Pawel Zarembski 0:01f31e923fe2 33 #define EP_STALL (1UL << 29)
Pawel Zarembski 0:01f31e923fe2 34 #define TOOGLE_RESET (1UL << 28)
Pawel Zarembski 0:01f31e923fe2 35 #define EP_TYPE (1UL << 26)
Pawel Zarembski 0:01f31e923fe2 36
Pawel Zarembski 0:01f31e923fe2 37 #define N_BYTES(n) ((n & 0x3FF) << 16)
Pawel Zarembski 0:01f31e923fe2 38 #define BUF_ADDR(addr) (((addr) >> 6) & 0xFFFF)
Pawel Zarembski 0:01f31e923fe2 39
Pawel Zarembski 0:01f31e923fe2 40 #define EP_OUT_IDX(EPNum) (EPNum * 2 )
Pawel Zarembski 0:01f31e923fe2 41 #define EP_IN_IDX(EPNum) (EPNum * 2 + 1)
Pawel Zarembski 0:01f31e923fe2 42
Pawel Zarembski 0:01f31e923fe2 43 #define EP_LIST_BASE 0x20004000
Pawel Zarembski 0:01f31e923fe2 44 #define EP_BUF_BASE (U32)(EP_LIST_BASE + 0x100)
Pawel Zarembski 0:01f31e923fe2 45
Pawel Zarembski 0:01f31e923fe2 46 typedef struct BUF_INFO {
Pawel Zarembski 0:01f31e923fe2 47 U32 buf_len;
Pawel Zarembski 0:01f31e923fe2 48 U32 buf_ptr;
Pawel Zarembski 0:01f31e923fe2 49 } EP_BUF_INFO;
Pawel Zarembski 0:01f31e923fe2 50
Pawel Zarembski 0:01f31e923fe2 51 EP_BUF_INFO EPBufInfo[(USBD_EP_NUM + 1) * 2];
Pawel Zarembski 0:01f31e923fe2 52 volatile U32 EPList[(USBD_EP_NUM + 1) * 2] __at(EP_LIST_BASE);
Pawel Zarembski 0:01f31e923fe2 53
Pawel Zarembski 0:01f31e923fe2 54 static U32 addr = 3 * 64 + EP_BUF_BASE;
Pawel Zarembski 0:01f31e923fe2 55 static U32 ctrl_out_next = 0;
Pawel Zarembski 0:01f31e923fe2 56
Pawel Zarembski 0:01f31e923fe2 57 /*
Pawel Zarembski 0:01f31e923fe2 58 * Get EP CmdStat pointer
Pawel Zarembski 0:01f31e923fe2 59 * Parameters: EPNum: endpoint number
Pawel Zarembski 0:01f31e923fe2 60 *
Pawel Zarembski 0:01f31e923fe2 61 */
Pawel Zarembski 0:01f31e923fe2 62
Pawel Zarembski 0:01f31e923fe2 63 U32 *GetEpCmdStatPtr(U32 EPNum)
Pawel Zarembski 0:01f31e923fe2 64 {
Pawel Zarembski 0:01f31e923fe2 65 U32 ptr = 0;
Pawel Zarembski 0:01f31e923fe2 66
Pawel Zarembski 0:01f31e923fe2 67 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 68 EPNum &= ~0x80;
Pawel Zarembski 0:01f31e923fe2 69 ptr = 8;
Pawel Zarembski 0:01f31e923fe2 70 }
Pawel Zarembski 0:01f31e923fe2 71
Pawel Zarembski 0:01f31e923fe2 72 ptr += EP_LIST_BASE + EPNum * 16;
Pawel Zarembski 0:01f31e923fe2 73 return ((U32 *)ptr);
Pawel Zarembski 0:01f31e923fe2 74 }
Pawel Zarembski 0:01f31e923fe2 75
Pawel Zarembski 0:01f31e923fe2 76
Pawel Zarembski 0:01f31e923fe2 77 /*
Pawel Zarembski 0:01f31e923fe2 78 * Usb interrupt enable/disable
Pawel Zarembski 0:01f31e923fe2 79 * Parameters: ena: enable/disable
Pawel Zarembski 0:01f31e923fe2 80 * 0: disable interrupt
Pawel Zarembski 0:01f31e923fe2 81 * 1: enable interrupt
Pawel Zarembski 0:01f31e923fe2 82 */
Pawel Zarembski 0:01f31e923fe2 83
Pawel Zarembski 0:01f31e923fe2 84 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 85 void __svc(1) USBD_Intr(int ena);
Pawel Zarembski 0:01f31e923fe2 86 void __SVC_1(int ena)
Pawel Zarembski 0:01f31e923fe2 87 {
Pawel Zarembski 0:01f31e923fe2 88 if (ena) {
Pawel Zarembski 0:01f31e923fe2 89 NVIC_EnableIRQ(USB_IRQn); /* Enable USB interrupt */
Pawel Zarembski 0:01f31e923fe2 90 } else {
Pawel Zarembski 0:01f31e923fe2 91 NVIC_DisableIRQ(USB_IRQn); /* Disable USB interrupt */
Pawel Zarembski 0:01f31e923fe2 92 }
Pawel Zarembski 0:01f31e923fe2 93 }
Pawel Zarembski 0:01f31e923fe2 94 #endif
Pawel Zarembski 0:01f31e923fe2 95
Pawel Zarembski 0:01f31e923fe2 96
Pawel Zarembski 0:01f31e923fe2 97
Pawel Zarembski 0:01f31e923fe2 98 /*
Pawel Zarembski 0:01f31e923fe2 99 * USB Device Initialize Function
Pawel Zarembski 0:01f31e923fe2 100 * Called by the User to initialize USB Device
Pawel Zarembski 0:01f31e923fe2 101 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 102 */
Pawel Zarembski 0:01f31e923fe2 103
Pawel Zarembski 0:01f31e923fe2 104 void USBD_Init(void)
Pawel Zarembski 0:01f31e923fe2 105 {
Pawel Zarembski 0:01f31e923fe2 106 LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 6);
Pawel Zarembski 0:01f31e923fe2 107 LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 14) |
Pawel Zarembski 0:01f31e923fe2 108 (1UL << 27);
Pawel Zarembski 0:01f31e923fe2 109 LPC_USB->DEVCMDSTAT |= (1UL << 9); /* PLL ON */
Pawel Zarembski 0:01f31e923fe2 110 LPC_IOCON->PIO0_3 &= ~(0x1F);
Pawel Zarembski 0:01f31e923fe2 111 LPC_IOCON->PIO0_3 |= (1UL << 0); /* Secondary function VBUS */
Pawel Zarembski 0:01f31e923fe2 112 LPC_IOCON->PIO0_6 &= ~7;
Pawel Zarembski 0:01f31e923fe2 113 LPC_IOCON->PIO0_6 |= (1UL << 0); /* Secondary function USB CON */
Pawel Zarembski 0:01f31e923fe2 114 LPC_SYSCON->PDRUNCFG &= ~((1UL << 8) | /* USB PLL powered */
Pawel Zarembski 0:01f31e923fe2 115 (1UL << 10)); /* USB transceiver powered */
Pawel Zarembski 0:01f31e923fe2 116 LPC_USB->DATABUFSTART = EP_BUF_BASE & 0xFFC00000;
Pawel Zarembski 0:01f31e923fe2 117 LPC_USB->EPLISTSTART = EP_LIST_BASE;
Pawel Zarembski 0:01f31e923fe2 118 NVIC_EnableIRQ(USB_IRQn);
Pawel Zarembski 0:01f31e923fe2 119 USBD_Reset();
Pawel Zarembski 0:01f31e923fe2 120 }
Pawel Zarembski 0:01f31e923fe2 121
Pawel Zarembski 0:01f31e923fe2 122
Pawel Zarembski 0:01f31e923fe2 123 /*
Pawel Zarembski 0:01f31e923fe2 124 * USB Device Connect Function
Pawel Zarembski 0:01f31e923fe2 125 * Called by the User to Connect/Disconnect USB Device
Pawel Zarembski 0:01f31e923fe2 126 * Parameters: con: Connect/Disconnect
Pawel Zarembski 0:01f31e923fe2 127 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 128 */
Pawel Zarembski 0:01f31e923fe2 129
Pawel Zarembski 0:01f31e923fe2 130 void USBD_Connect(BOOL con)
Pawel Zarembski 0:01f31e923fe2 131 {
Pawel Zarembski 0:01f31e923fe2 132 if (con) {
Pawel Zarembski 0:01f31e923fe2 133 LPC_USB->DEVCMDSTAT |= (1UL << 16); /* Set device connect status */
Pawel Zarembski 0:01f31e923fe2 134 } else {
Pawel Zarembski 0:01f31e923fe2 135 LPC_USB->DEVCMDSTAT &= ~(1UL << 16); /* Clear device connect status */
Pawel Zarembski 0:01f31e923fe2 136 }
Pawel Zarembski 0:01f31e923fe2 137
Pawel Zarembski 0:01f31e923fe2 138 return;
Pawel Zarembski 0:01f31e923fe2 139 }
Pawel Zarembski 0:01f31e923fe2 140
Pawel Zarembski 0:01f31e923fe2 141
Pawel Zarembski 0:01f31e923fe2 142 /*
Pawel Zarembski 0:01f31e923fe2 143 * USB Device Reset Function
Pawel Zarembski 0:01f31e923fe2 144 * Called automatically on USB Device Reset
Pawel Zarembski 0:01f31e923fe2 145 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 146 */
Pawel Zarembski 0:01f31e923fe2 147
Pawel Zarembski 0:01f31e923fe2 148 void USBD_Reset(void)
Pawel Zarembski 0:01f31e923fe2 149 {
Pawel Zarembski 0:01f31e923fe2 150 U32 i;
Pawel Zarembski 0:01f31e923fe2 151 U32 *ptr;
Pawel Zarembski 0:01f31e923fe2 152 addr = 3 * 64 + EP_BUF_BASE;
Pawel Zarembski 0:01f31e923fe2 153
Pawel Zarembski 0:01f31e923fe2 154 for (i = 2; i < (5 * 4); i++) {
Pawel Zarembski 0:01f31e923fe2 155 EPList[i] = (1UL << 30); /* EPs disabled */
Pawel Zarembski 0:01f31e923fe2 156 }
Pawel Zarembski 0:01f31e923fe2 157
Pawel Zarembski 0:01f31e923fe2 158 ctrl_out_next = 0;
Pawel Zarembski 0:01f31e923fe2 159 EPBufInfo[0].buf_len = USBD_MAX_PACKET0;
Pawel Zarembski 0:01f31e923fe2 160 EPBufInfo[0].buf_ptr = EP_BUF_BASE;
Pawel Zarembski 0:01f31e923fe2 161 EPBufInfo[1].buf_len = USBD_MAX_PACKET0;
Pawel Zarembski 0:01f31e923fe2 162 EPBufInfo[1].buf_ptr = EP_BUF_BASE + 2 * 64;
Pawel Zarembski 0:01f31e923fe2 163 ptr = GetEpCmdStatPtr(0);
Pawel Zarembski 0:01f31e923fe2 164 *ptr = N_BYTES(EPBufInfo[0].buf_len) | /* EP0 OUT */
Pawel Zarembski 0:01f31e923fe2 165 BUF_ADDR(EPBufInfo[0].buf_ptr) |
Pawel Zarembski 0:01f31e923fe2 166 BUF_ACTIVE;
Pawel Zarembski 0:01f31e923fe2 167 ptr++;
Pawel Zarembski 0:01f31e923fe2 168 *ptr = BUF_ADDR(EPBufInfo[0].buf_ptr + 64);/* SETUP */
Pawel Zarembski 0:01f31e923fe2 169 LPC_USB->DEVCMDSTAT |= (1UL << 7); /*USB device enable */
Pawel Zarembski 0:01f31e923fe2 170 LPC_USB->INTSTAT = 0x2FC; /* clear EP interrupt flags */
Pawel Zarembski 0:01f31e923fe2 171 LPC_USB->INTEN = ((1UL << 30) | /* SOF intr enable */
Pawel Zarembski 0:01f31e923fe2 172 (1UL << 0) | /* EP0 OUT intr enable */
Pawel Zarembski 0:01f31e923fe2 173 (1UL << 1) | /* EP0 IN intr enable */
Pawel Zarembski 0:01f31e923fe2 174 (1UL << 31)); /* stat change int en */
Pawel Zarembski 0:01f31e923fe2 175 }
Pawel Zarembski 0:01f31e923fe2 176
Pawel Zarembski 0:01f31e923fe2 177
Pawel Zarembski 0:01f31e923fe2 178 /*
Pawel Zarembski 0:01f31e923fe2 179 * USB Device Suspend Function
Pawel Zarembski 0:01f31e923fe2 180 * Called automatically on USB Device Suspend
Pawel Zarembski 0:01f31e923fe2 181 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 182 */
Pawel Zarembski 0:01f31e923fe2 183
Pawel Zarembski 0:01f31e923fe2 184 void USBD_Suspend(void)
Pawel Zarembski 0:01f31e923fe2 185 {
Pawel Zarembski 0:01f31e923fe2 186 /* Performed by Hardware */
Pawel Zarembski 0:01f31e923fe2 187 }
Pawel Zarembski 0:01f31e923fe2 188
Pawel Zarembski 0:01f31e923fe2 189
Pawel Zarembski 0:01f31e923fe2 190 /*
Pawel Zarembski 0:01f31e923fe2 191 * USB Device Resume Function
Pawel Zarembski 0:01f31e923fe2 192 * Called automatically on USB Device Resume
Pawel Zarembski 0:01f31e923fe2 193 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 194 */
Pawel Zarembski 0:01f31e923fe2 195
Pawel Zarembski 0:01f31e923fe2 196 void USBD_Resume(void)
Pawel Zarembski 0:01f31e923fe2 197 {
Pawel Zarembski 0:01f31e923fe2 198 /* Performed by Hardware */
Pawel Zarembski 0:01f31e923fe2 199 }
Pawel Zarembski 0:01f31e923fe2 200
Pawel Zarembski 0:01f31e923fe2 201
Pawel Zarembski 0:01f31e923fe2 202 /*
Pawel Zarembski 0:01f31e923fe2 203 * USB Device Remote Wakeup Function
Pawel Zarembski 0:01f31e923fe2 204 * Called automatically on USB Device Remote Wakeup
Pawel Zarembski 0:01f31e923fe2 205 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 206 */
Pawel Zarembski 0:01f31e923fe2 207
Pawel Zarembski 0:01f31e923fe2 208 void USBD_WakeUp(void)
Pawel Zarembski 0:01f31e923fe2 209 {
Pawel Zarembski 0:01f31e923fe2 210 LPC_SYSCON->USBCLKCTRL = 1;
Pawel Zarembski 0:01f31e923fe2 211 LPC_USB->DEVCMDSTAT &= ~(1UL << 17); /*clear device suspend status */
Pawel Zarembski 0:01f31e923fe2 212
Pawel Zarembski 0:01f31e923fe2 213 while (LPC_USB->DEVCMDSTAT & (1UL << 17));
Pawel Zarembski 0:01f31e923fe2 214
Pawel Zarembski 0:01f31e923fe2 215 LPC_SYSCON->USBCLKCTRL = 0;
Pawel Zarembski 0:01f31e923fe2 216 }
Pawel Zarembski 0:01f31e923fe2 217
Pawel Zarembski 0:01f31e923fe2 218
Pawel Zarembski 0:01f31e923fe2 219 /*
Pawel Zarembski 0:01f31e923fe2 220 * USB Device Remote Wakeup Configuration Function
Pawel Zarembski 0:01f31e923fe2 221 * Parameters: cfg: Device Enable/Disable
Pawel Zarembski 0:01f31e923fe2 222 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 223 */
Pawel Zarembski 0:01f31e923fe2 224
Pawel Zarembski 0:01f31e923fe2 225 void USBD_WakeUpCfg(BOOL cfg)
Pawel Zarembski 0:01f31e923fe2 226 {
Pawel Zarembski 0:01f31e923fe2 227 if (cfg == __TRUE) {
Pawel Zarembski 0:01f31e923fe2 228 LPC_USB->DEVCMDSTAT &= ~(1UL << 9); /*PPL_ON=0, in suspend clk is stoped */
Pawel Zarembski 0:01f31e923fe2 229 } else {
Pawel Zarembski 0:01f31e923fe2 230 LPC_USB->DEVCMDSTAT |= (1UL << 9); /*PPL_ON=1, in suspend clk isnt stoped */
Pawel Zarembski 0:01f31e923fe2 231 LPC_SYSCON->USBCLKCTRL = 0;
Pawel Zarembski 0:01f31e923fe2 232 }
Pawel Zarembski 0:01f31e923fe2 233 }
Pawel Zarembski 0:01f31e923fe2 234
Pawel Zarembski 0:01f31e923fe2 235
Pawel Zarembski 0:01f31e923fe2 236 /*
Pawel Zarembski 0:01f31e923fe2 237 * USB Device Set Address Function
Pawel Zarembski 0:01f31e923fe2 238 * Parameters: adr: USB Device Address
Pawel Zarembski 0:01f31e923fe2 239 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 240 */
Pawel Zarembski 0:01f31e923fe2 241
Pawel Zarembski 0:01f31e923fe2 242 void USBD_SetAddress(U32 adr, U32 setup)
Pawel Zarembski 0:01f31e923fe2 243 {
Pawel Zarembski 0:01f31e923fe2 244 if (!setup) {
Pawel Zarembski 0:01f31e923fe2 245 LPC_USB->DEVCMDSTAT &= ~0x7F;
Pawel Zarembski 0:01f31e923fe2 246 LPC_USB->DEVCMDSTAT |= adr | (1UL << 7);
Pawel Zarembski 0:01f31e923fe2 247 }
Pawel Zarembski 0:01f31e923fe2 248 }
Pawel Zarembski 0:01f31e923fe2 249
Pawel Zarembski 0:01f31e923fe2 250
Pawel Zarembski 0:01f31e923fe2 251
Pawel Zarembski 0:01f31e923fe2 252 /*
Pawel Zarembski 0:01f31e923fe2 253 * USB Device Configure Function
Pawel Zarembski 0:01f31e923fe2 254 * Parameters: cfg: Device Configure/Deconfigure
Pawel Zarembski 0:01f31e923fe2 255 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 256 */
Pawel Zarembski 0:01f31e923fe2 257
Pawel Zarembski 0:01f31e923fe2 258 void USBD_Configure(BOOL cfg)
Pawel Zarembski 0:01f31e923fe2 259 {
Pawel Zarembski 0:01f31e923fe2 260 addr = 3 * 64 + EP_BUF_BASE;
Pawel Zarembski 0:01f31e923fe2 261 }
Pawel Zarembski 0:01f31e923fe2 262
Pawel Zarembski 0:01f31e923fe2 263
Pawel Zarembski 0:01f31e923fe2 264 /*
Pawel Zarembski 0:01f31e923fe2 265 * Configure USB Device Endpoint according to Descriptor
Pawel Zarembski 0:01f31e923fe2 266 * Parameters: pEPD: Pointer to Device Endpoint Descriptor
Pawel Zarembski 0:01f31e923fe2 267 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 268 */
Pawel Zarembski 0:01f31e923fe2 269
Pawel Zarembski 0:01f31e923fe2 270 void USBD_ConfigEP(USB_ENDPOINT_DESCRIPTOR *pEPD)
Pawel Zarembski 0:01f31e923fe2 271 {
Pawel Zarembski 0:01f31e923fe2 272 U32 num, val, type;
Pawel Zarembski 0:01f31e923fe2 273 U32 *ptr;
Pawel Zarembski 0:01f31e923fe2 274 num = pEPD->bEndpointAddress;
Pawel Zarembski 0:01f31e923fe2 275 val = pEPD->wMaxPacketSize;
Pawel Zarembski 0:01f31e923fe2 276 type = pEPD->bmAttributes & USB_ENDPOINT_TYPE_MASK;
Pawel Zarembski 0:01f31e923fe2 277
Pawel Zarembski 0:01f31e923fe2 278 /* IN EPs */
Pawel Zarembski 0:01f31e923fe2 279 if (num & 0x80) {
Pawel Zarembski 0:01f31e923fe2 280 num &= ~0x80;
Pawel Zarembski 0:01f31e923fe2 281 EPBufInfo[EP_IN_IDX(num)].buf_len = val;
Pawel Zarembski 0:01f31e923fe2 282 EPBufInfo[EP_IN_IDX(num)].buf_ptr = addr;
Pawel Zarembski 0:01f31e923fe2 283 addr += ((val + 63) >> 6) * 64; /* calc new free buffer address */
Pawel Zarembski 0:01f31e923fe2 284 ptr = GetEpCmdStatPtr(num | 0x80);
Pawel Zarembski 0:01f31e923fe2 285 *ptr = EP_DISABLED;
Pawel Zarembski 0:01f31e923fe2 286
Pawel Zarembski 0:01f31e923fe2 287 if (type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
Pawel Zarembski 0:01f31e923fe2 288 *ptr |= EP_TYPE;
Pawel Zarembski 0:01f31e923fe2 289 }
Pawel Zarembski 0:01f31e923fe2 290 }
Pawel Zarembski 0:01f31e923fe2 291
Pawel Zarembski 0:01f31e923fe2 292 /* OUT EPs */
Pawel Zarembski 0:01f31e923fe2 293 else {
Pawel Zarembski 0:01f31e923fe2 294 EPBufInfo[EP_OUT_IDX(num)].buf_len = val;
Pawel Zarembski 0:01f31e923fe2 295 EPBufInfo[EP_OUT_IDX(num)].buf_ptr = addr;
Pawel Zarembski 0:01f31e923fe2 296 ptr = GetEpCmdStatPtr(num);
Pawel Zarembski 0:01f31e923fe2 297 *ptr = N_BYTES(EPBufInfo[EP_OUT_IDX(num)].buf_len) |
Pawel Zarembski 0:01f31e923fe2 298 BUF_ADDR(EPBufInfo[EP_OUT_IDX(num)].buf_ptr) |
Pawel Zarembski 0:01f31e923fe2 299 EP_DISABLED;
Pawel Zarembski 0:01f31e923fe2 300
Pawel Zarembski 0:01f31e923fe2 301 if (type == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
Pawel Zarembski 0:01f31e923fe2 302 *ptr |= EP_TYPE;
Pawel Zarembski 0:01f31e923fe2 303 }
Pawel Zarembski 0:01f31e923fe2 304
Pawel Zarembski 0:01f31e923fe2 305 addr += ((val + 63) >> 6) * 64; /* calc new free buffer address */
Pawel Zarembski 0:01f31e923fe2 306 }
Pawel Zarembski 0:01f31e923fe2 307 }
Pawel Zarembski 0:01f31e923fe2 308
Pawel Zarembski 0:01f31e923fe2 309
Pawel Zarembski 0:01f31e923fe2 310 /*
Pawel Zarembski 0:01f31e923fe2 311 * Set Direction for USB Device Control Endpoint
Pawel Zarembski 0:01f31e923fe2 312 * Parameters: dir: Out (dir == 0), In (dir <> 0)
Pawel Zarembski 0:01f31e923fe2 313 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 314 */
Pawel Zarembski 0:01f31e923fe2 315
Pawel Zarembski 0:01f31e923fe2 316 void USBD_DirCtrlEP(U32 dir)
Pawel Zarembski 0:01f31e923fe2 317 {
Pawel Zarembski 0:01f31e923fe2 318 /* Not needed */
Pawel Zarembski 0:01f31e923fe2 319 }
Pawel Zarembski 0:01f31e923fe2 320
Pawel Zarembski 0:01f31e923fe2 321
Pawel Zarembski 0:01f31e923fe2 322 /*
Pawel Zarembski 0:01f31e923fe2 323 * Enable USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 324 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 325 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 326 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 327 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 328 */
Pawel Zarembski 0:01f31e923fe2 329
Pawel Zarembski 0:01f31e923fe2 330 void USBD_EnableEP(U32 EPNum)
Pawel Zarembski 0:01f31e923fe2 331 {
Pawel Zarembski 0:01f31e923fe2 332 U32 *ptr;;
Pawel Zarembski 0:01f31e923fe2 333 ptr = GetEpCmdStatPtr(EPNum);
Pawel Zarembski 0:01f31e923fe2 334
Pawel Zarembski 0:01f31e923fe2 335 /* IN EP */
Pawel Zarembski 0:01f31e923fe2 336 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 337 EPNum &= ~0x80;
Pawel Zarembski 0:01f31e923fe2 338 *ptr &= ~EP_DISABLED;
Pawel Zarembski 0:01f31e923fe2 339 LPC_USB->INTSTAT = (1 << EP_IN_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 340 LPC_USB->INTEN |= (1 << EP_IN_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 341 }
Pawel Zarembski 0:01f31e923fe2 342
Pawel Zarembski 0:01f31e923fe2 343 /* OUT EP */
Pawel Zarembski 0:01f31e923fe2 344 else {
Pawel Zarembski 0:01f31e923fe2 345 *ptr &= ~EP_DISABLED;
Pawel Zarembski 0:01f31e923fe2 346 *ptr |= BUF_ACTIVE;
Pawel Zarembski 0:01f31e923fe2 347 LPC_USB->INTSTAT = (1 << EP_OUT_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 348 LPC_USB->INTEN |= (1 << EP_OUT_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 349 }
Pawel Zarembski 0:01f31e923fe2 350 }
Pawel Zarembski 0:01f31e923fe2 351
Pawel Zarembski 0:01f31e923fe2 352
Pawel Zarembski 0:01f31e923fe2 353 /*
Pawel Zarembski 0:01f31e923fe2 354 * Disable USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 355 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 356 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 357 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 358 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 359 */
Pawel Zarembski 0:01f31e923fe2 360
Pawel Zarembski 0:01f31e923fe2 361 void USBD_DisableEP(U32 EPNum)
Pawel Zarembski 0:01f31e923fe2 362 {
Pawel Zarembski 0:01f31e923fe2 363 U32 *ptr;
Pawel Zarembski 0:01f31e923fe2 364 ptr = GetEpCmdStatPtr(EPNum);
Pawel Zarembski 0:01f31e923fe2 365 *ptr = EP_DISABLED;
Pawel Zarembski 0:01f31e923fe2 366
Pawel Zarembski 0:01f31e923fe2 367 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 368 EPNum &= ~0x80;
Pawel Zarembski 0:01f31e923fe2 369 LPC_USB->INTEN &= ~(1 << EP_IN_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 370
Pawel Zarembski 0:01f31e923fe2 371 } else {
Pawel Zarembski 0:01f31e923fe2 372 LPC_USB->INTEN &= ~(1 << EP_OUT_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 373 }
Pawel Zarembski 0:01f31e923fe2 374 }
Pawel Zarembski 0:01f31e923fe2 375
Pawel Zarembski 0:01f31e923fe2 376
Pawel Zarembski 0:01f31e923fe2 377 /*
Pawel Zarembski 0:01f31e923fe2 378 * Reset USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 379 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 380 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 381 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 382 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 383 */
Pawel Zarembski 0:01f31e923fe2 384
Pawel Zarembski 0:01f31e923fe2 385 void USBD_ResetEP(U32 EPNum)
Pawel Zarembski 0:01f31e923fe2 386 {
Pawel Zarembski 0:01f31e923fe2 387 U32 *ptr;
Pawel Zarembski 0:01f31e923fe2 388 ptr = GetEpCmdStatPtr(EPNum);
Pawel Zarembski 0:01f31e923fe2 389 *ptr |= TOOGLE_RESET;
Pawel Zarembski 0:01f31e923fe2 390 }
Pawel Zarembski 0:01f31e923fe2 391
Pawel Zarembski 0:01f31e923fe2 392
Pawel Zarembski 0:01f31e923fe2 393 /*
Pawel Zarembski 0:01f31e923fe2 394 * Set Stall for USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 395 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 396 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 397 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 398 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 399 */
Pawel Zarembski 0:01f31e923fe2 400
Pawel Zarembski 0:01f31e923fe2 401 void USBD_SetStallEP(U32 EPNum)
Pawel Zarembski 0:01f31e923fe2 402 {
Pawel Zarembski 0:01f31e923fe2 403 U32 *ptr;
Pawel Zarembski 0:01f31e923fe2 404 ptr = GetEpCmdStatPtr(EPNum);
Pawel Zarembski 0:01f31e923fe2 405
Pawel Zarembski 0:01f31e923fe2 406 if (EPNum & 0x7F) {
Pawel Zarembski 0:01f31e923fe2 407 if (*ptr & BUF_ACTIVE) {
Pawel Zarembski 0:01f31e923fe2 408 *ptr &= ~(BUF_ACTIVE);
Pawel Zarembski 0:01f31e923fe2 409 }
Pawel Zarembski 0:01f31e923fe2 410
Pawel Zarembski 0:01f31e923fe2 411 } else {
Pawel Zarembski 0:01f31e923fe2 412 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 413 EPNum &= ~0x80;
Pawel Zarembski 0:01f31e923fe2 414 LPC_USB->EPSKIP |= (1 << EP_IN_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 415
Pawel Zarembski 0:01f31e923fe2 416 while (LPC_USB->EPSKIP & (1 << EP_IN_IDX(EPNum)));
Pawel Zarembski 0:01f31e923fe2 417
Pawel Zarembski 0:01f31e923fe2 418 } else {
Pawel Zarembski 0:01f31e923fe2 419 LPC_USB->EPSKIP |= (1 << EP_OUT_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 420
Pawel Zarembski 0:01f31e923fe2 421 while (LPC_USB->EPSKIP & (1 << EP_OUT_IDX(EPNum)));
Pawel Zarembski 0:01f31e923fe2 422 }
Pawel Zarembski 0:01f31e923fe2 423 }
Pawel Zarembski 0:01f31e923fe2 424
Pawel Zarembski 0:01f31e923fe2 425 if ((EPNum & 0x7F) == 0) {
Pawel Zarembski 0:01f31e923fe2 426 /* Endpoint is stalled so control out won't be next */
Pawel Zarembski 0:01f31e923fe2 427 ctrl_out_next = 0;
Pawel Zarembski 0:01f31e923fe2 428 }
Pawel Zarembski 0:01f31e923fe2 429
Pawel Zarembski 0:01f31e923fe2 430 *ptr |= EP_STALL;
Pawel Zarembski 0:01f31e923fe2 431 }
Pawel Zarembski 0:01f31e923fe2 432
Pawel Zarembski 0:01f31e923fe2 433
Pawel Zarembski 0:01f31e923fe2 434 /*
Pawel Zarembski 0:01f31e923fe2 435 * Clear Stall for USB Device Endpoint
Pawel Zarembski 0:01f31e923fe2 436 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 437 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 438 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 439 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 440 */
Pawel Zarembski 0:01f31e923fe2 441
Pawel Zarembski 0:01f31e923fe2 442 void USBD_ClrStallEP(U32 EPNum)
Pawel Zarembski 0:01f31e923fe2 443 {
Pawel Zarembski 0:01f31e923fe2 444 U32 *ptr;
Pawel Zarembski 0:01f31e923fe2 445 ptr = GetEpCmdStatPtr(EPNum);
Pawel Zarembski 0:01f31e923fe2 446
Pawel Zarembski 0:01f31e923fe2 447 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 448 *ptr &= ~EP_STALL;
Pawel Zarembski 0:01f31e923fe2 449
Pawel Zarembski 0:01f31e923fe2 450 } else {
Pawel Zarembski 0:01f31e923fe2 451 *ptr &= ~EP_STALL;
Pawel Zarembski 0:01f31e923fe2 452 *ptr |= BUF_ACTIVE;
Pawel Zarembski 0:01f31e923fe2 453 }
Pawel Zarembski 0:01f31e923fe2 454
Pawel Zarembski 0:01f31e923fe2 455 USBD_ResetEP(EPNum);
Pawel Zarembski 0:01f31e923fe2 456 }
Pawel Zarembski 0:01f31e923fe2 457
Pawel Zarembski 0:01f31e923fe2 458
Pawel Zarembski 0:01f31e923fe2 459 /*
Pawel Zarembski 0:01f31e923fe2 460 * Clear USB Device Endpoint Buffer
Pawel Zarembski 0:01f31e923fe2 461 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 462 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 463 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 464 * Return Value: None
Pawel Zarembski 0:01f31e923fe2 465 */
Pawel Zarembski 0:01f31e923fe2 466
Pawel Zarembski 0:01f31e923fe2 467 void USBD_ClearEPBuf(U32 EPNum)
Pawel Zarembski 0:01f31e923fe2 468 {
Pawel Zarembski 0:01f31e923fe2 469 U32 cnt, i;
Pawel Zarembski 0:01f31e923fe2 470 U8 *dataptr;
Pawel Zarembski 0:01f31e923fe2 471
Pawel Zarembski 0:01f31e923fe2 472 if (EPNum & 0x80) {
Pawel Zarembski 0:01f31e923fe2 473 EPNum &= ~0x80;
Pawel Zarembski 0:01f31e923fe2 474 dataptr = (U8 *)EPBufInfo[EP_IN_IDX(EPNum)].buf_ptr;
Pawel Zarembski 0:01f31e923fe2 475 cnt = EPBufInfo[EP_IN_IDX(EPNum)].buf_len;
Pawel Zarembski 0:01f31e923fe2 476
Pawel Zarembski 0:01f31e923fe2 477 for (i = 0; i < cnt; i++) {
Pawel Zarembski 0:01f31e923fe2 478 dataptr[i] = 0;
Pawel Zarembski 0:01f31e923fe2 479 }
Pawel Zarembski 0:01f31e923fe2 480
Pawel Zarembski 0:01f31e923fe2 481 } else {
Pawel Zarembski 0:01f31e923fe2 482 dataptr = (U8 *)EPBufInfo[EP_OUT_IDX(EPNum)].buf_ptr;
Pawel Zarembski 0:01f31e923fe2 483 cnt = EPBufInfo[EP_OUT_IDX(EPNum)].buf_len;
Pawel Zarembski 0:01f31e923fe2 484
Pawel Zarembski 0:01f31e923fe2 485 for (i = 0; i < cnt; i++) {
Pawel Zarembski 0:01f31e923fe2 486 dataptr[i] = 0;
Pawel Zarembski 0:01f31e923fe2 487 }
Pawel Zarembski 0:01f31e923fe2 488 }
Pawel Zarembski 0:01f31e923fe2 489 }
Pawel Zarembski 0:01f31e923fe2 490
Pawel Zarembski 0:01f31e923fe2 491
Pawel Zarembski 0:01f31e923fe2 492 /*
Pawel Zarembski 0:01f31e923fe2 493 * Read USB Device Endpoint Data
Pawel Zarembski 0:01f31e923fe2 494 * Parameters: EPNum: Device Endpoint Number
Pawel Zarembski 0:01f31e923fe2 495 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 496 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 497 * pData: Pointer to Data Buffer
Pawel Zarembski 0:01f31e923fe2 498 * Return Value: Number of bytes read
Pawel Zarembski 0:01f31e923fe2 499 */
Pawel Zarembski 0:01f31e923fe2 500
Pawel Zarembski 0:01f31e923fe2 501 U32 USBD_ReadEP(U32 EPNum, U8 *pData, U32 size)
Pawel Zarembski 0:01f31e923fe2 502 {
Pawel Zarembski 0:01f31e923fe2 503 U32 cnt, i, xfer_size;
Pawel Zarembski 0:01f31e923fe2 504 volatile U32 *ptr;
Pawel Zarembski 0:01f31e923fe2 505 U8 *dataptr;
Pawel Zarembski 0:01f31e923fe2 506 ptr = GetEpCmdStatPtr(EPNum);
Pawel Zarembski 0:01f31e923fe2 507 int timeout = 256;
Pawel Zarembski 0:01f31e923fe2 508
Pawel Zarembski 0:01f31e923fe2 509 /* Setup packet */
Pawel Zarembski 0:01f31e923fe2 510 if ((EPNum == 0) && !ctrl_out_next && (LPC_USB->DEVCMDSTAT & (1UL << 8))) {
Pawel Zarembski 0:01f31e923fe2 511 cnt = USBD_MAX_PACKET0;
Pawel Zarembski 0:01f31e923fe2 512
Pawel Zarembski 0:01f31e923fe2 513 if (size < cnt) {
Pawel Zarembski 0:01f31e923fe2 514 util_assert(0);
Pawel Zarembski 0:01f31e923fe2 515 cnt = size;
Pawel Zarembski 0:01f31e923fe2 516 }
Pawel Zarembski 0:01f31e923fe2 517
Pawel Zarembski 0:01f31e923fe2 518 dataptr = (U8 *)(EPBufInfo[EP_OUT_IDX(EPNum)].buf_ptr + 64);
Pawel Zarembski 0:01f31e923fe2 519
Pawel Zarembski 0:01f31e923fe2 520 for (i = 0; i < cnt; i++) {
Pawel Zarembski 0:01f31e923fe2 521 pData[i] = dataptr[i];
Pawel Zarembski 0:01f31e923fe2 522 }
Pawel Zarembski 0:01f31e923fe2 523
Pawel Zarembski 0:01f31e923fe2 524 xfer_size = (pData[7] << 8) | (pData[6] << 0);
Pawel Zarembski 0:01f31e923fe2 525 if ((xfer_size > 0) && (pData[0] & (1 << 7))) {
Pawel Zarembski 0:01f31e923fe2 526 /* This control transfer has a data IN stage */
Pawel Zarembski 0:01f31e923fe2 527 /* and ends with a zero length data OUT transfer. */
Pawel Zarembski 0:01f31e923fe2 528 /* Ensure the data OUT token is not skipped even if */
Pawel Zarembski 0:01f31e923fe2 529 /* a SETUP token arrives before USBD_ReadEP has */
Pawel Zarembski 0:01f31e923fe2 530 /* been called. */
Pawel Zarembski 0:01f31e923fe2 531 ctrl_out_next = 1;
Pawel Zarembski 0:01f31e923fe2 532 }
Pawel Zarembski 0:01f31e923fe2 533
Pawel Zarembski 0:01f31e923fe2 534 LPC_USB->EPSKIP |= (1 << EP_IN_IDX(EPNum));
Pawel Zarembski 0:01f31e923fe2 535
Pawel Zarembski 0:01f31e923fe2 536 while (LPC_USB->EPSKIP & (1 << EP_IN_IDX(EPNum)));
Pawel Zarembski 0:01f31e923fe2 537
Pawel Zarembski 0:01f31e923fe2 538 if (*(ptr + 2) & EP_STALL) {
Pawel Zarembski 0:01f31e923fe2 539 *(ptr + 2) &= ~(EP_STALL);
Pawel Zarembski 0:01f31e923fe2 540 }
Pawel Zarembski 0:01f31e923fe2 541
Pawel Zarembski 0:01f31e923fe2 542 if (*ptr & EP_STALL) {
Pawel Zarembski 0:01f31e923fe2 543 *ptr &= ~(EP_STALL);
Pawel Zarembski 0:01f31e923fe2 544 }
Pawel Zarembski 0:01f31e923fe2 545
Pawel Zarembski 0:01f31e923fe2 546 LPC_USB->DEVCMDSTAT |= (1UL << 8);
Pawel Zarembski 0:01f31e923fe2 547 }
Pawel Zarembski 0:01f31e923fe2 548
Pawel Zarembski 0:01f31e923fe2 549 /* OUT packet */
Pawel Zarembski 0:01f31e923fe2 550 else {
Pawel Zarembski 0:01f31e923fe2 551 ptr = GetEpCmdStatPtr(EPNum);
Pawel Zarembski 0:01f31e923fe2 552 cnt = EPBufInfo[EP_OUT_IDX(EPNum)].buf_len - ((*ptr >> 16) & 0x3FF);
Pawel Zarembski 0:01f31e923fe2 553 dataptr = (U8 *)EPBufInfo[EP_OUT_IDX(EPNum)].buf_ptr;
Pawel Zarembski 0:01f31e923fe2 554
Pawel Zarembski 0:01f31e923fe2 555 while ((timeout-- > 0) && (*ptr & BUF_ACTIVE)); //spin on the hardware until it's done
Pawel Zarembski 0:01f31e923fe2 556 util_assert(!(*ptr & BUF_ACTIVE)); //check for timeout
Pawel Zarembski 0:01f31e923fe2 557
Pawel Zarembski 0:01f31e923fe2 558 if (size < cnt) {
Pawel Zarembski 0:01f31e923fe2 559 util_assert(0);
Pawel Zarembski 0:01f31e923fe2 560 cnt = size;
Pawel Zarembski 0:01f31e923fe2 561 }
Pawel Zarembski 0:01f31e923fe2 562
Pawel Zarembski 0:01f31e923fe2 563 cnt = cnt < size ? cnt : size;
Pawel Zarembski 0:01f31e923fe2 564
Pawel Zarembski 0:01f31e923fe2 565 for (i = 0; i < cnt; i++) {
Pawel Zarembski 0:01f31e923fe2 566 pData[i] = dataptr[i];
Pawel Zarembski 0:01f31e923fe2 567 }
Pawel Zarembski 0:01f31e923fe2 568
Pawel Zarembski 0:01f31e923fe2 569 *ptr = N_BYTES(EPBufInfo[EP_OUT_IDX(EPNum)].buf_len) |
Pawel Zarembski 0:01f31e923fe2 570 BUF_ADDR(EPBufInfo[EP_OUT_IDX(EPNum)].buf_ptr) |
Pawel Zarembski 0:01f31e923fe2 571 BUF_ACTIVE;
Pawel Zarembski 0:01f31e923fe2 572
Pawel Zarembski 0:01f31e923fe2 573 if (EPNum == 0) {
Pawel Zarembski 0:01f31e923fe2 574 /* If ctrl_out_next is set then this should be a zero length */
Pawel Zarembski 0:01f31e923fe2 575 /* data OUT packet. */
Pawel Zarembski 0:01f31e923fe2 576 util_assert(!ctrl_out_next || (cnt == 0));
Pawel Zarembski 0:01f31e923fe2 577 ctrl_out_next = 0;
Pawel Zarembski 0:01f31e923fe2 578 if (LPC_USB->DEVCMDSTAT & (1UL << 8)) {
Pawel Zarembski 0:01f31e923fe2 579 // A setup packet is still pending so trigger another interrupt
Pawel Zarembski 0:01f31e923fe2 580 LPC_USB->INTSETSTAT |= (1 << 0);
Pawel Zarembski 0:01f31e923fe2 581 }
Pawel Zarembski 0:01f31e923fe2 582 }
Pawel Zarembski 0:01f31e923fe2 583 }
Pawel Zarembski 0:01f31e923fe2 584
Pawel Zarembski 0:01f31e923fe2 585 return (cnt);
Pawel Zarembski 0:01f31e923fe2 586 }
Pawel Zarembski 0:01f31e923fe2 587
Pawel Zarembski 0:01f31e923fe2 588
Pawel Zarembski 0:01f31e923fe2 589 /*
Pawel Zarembski 0:01f31e923fe2 590 * Write USB Device Endpoint Data
Pawel Zarembski 0:01f31e923fe2 591 * Parameters: EPNum: Endpoint Number
Pawel Zarembski 0:01f31e923fe2 592 * EPNum.0..3: Address
Pawel Zarembski 0:01f31e923fe2 593 * EPNum.7: Dir
Pawel Zarembski 0:01f31e923fe2 594 * pData: Pointer to Data Buffer
Pawel Zarembski 0:01f31e923fe2 595 * cnt: Number of bytes to write
Pawel Zarembski 0:01f31e923fe2 596 * Return Value: Number of bytes written
Pawel Zarembski 0:01f31e923fe2 597 */
Pawel Zarembski 0:01f31e923fe2 598
Pawel Zarembski 0:01f31e923fe2 599 U32 USBD_WriteEP(U32 EPNum, U8 *pData, U32 cnt)
Pawel Zarembski 0:01f31e923fe2 600 {
Pawel Zarembski 0:01f31e923fe2 601 U32 i;
Pawel Zarembski 0:01f31e923fe2 602 volatile U32 *ptr;
Pawel Zarembski 0:01f31e923fe2 603 U32 *dataptr;
Pawel Zarembski 0:01f31e923fe2 604 ptr = GetEpCmdStatPtr(EPNum);
Pawel Zarembski 0:01f31e923fe2 605 EPNum &= ~0x80;
Pawel Zarembski 0:01f31e923fe2 606
Pawel Zarembski 0:01f31e923fe2 607 while (*ptr & BUF_ACTIVE);
Pawel Zarembski 0:01f31e923fe2 608
Pawel Zarembski 0:01f31e923fe2 609 *ptr &= ~(0x3FFFFFF);
Pawel Zarembski 0:01f31e923fe2 610 *ptr |= BUF_ADDR(EPBufInfo[EP_IN_IDX(EPNum)].buf_ptr) |
Pawel Zarembski 0:01f31e923fe2 611 N_BYTES(cnt);
Pawel Zarembski 0:01f31e923fe2 612 dataptr = (U32 *)EPBufInfo[EP_IN_IDX(EPNum)].buf_ptr;
Pawel Zarembski 0:01f31e923fe2 613
Pawel Zarembski 0:01f31e923fe2 614 for (i = 0; i < (cnt + 3) / 4; i++) {
Pawel Zarembski 0:01f31e923fe2 615 dataptr[i] = * ((__packed U32 *)pData);
Pawel Zarembski 0:01f31e923fe2 616 pData += 4;
Pawel Zarembski 0:01f31e923fe2 617 }
Pawel Zarembski 0:01f31e923fe2 618
Pawel Zarembski 0:01f31e923fe2 619 if (EPNum && (*ptr & EP_STALL)) {
Pawel Zarembski 0:01f31e923fe2 620 return (0);
Pawel Zarembski 0:01f31e923fe2 621 }
Pawel Zarembski 0:01f31e923fe2 622
Pawel Zarembski 0:01f31e923fe2 623 *ptr |= BUF_ACTIVE;
Pawel Zarembski 0:01f31e923fe2 624 return (cnt);
Pawel Zarembski 0:01f31e923fe2 625 }
Pawel Zarembski 0:01f31e923fe2 626
Pawel Zarembski 0:01f31e923fe2 627
Pawel Zarembski 0:01f31e923fe2 628 /*
Pawel Zarembski 0:01f31e923fe2 629 * Get USB Device Last Frame Number
Pawel Zarembski 0:01f31e923fe2 630 * Parameters: None
Pawel Zarembski 0:01f31e923fe2 631 * Return Value: Frame Number
Pawel Zarembski 0:01f31e923fe2 632 */
Pawel Zarembski 0:01f31e923fe2 633
Pawel Zarembski 0:01f31e923fe2 634 U32 USBD_GetFrame(void)
Pawel Zarembski 0:01f31e923fe2 635 {
Pawel Zarembski 0:01f31e923fe2 636 return (LPC_USB->INFO & 0x7FF);
Pawel Zarembski 0:01f31e923fe2 637 }
Pawel Zarembski 0:01f31e923fe2 638
Pawel Zarembski 0:01f31e923fe2 639
Pawel Zarembski 0:01f31e923fe2 640 /*
Pawel Zarembski 0:01f31e923fe2 641 * USB Device Interrupt Service Routine
Pawel Zarembski 0:01f31e923fe2 642 */
Pawel Zarembski 0:01f31e923fe2 643
Pawel Zarembski 0:01f31e923fe2 644 void USB_IRQHandler(void)
Pawel Zarembski 0:01f31e923fe2 645 {
Pawel Zarembski 0:01f31e923fe2 646 NVIC_DisableIRQ(USB_IRQn);
Pawel Zarembski 0:01f31e923fe2 647 USBD_SignalHandler();
Pawel Zarembski 0:01f31e923fe2 648 }
Pawel Zarembski 0:01f31e923fe2 649
Pawel Zarembski 0:01f31e923fe2 650 void USBD_Handler(void)
Pawel Zarembski 0:01f31e923fe2 651 {
Pawel Zarembski 0:01f31e923fe2 652 U32 sts, val, num, i;
Pawel Zarembski 0:01f31e923fe2 653 sts = LPC_USB->INTSTAT;
Pawel Zarembski 0:01f31e923fe2 654 LPC_USB->INTSTAT = sts;
Pawel Zarembski 0:01f31e923fe2 655
Pawel Zarembski 0:01f31e923fe2 656 /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
Pawel Zarembski 0:01f31e923fe2 657 if (sts & (1UL << 31)) {
Pawel Zarembski 0:01f31e923fe2 658 val = LPC_USB->DEVCMDSTAT;
Pawel Zarembski 0:01f31e923fe2 659
Pawel Zarembski 0:01f31e923fe2 660 /* reset interrupt */
Pawel Zarembski 0:01f31e923fe2 661 if (val & (1UL << 26)) {
Pawel Zarembski 0:01f31e923fe2 662 LPC_USB->DEVCMDSTAT |= (1UL << 26);
Pawel Zarembski 0:01f31e923fe2 663 USBD_Reset();
Pawel Zarembski 0:01f31e923fe2 664 usbd_reset_core();
Pawel Zarembski 0:01f31e923fe2 665 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 666
Pawel Zarembski 0:01f31e923fe2 667 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 668 isr_evt_set(USBD_EVT_RESET, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 669 }
Pawel Zarembski 0:01f31e923fe2 670
Pawel Zarembski 0:01f31e923fe2 671 #else
Pawel Zarembski 0:01f31e923fe2 672
Pawel Zarembski 0:01f31e923fe2 673 if (USBD_P_Reset_Event) {
Pawel Zarembski 0:01f31e923fe2 674 USBD_P_Reset_Event();
Pawel Zarembski 0:01f31e923fe2 675 }
Pawel Zarembski 0:01f31e923fe2 676
Pawel Zarembski 0:01f31e923fe2 677 #endif
Pawel Zarembski 0:01f31e923fe2 678 }
Pawel Zarembski 0:01f31e923fe2 679
Pawel Zarembski 0:01f31e923fe2 680 /* connect interrupt */
Pawel Zarembski 0:01f31e923fe2 681 if (val & (1UL << 24)) {
Pawel Zarembski 0:01f31e923fe2 682 LPC_USB->DEVCMDSTAT |= (1UL << 24);
Pawel Zarembski 0:01f31e923fe2 683 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 684
Pawel Zarembski 0:01f31e923fe2 685 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 686 if (val & (1UL << 16)) {
Pawel Zarembski 0:01f31e923fe2 687 isr_evt_set(USBD_EVT_POWER_ON, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 688 } else {
Pawel Zarembski 0:01f31e923fe2 689 isr_evt_set(USBD_EVT_POWER_OFF, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 690 }
Pawel Zarembski 0:01f31e923fe2 691 }
Pawel Zarembski 0:01f31e923fe2 692
Pawel Zarembski 0:01f31e923fe2 693 #else
Pawel Zarembski 0:01f31e923fe2 694
Pawel Zarembski 0:01f31e923fe2 695 if (USBD_P_Power_Event) {
Pawel Zarembski 0:01f31e923fe2 696 USBD_P_Power_Event((val >> 16) & 1);
Pawel Zarembski 0:01f31e923fe2 697 }
Pawel Zarembski 0:01f31e923fe2 698
Pawel Zarembski 0:01f31e923fe2 699 #endif
Pawel Zarembski 0:01f31e923fe2 700 }
Pawel Zarembski 0:01f31e923fe2 701
Pawel Zarembski 0:01f31e923fe2 702 /* suspend/resume interrupt */
Pawel Zarembski 0:01f31e923fe2 703 if (val & (1 << 25)) {
Pawel Zarembski 0:01f31e923fe2 704 LPC_USB->DEVCMDSTAT |= (1UL << 25);
Pawel Zarembski 0:01f31e923fe2 705
Pawel Zarembski 0:01f31e923fe2 706 /* suspend interrupt */
Pawel Zarembski 0:01f31e923fe2 707 if (val & (1UL << 17)) {
Pawel Zarembski 0:01f31e923fe2 708 USBD_Suspend();
Pawel Zarembski 0:01f31e923fe2 709 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 710
Pawel Zarembski 0:01f31e923fe2 711 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 712 isr_evt_set(USBD_EVT_SUSPEND, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 713 }
Pawel Zarembski 0:01f31e923fe2 714
Pawel Zarembski 0:01f31e923fe2 715 #else
Pawel Zarembski 0:01f31e923fe2 716
Pawel Zarembski 0:01f31e923fe2 717 if (USBD_P_Suspend_Event) {
Pawel Zarembski 0:01f31e923fe2 718 USBD_P_Suspend_Event();
Pawel Zarembski 0:01f31e923fe2 719 }
Pawel Zarembski 0:01f31e923fe2 720
Pawel Zarembski 0:01f31e923fe2 721 #endif
Pawel Zarembski 0:01f31e923fe2 722 }
Pawel Zarembski 0:01f31e923fe2 723
Pawel Zarembski 0:01f31e923fe2 724 /* resume interrupt */
Pawel Zarembski 0:01f31e923fe2 725 else {
Pawel Zarembski 0:01f31e923fe2 726 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 727
Pawel Zarembski 0:01f31e923fe2 728 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 729 isr_evt_set(USBD_EVT_RESUME, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 730 }
Pawel Zarembski 0:01f31e923fe2 731
Pawel Zarembski 0:01f31e923fe2 732 #else
Pawel Zarembski 0:01f31e923fe2 733
Pawel Zarembski 0:01f31e923fe2 734 if (USBD_P_Resume_Event) {
Pawel Zarembski 0:01f31e923fe2 735 USBD_P_Resume_Event();
Pawel Zarembski 0:01f31e923fe2 736 }
Pawel Zarembski 0:01f31e923fe2 737
Pawel Zarembski 0:01f31e923fe2 738 #endif
Pawel Zarembski 0:01f31e923fe2 739 }
Pawel Zarembski 0:01f31e923fe2 740 }
Pawel Zarembski 0:01f31e923fe2 741 }
Pawel Zarembski 0:01f31e923fe2 742
Pawel Zarembski 0:01f31e923fe2 743 /* Start of Frame */
Pawel Zarembski 0:01f31e923fe2 744 if (sts & (1UL << 30)) {
Pawel Zarembski 0:01f31e923fe2 745 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 746
Pawel Zarembski 0:01f31e923fe2 747 if (USBD_RTX_DevTask) {
Pawel Zarembski 0:01f31e923fe2 748 isr_evt_set(USBD_EVT_SOF, USBD_RTX_DevTask);
Pawel Zarembski 0:01f31e923fe2 749 }
Pawel Zarembski 0:01f31e923fe2 750
Pawel Zarembski 0:01f31e923fe2 751 #else
Pawel Zarembski 0:01f31e923fe2 752
Pawel Zarembski 0:01f31e923fe2 753 if (USBD_P_SOF_Event) {
Pawel Zarembski 0:01f31e923fe2 754 USBD_P_SOF_Event();
Pawel Zarembski 0:01f31e923fe2 755 }
Pawel Zarembski 0:01f31e923fe2 756
Pawel Zarembski 0:01f31e923fe2 757 #endif
Pawel Zarembski 0:01f31e923fe2 758 }
Pawel Zarembski 0:01f31e923fe2 759
Pawel Zarembski 0:01f31e923fe2 760 /* EndPoint Interrupt */
Pawel Zarembski 0:01f31e923fe2 761 if (sts & 0x3FF) {
Pawel Zarembski 0:01f31e923fe2 762 const uint32_t endpoint_count = ((USBD_EP_NUM + 1) * 2);
Pawel Zarembski 0:01f31e923fe2 763
Pawel Zarembski 0:01f31e923fe2 764 for (i = 0; i < endpoint_count; i++) {
Pawel Zarembski 0:01f31e923fe2 765 // Iterate through endpoints in the reverse order so IN endpoints
Pawel Zarembski 0:01f31e923fe2 766 // get processed before OUT endpoints if they are both pending.
Pawel Zarembski 0:01f31e923fe2 767 num = endpoint_count - i - 1;
Pawel Zarembski 0:01f31e923fe2 768
Pawel Zarembski 0:01f31e923fe2 769 if (sts & (1UL << num)) {
Pawel Zarembski 0:01f31e923fe2 770 /* Setup */
Pawel Zarembski 0:01f31e923fe2 771 if ((num == 0) && !ctrl_out_next && (LPC_USB->DEVCMDSTAT & (1UL << 8))) {
Pawel Zarembski 0:01f31e923fe2 772 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 773
Pawel Zarembski 0:01f31e923fe2 774 if (USBD_RTX_EPTask[num / 2]) {
Pawel Zarembski 0:01f31e923fe2 775 isr_evt_set(USBD_EVT_SETUP, USBD_RTX_EPTask[num / 2]);
Pawel Zarembski 0:01f31e923fe2 776 }
Pawel Zarembski 0:01f31e923fe2 777
Pawel Zarembski 0:01f31e923fe2 778 #else
Pawel Zarembski 0:01f31e923fe2 779
Pawel Zarembski 0:01f31e923fe2 780 if (USBD_P_EP[num / 2]) {
Pawel Zarembski 0:01f31e923fe2 781 USBD_P_EP[num / 2](USBD_EVT_SETUP);
Pawel Zarembski 0:01f31e923fe2 782 }
Pawel Zarembski 0:01f31e923fe2 783
Pawel Zarembski 0:01f31e923fe2 784 #endif
Pawel Zarembski 0:01f31e923fe2 785 }
Pawel Zarembski 0:01f31e923fe2 786
Pawel Zarembski 0:01f31e923fe2 787 /* OUT */
Pawel Zarembski 0:01f31e923fe2 788 else if ((num % 2) == 0) {
Pawel Zarembski 0:01f31e923fe2 789 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 790
Pawel Zarembski 0:01f31e923fe2 791 if (USBD_RTX_EPTask[num / 2]) {
Pawel Zarembski 0:01f31e923fe2 792 isr_evt_set(USBD_EVT_OUT, USBD_RTX_EPTask[num / 2]);
Pawel Zarembski 0:01f31e923fe2 793 }
Pawel Zarembski 0:01f31e923fe2 794
Pawel Zarembski 0:01f31e923fe2 795 #else
Pawel Zarembski 0:01f31e923fe2 796
Pawel Zarembski 0:01f31e923fe2 797 if (USBD_P_EP[num / 2]) {
Pawel Zarembski 0:01f31e923fe2 798 USBD_P_EP[num / 2](USBD_EVT_OUT);
Pawel Zarembski 0:01f31e923fe2 799 }
Pawel Zarembski 0:01f31e923fe2 800
Pawel Zarembski 0:01f31e923fe2 801 #endif
Pawel Zarembski 0:01f31e923fe2 802 }
Pawel Zarembski 0:01f31e923fe2 803
Pawel Zarembski 0:01f31e923fe2 804 /* IN */
Pawel Zarembski 0:01f31e923fe2 805 else {
Pawel Zarembski 0:01f31e923fe2 806 #ifdef __RTX
Pawel Zarembski 0:01f31e923fe2 807
Pawel Zarembski 0:01f31e923fe2 808 if (USBD_RTX_EPTask[num / 2]) {
Pawel Zarembski 0:01f31e923fe2 809 isr_evt_set(USBD_EVT_IN, USBD_RTX_EPTask[num / 2]);
Pawel Zarembski 0:01f31e923fe2 810 }
Pawel Zarembski 0:01f31e923fe2 811
Pawel Zarembski 0:01f31e923fe2 812 #else
Pawel Zarembski 0:01f31e923fe2 813
Pawel Zarembski 0:01f31e923fe2 814 if (USBD_P_EP[num / 2]) {
Pawel Zarembski 0:01f31e923fe2 815 USBD_P_EP[num / 2](USBD_EVT_IN);
Pawel Zarembski 0:01f31e923fe2 816 }
Pawel Zarembski 0:01f31e923fe2 817
Pawel Zarembski 0:01f31e923fe2 818 #endif
Pawel Zarembski 0:01f31e923fe2 819 }
Pawel Zarembski 0:01f31e923fe2 820 }
Pawel Zarembski 0:01f31e923fe2 821 }
Pawel Zarembski 0:01f31e923fe2 822 }
Pawel Zarembski 0:01f31e923fe2 823
Pawel Zarembski 0:01f31e923fe2 824 NVIC_EnableIRQ(USB_IRQn);
Pawel Zarembski 0:01f31e923fe2 825 }