Adaptation of the official mbed USBHost repository to work with the LPC4088 Display Module

Dependents:   DMSupport DMSupport DMSupport DMSupport

Fork of DM_USBHost by EmbeddedArtists AB

Committer:
embeddedartists
Date:
Mon Nov 04 14:30:07 2019 +0000
Revision:
33:819bbf04163b
Parent:
32:f2d129436056
More updates related to mbed OS 5

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 8:93da8ea2708b 1 /* mbed USBHost Library
samux 8:93da8ea2708b 2 * Copyright (c) 2006-2013 ARM Limited
samux 8:93da8ea2708b 3 *
samux 8:93da8ea2708b 4 * Licensed under the Apache License, Version 2.0 (the "License");
samux 8:93da8ea2708b 5 * you may not use this file except in compliance with the License.
samux 8:93da8ea2708b 6 * You may obtain a copy of the License at
samux 8:93da8ea2708b 7 *
samux 8:93da8ea2708b 8 * http://www.apache.org/licenses/LICENSE-2.0
samux 8:93da8ea2708b 9 *
samux 8:93da8ea2708b 10 * Unless required by applicable law or agreed to in writing, software
samux 8:93da8ea2708b 11 * distributed under the License is distributed on an "AS IS" BASIS,
samux 8:93da8ea2708b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
samux 8:93da8ea2708b 13 * See the License for the specific language governing permissions and
samux 8:93da8ea2708b 14 * limitations under the License.
samux 8:93da8ea2708b 15 */
mbed_official 0:a554658735bf 16
mbed_official 0:a554658735bf 17 #include "mbed.h"
mbed_official 0:a554658735bf 18 #include "USBHALHost.h"
mbed_official 0:a554658735bf 19 #include "dbg.h"
mbed_official 0:a554658735bf 20
mbed_official 0:a554658735bf 21 // bits of the USB/OTG clock control register
mbed_official 0:a554658735bf 22 #define HOST_CLK_EN (1<<0)
mbed_official 0:a554658735bf 23 #define DEV_CLK_EN (1<<1)
mbed_official 0:a554658735bf 24 #define PORTSEL_CLK_EN (1<<3)
mbed_official 0:a554658735bf 25 #define AHB_CLK_EN (1<<4)
mbed_official 0:a554658735bf 26
mbed_official 0:a554658735bf 27 // bits of the USB/OTG clock status register
mbed_official 0:a554658735bf 28 #define HOST_CLK_ON (1<<0)
mbed_official 0:a554658735bf 29 #define DEV_CLK_ON (1<<1)
mbed_official 0:a554658735bf 30 #define PORTSEL_CLK_ON (1<<3)
mbed_official 0:a554658735bf 31 #define AHB_CLK_ON (1<<4)
mbed_official 0:a554658735bf 32
mbed_official 0:a554658735bf 33 // we need host clock, OTG/portsel clock and AHB clock
mbed_official 0:a554658735bf 34 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
mbed_official 0:a554658735bf 35
mbed_official 0:a554658735bf 36 #define HCCA_SIZE sizeof(HCCA)
mbed_official 0:a554658735bf 37 #define ED_SIZE sizeof(HCED)
mbed_official 0:a554658735bf 38 #define TD_SIZE sizeof(HCTD)
mbed_official 0:a554658735bf 39
mbed_official 0:a554658735bf 40 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
mbed_official 0:a554658735bf 41
embeddedartists 33:819bbf04163b 42 // Put the USB structures in the only memory accessible by the USB stack - the AHBSRAM1
embeddedartists 33:819bbf04163b 43 static volatile uint8_t usb_buf[TOTAL_SIZE] __attribute__((section("AHBSRAM1"),aligned(256)));// __attribute__((section("AHBSRAM0"),aligned(256))); //256 bytes aligned!
embeddedartists 27:aa2fd412f1d3 44
embeddedartists 33:819bbf04163b 45 // A very basic implementation of malloc to allocate in the AHBSRAM1
embeddedartists 27:aa2fd412f1d3 46 #define SAFE_MEM_TO_USE (10*1024)
embeddedartists 27:aa2fd412f1d3 47 #define SAFE_MEM_BLOCK_SIZE (512)
embeddedartists 27:aa2fd412f1d3 48 #define SAFE_MEM_NUM_BLOCKS (SAFE_MEM_TO_USE/SAFE_MEM_BLOCK_SIZE)
embeddedartists 27:aa2fd412f1d3 49 typedef struct {
embeddedartists 27:aa2fd412f1d3 50 volatile uint8_t* ptr;
embeddedartists 27:aa2fd412f1d3 51 bool used;
embeddedartists 27:aa2fd412f1d3 52 } safe_mem_info_t;
embeddedartists 27:aa2fd412f1d3 53 static safe_mem_info_t safe_mem_list[SAFE_MEM_NUM_BLOCKS];
embeddedartists 33:819bbf04163b 54 static uint8_t safe_mem_data[SAFE_MEM_TO_USE] __attribute__((section("AHBSRAM1"),aligned(256)));//__attribute__((section("AHBSRAM0"),aligned)); //256 bytes aligned!
embeddedartists 27:aa2fd412f1d3 55
embeddedartists 27:aa2fd412f1d3 56 // To detect when memory outside of the AHBSRAM0 is passed to the USB stack
embeddedartists 27:aa2fd412f1d3 57 void assert_mem_region(uint32_t ptr)
embeddedartists 27:aa2fd412f1d3 58 {
embeddedartists 27:aa2fd412f1d3 59 if (( ptr != 0) && ((ptr & 0xff000000) != 0x20000000)) {
embeddedartists 27:aa2fd412f1d3 60 USB_ERR("0x%08x not in USB MEM", ptr);
embeddedartists 27:aa2fd412f1d3 61 mbed_die();
embeddedartists 27:aa2fd412f1d3 62 }
embeddedartists 27:aa2fd412f1d3 63 }
mbed_official 0:a554658735bf 64
mbed_official 0:a554658735bf 65 USBHALHost * USBHALHost::instHost;
mbed_official 0:a554658735bf 66
mbed_official 0:a554658735bf 67 USBHALHost::USBHALHost() {
mbed_official 0:a554658735bf 68 instHost = this;
mbed_official 0:a554658735bf 69 memInit();
mbed_official 0:a554658735bf 70 memset((void*)usb_hcca, 0, HCCA_SIZE);
mbed_official 0:a554658735bf 71 for (int i = 0; i < MAX_ENDPOINT; i++) {
mbed_official 0:a554658735bf 72 edBufAlloc[i] = false;
mbed_official 0:a554658735bf 73 }
mbed_official 0:a554658735bf 74 for (int i = 0; i < MAX_TD; i++) {
mbed_official 0:a554658735bf 75 tdBufAlloc[i] = false;
mbed_official 0:a554658735bf 76 }
embeddedartists 27:aa2fd412f1d3 77 for (int i = 0; i < SAFE_MEM_NUM_BLOCKS; i++) {
embeddedartists 27:aa2fd412f1d3 78 safe_mem_list[i].used = false;
embeddedartists 27:aa2fd412f1d3 79 safe_mem_list[i].ptr = safe_mem_data + SAFE_MEM_BLOCK_SIZE*i;
embeddedartists 27:aa2fd412f1d3 80 }
embeddedartists 33:819bbf04163b 81
mbed_official 0:a554658735bf 82 }
mbed_official 0:a554658735bf 83
embeddedartists 27:aa2fd412f1d3 84 uint8_t* USBHALHost::getSafeMem(uint32_t size) {
embeddedartists 27:aa2fd412f1d3 85 uint8_t* result = NULL;
embeddedartists 27:aa2fd412f1d3 86 if (size > 512) {
embeddedartists 27:aa2fd412f1d3 87 USB_ERR("getSafeMem(%u) not supported", size);
embeddedartists 27:aa2fd412f1d3 88 } else {
embeddedartists 27:aa2fd412f1d3 89 safemem_mutex.lock();
embeddedartists 27:aa2fd412f1d3 90 for (int i = 0; i < SAFE_MEM_NUM_BLOCKS; i++) {
embeddedartists 27:aa2fd412f1d3 91 if (!safe_mem_list[i].used) {
embeddedartists 27:aa2fd412f1d3 92 safe_mem_list[i].used = true;
embeddedartists 27:aa2fd412f1d3 93 result = (uint8_t*)safe_mem_list[i].ptr;
embeddedartists 27:aa2fd412f1d3 94 break;
embeddedartists 27:aa2fd412f1d3 95 }
embeddedartists 27:aa2fd412f1d3 96 }
embeddedartists 27:aa2fd412f1d3 97 safemem_mutex.unlock();
embeddedartists 27:aa2fd412f1d3 98 }
embeddedartists 27:aa2fd412f1d3 99 if (result == NULL) {
embeddedartists 27:aa2fd412f1d3 100 USB_ERR("getSafeMem(%u) failed to allocate", size);
embeddedartists 27:aa2fd412f1d3 101 }
embeddedartists 27:aa2fd412f1d3 102 return result;
embeddedartists 27:aa2fd412f1d3 103 }
embeddedartists 27:aa2fd412f1d3 104
embeddedartists 27:aa2fd412f1d3 105 void USBHALHost::returnSafeMem(uint8_t* mem) {
embeddedartists 27:aa2fd412f1d3 106 safemem_mutex.lock();
embeddedartists 27:aa2fd412f1d3 107 int i;
embeddedartists 27:aa2fd412f1d3 108 for (i = 0; i < SAFE_MEM_NUM_BLOCKS; i++) {
embeddedartists 27:aa2fd412f1d3 109 if (safe_mem_list[i].ptr == mem) {
embeddedartists 27:aa2fd412f1d3 110 safe_mem_list[i].used = false;
embeddedartists 27:aa2fd412f1d3 111 break;
embeddedartists 27:aa2fd412f1d3 112 }
embeddedartists 27:aa2fd412f1d3 113 }
embeddedartists 27:aa2fd412f1d3 114 safemem_mutex.unlock();
embeddedartists 27:aa2fd412f1d3 115 if (i == SAFE_MEM_NUM_BLOCKS) {
embeddedartists 27:aa2fd412f1d3 116 USB_ERR("returnSafeMem(%p) not allocated", mem);
embeddedartists 27:aa2fd412f1d3 117 }
embeddedartists 27:aa2fd412f1d3 118 }
embeddedartists 27:aa2fd412f1d3 119
embeddedartists 27:aa2fd412f1d3 120
mbed_official 0:a554658735bf 121 void USBHALHost::init() {
mbed_official 0:a554658735bf 122 NVIC_DisableIRQ(USB_IRQn);
mbed_official 24:868cbfe611a7 123
mbed_official 0:a554658735bf 124 //Cut power
mbed_official 0:a554658735bf 125 LPC_SC->PCONP &= ~(1UL<<31);
embeddedartists 32:f2d129436056 126 ThisThread::sleep_for(1000);
mbed_official 0:a554658735bf 127
mbed_official 0:a554658735bf 128 // turn on power for USB
mbed_official 0:a554658735bf 129 LPC_SC->PCONP |= (1UL<<31);
mbed_official 0:a554658735bf 130
mbed_official 0:a554658735bf 131 // Enable USB host clock, port selection and AHB clock
embeddedartists 27:aa2fd412f1d3 132 LPC_USB->USBClkCtrl = 0x19;
mbed_official 0:a554658735bf 133
mbed_official 0:a554658735bf 134 // Wait for clocks to become available
embeddedartists 27:aa2fd412f1d3 135 while ((LPC_USB->USBClkSt & 0x19) != 0x19);
mbed_official 0:a554658735bf 136
mbed_official 0:a554658735bf 137 // it seems the bits[0:1] mean the following
mbed_official 0:a554658735bf 138 // 0: U1=device, U2=host
mbed_official 0:a554658735bf 139 // 1: U1=host, U2=host
mbed_official 0:a554658735bf 140 // 2: reserved
mbed_official 0:a554658735bf 141 // 3: U1=host, U2=device
mbed_official 0:a554658735bf 142 // NB: this register is only available if OTG clock (aka "port select") is enabled!!
embeddedartists 27:aa2fd412f1d3 143 LPC_USB->OTGStCtrl = 1;
mbed_official 0:a554658735bf 144
mbed_official 0:a554658735bf 145 // configure USB D+/D- pins
embeddedartists 27:aa2fd412f1d3 146
embeddedartists 27:aa2fd412f1d3 147 LPC_IOCON->P0_29 &= ~0x9F; // USB_D+1
embeddedartists 27:aa2fd412f1d3 148 LPC_IOCON->P0_29 |= 0x01; // USB_D+1
embeddedartists 27:aa2fd412f1d3 149 LPC_IOCON->P0_30 &= ~0x9F; // USB_D-1
embeddedartists 27:aa2fd412f1d3 150 LPC_IOCON->P0_30 |= 0x01; // USB_D-1
embeddedartists 27:aa2fd412f1d3 151
embeddedartists 27:aa2fd412f1d3 152 LPC_IOCON->P0_31 &= ~0x9F; // USB_D+2
embeddedartists 27:aa2fd412f1d3 153 LPC_IOCON->P0_31 |= 0x01; // USB_D+2
embeddedartists 27:aa2fd412f1d3 154
embeddedartists 27:aa2fd412f1d3 155 LPC_IOCON->P1_30 &= ~0x1F; // USB_PWRD2
embeddedartists 27:aa2fd412f1d3 156 LPC_IOCON->P1_30 |= 0x01; // USB_PWRD2
embeddedartists 27:aa2fd412f1d3 157 LPC_IOCON->P1_31 &= ~0x1F; // USB_OVRCR2
embeddedartists 27:aa2fd412f1d3 158 LPC_IOCON->P1_31 |= 0x01; // USB_OVRCR2
embeddedartists 27:aa2fd412f1d3 159
embeddedartists 27:aa2fd412f1d3 160 LPC_IOCON->P0_14 &= ~0x1F; // USB ID Pin as GPIO, output, high
embeddedartists 27:aa2fd412f1d3 161 LPC_GPIO0->DIR |= (1<<14);
embeddedartists 27:aa2fd412f1d3 162 LPC_GPIO0->SET = (1<<14);
embeddedartists 27:aa2fd412f1d3 163 LPC_IOCON->P4_31 &= ~0x1F; // USB CONN Pin as GPIO, output, low
embeddedartists 27:aa2fd412f1d3 164 LPC_GPIO4->DIR |= (1UL<<31);
embeddedartists 27:aa2fd412f1d3 165 LPC_GPIO4->CLR = (1UL<<31);
embeddedartists 27:aa2fd412f1d3 166
embeddedartists 27:aa2fd412f1d3 167 USB_DBG("initialize OHCI\n");
embeddedartists 27:aa2fd412f1d3 168
embeddedartists 27:aa2fd412f1d3 169 // Wait 100 ms before apply reset
embeddedartists 32:f2d129436056 170 ThisThread::sleep_for(100);
mbed_official 0:a554658735bf 171
mbed_official 0:a554658735bf 172 LPC_USB->HcControl = 0; // HARDWARE RESET
mbed_official 0:a554658735bf 173 LPC_USB->HcControlHeadED = 0; // Initialize Control list head to Zero
mbed_official 0:a554658735bf 174 LPC_USB->HcBulkHeadED = 0; // Initialize Bulk list head to Zero
mbed_official 0:a554658735bf 175
mbed_official 0:a554658735bf 176 // software reset
mbed_official 0:a554658735bf 177 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
mbed_official 24:868cbfe611a7 178
mbed_official 0:a554658735bf 179 // Write Fm Interval and Largest Data Packet Counter
mbed_official 0:a554658735bf 180 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL;
mbed_official 0:a554658735bf 181 LPC_USB->HcPeriodicStart = FI * 90 / 100;
mbed_official 0:a554658735bf 182
mbed_official 0:a554658735bf 183 // Put HC in operational state
mbed_official 0:a554658735bf 184 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
embeddedartists 27:aa2fd412f1d3 185
mbed_official 0:a554658735bf 186 // Set Global Power
mbed_official 0:a554658735bf 187 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;
mbed_official 0:a554658735bf 188
mbed_official 0:a554658735bf 189 LPC_USB->HcHCCA = (uint32_t)(usb_hcca);
mbed_official 24:868cbfe611a7 190
mbed_official 0:a554658735bf 191 // Clear Interrrupt Status
mbed_official 0:a554658735bf 192 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
mbed_official 0:a554658735bf 193
mbed_official 0:a554658735bf 194 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC;
mbed_official 0:a554658735bf 195
mbed_official 0:a554658735bf 196 // Enable the USB Interrupt
mbed_official 0:a554658735bf 197 NVIC_SetVector(USB_IRQn, (uint32_t)(_usbisr));
mbed_official 0:a554658735bf 198 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
mbed_official 0:a554658735bf 199 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
embeddedartists 27:aa2fd412f1d3 200 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_CSC;
embeddedartists 27:aa2fd412f1d3 201 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_PRSC;
embeddedartists 27:aa2fd412f1d3 202 resetRootHub();
embeddedartists 27:aa2fd412f1d3 203 NVIC_SetPriority(USB_IRQn, 0);
mbed_official 0:a554658735bf 204 NVIC_EnableIRQ(USB_IRQn);
mbed_official 0:a554658735bf 205
embeddedartists 27:aa2fd412f1d3 206 if (LPC_USB->HcRhPortStatus2 & OR_RH_PORT_CCS) {
mbed_official 0:a554658735bf 207 //Device connected
embeddedartists 32:f2d129436056 208 ThisThread::sleep_for(150);
embeddedartists 27:aa2fd412f1d3 209 USB_DBG("Device connected (%08x)\n\r", LPC_USB->HcRhPortStatus2);
embeddedartists 27:aa2fd412f1d3 210 deviceConnected(0, 2, LPC_USB->HcRhPortStatus2 & OR_RH_PORT_LSDA);
mbed_official 0:a554658735bf 211 }
mbed_official 0:a554658735bf 212 }
mbed_official 0:a554658735bf 213
mbed_official 0:a554658735bf 214 uint32_t USBHALHost::controlHeadED() {
mbed_official 0:a554658735bf 215 return LPC_USB->HcControlHeadED;
mbed_official 0:a554658735bf 216 }
mbed_official 0:a554658735bf 217
mbed_official 0:a554658735bf 218 uint32_t USBHALHost::bulkHeadED() {
mbed_official 0:a554658735bf 219 return LPC_USB->HcBulkHeadED;
mbed_official 0:a554658735bf 220 }
mbed_official 0:a554658735bf 221
mbed_official 0:a554658735bf 222 uint32_t USBHALHost::interruptHeadED() {
mbed_official 0:a554658735bf 223 return usb_hcca->IntTable[0];
mbed_official 0:a554658735bf 224 }
mbed_official 0:a554658735bf 225
mbed_official 0:a554658735bf 226 void USBHALHost::updateBulkHeadED(uint32_t addr) {
mbed_official 0:a554658735bf 227 LPC_USB->HcBulkHeadED = addr;
mbed_official 0:a554658735bf 228 }
mbed_official 0:a554658735bf 229
mbed_official 0:a554658735bf 230
mbed_official 0:a554658735bf 231 void USBHALHost::updateControlHeadED(uint32_t addr) {
mbed_official 0:a554658735bf 232 LPC_USB->HcControlHeadED = addr;
mbed_official 0:a554658735bf 233 }
mbed_official 0:a554658735bf 234
mbed_official 0:a554658735bf 235 void USBHALHost::updateInterruptHeadED(uint32_t addr) {
mbed_official 0:a554658735bf 236 usb_hcca->IntTable[0] = addr;
mbed_official 0:a554658735bf 237 }
mbed_official 0:a554658735bf 238
mbed_official 0:a554658735bf 239
mbed_official 0:a554658735bf 240 void USBHALHost::enableList(ENDPOINT_TYPE type) {
mbed_official 0:a554658735bf 241 switch(type) {
mbed_official 0:a554658735bf 242 case CONTROL_ENDPOINT:
mbed_official 0:a554658735bf 243 LPC_USB->HcCommandStatus = OR_CMD_STATUS_CLF;
mbed_official 0:a554658735bf 244 LPC_USB->HcControl |= OR_CONTROL_CLE;
mbed_official 0:a554658735bf 245 break;
mbed_official 0:a554658735bf 246 case ISOCHRONOUS_ENDPOINT:
mbed_official 0:a554658735bf 247 break;
mbed_official 0:a554658735bf 248 case BULK_ENDPOINT:
mbed_official 0:a554658735bf 249 LPC_USB->HcCommandStatus = OR_CMD_STATUS_BLF;
mbed_official 0:a554658735bf 250 LPC_USB->HcControl |= OR_CONTROL_BLE;
mbed_official 0:a554658735bf 251 break;
mbed_official 0:a554658735bf 252 case INTERRUPT_ENDPOINT:
mbed_official 0:a554658735bf 253 LPC_USB->HcControl |= OR_CONTROL_PLE;
mbed_official 0:a554658735bf 254 break;
mbed_official 0:a554658735bf 255 }
mbed_official 0:a554658735bf 256 }
mbed_official 0:a554658735bf 257
mbed_official 0:a554658735bf 258
mbed_official 0:a554658735bf 259 bool USBHALHost::disableList(ENDPOINT_TYPE type) {
mbed_official 0:a554658735bf 260 switch(type) {
mbed_official 0:a554658735bf 261 case CONTROL_ENDPOINT:
mbed_official 0:a554658735bf 262 if(LPC_USB->HcControl & OR_CONTROL_CLE) {
mbed_official 0:a554658735bf 263 LPC_USB->HcControl &= ~OR_CONTROL_CLE;
mbed_official 0:a554658735bf 264 return true;
mbed_official 0:a554658735bf 265 }
mbed_official 0:a554658735bf 266 return false;
mbed_official 0:a554658735bf 267 case ISOCHRONOUS_ENDPOINT:
mbed_official 0:a554658735bf 268 return false;
mbed_official 0:a554658735bf 269 case BULK_ENDPOINT:
mbed_official 0:a554658735bf 270 if(LPC_USB->HcControl & OR_CONTROL_BLE){
mbed_official 0:a554658735bf 271 LPC_USB->HcControl &= ~OR_CONTROL_BLE;
mbed_official 0:a554658735bf 272 return true;
mbed_official 0:a554658735bf 273 }
mbed_official 0:a554658735bf 274 return false;
mbed_official 0:a554658735bf 275 case INTERRUPT_ENDPOINT:
mbed_official 0:a554658735bf 276 if(LPC_USB->HcControl & OR_CONTROL_PLE) {
mbed_official 0:a554658735bf 277 LPC_USB->HcControl &= ~OR_CONTROL_PLE;
mbed_official 0:a554658735bf 278 return true;
mbed_official 0:a554658735bf 279 }
mbed_official 0:a554658735bf 280 return false;
mbed_official 0:a554658735bf 281 }
mbed_official 0:a554658735bf 282 return false;
mbed_official 0:a554658735bf 283 }
mbed_official 0:a554658735bf 284
mbed_official 0:a554658735bf 285
mbed_official 0:a554658735bf 286 void USBHALHost::memInit() {
mbed_official 0:a554658735bf 287 usb_hcca = (volatile HCCA *)usb_buf;
mbed_official 0:a554658735bf 288 usb_edBuf = usb_buf + HCCA_SIZE;
mbed_official 0:a554658735bf 289 usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE);
mbed_official 0:a554658735bf 290 }
mbed_official 0:a554658735bf 291
mbed_official 0:a554658735bf 292 volatile uint8_t * USBHALHost::getED() {
mbed_official 0:a554658735bf 293 for (int i = 0; i < MAX_ENDPOINT; i++) {
mbed_official 0:a554658735bf 294 if ( !edBufAlloc[i] ) {
mbed_official 0:a554658735bf 295 edBufAlloc[i] = true;
mbed_official 0:a554658735bf 296 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE);
mbed_official 0:a554658735bf 297 }
mbed_official 0:a554658735bf 298 }
embeddedartists 27:aa2fd412f1d3 299 USB_ERR("Could not allocate ED\r\n");
embeddedartists 27:aa2fd412f1d3 300 return NULL;
mbed_official 0:a554658735bf 301 }
mbed_official 0:a554658735bf 302
mbed_official 0:a554658735bf 303 volatile uint8_t * USBHALHost::getTD() {
mbed_official 0:a554658735bf 304 int i;
mbed_official 0:a554658735bf 305 for (i = 0; i < MAX_TD; i++) {
mbed_official 0:a554658735bf 306 if ( !tdBufAlloc[i] ) {
mbed_official 0:a554658735bf 307 tdBufAlloc[i] = true;
mbed_official 0:a554658735bf 308 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE);
mbed_official 0:a554658735bf 309 }
mbed_official 0:a554658735bf 310 }
embeddedartists 27:aa2fd412f1d3 311 USB_ERR("Could not allocate TD\r\n");
embeddedartists 27:aa2fd412f1d3 312 return NULL;
mbed_official 0:a554658735bf 313 }
mbed_official 0:a554658735bf 314
mbed_official 0:a554658735bf 315
mbed_official 0:a554658735bf 316 void USBHALHost::freeED(volatile uint8_t * ed) {
mbed_official 0:a554658735bf 317 int i;
mbed_official 0:a554658735bf 318 i = (ed - usb_edBuf) / ED_SIZE;
mbed_official 0:a554658735bf 319 edBufAlloc[i] = false;
mbed_official 0:a554658735bf 320 }
mbed_official 0:a554658735bf 321
mbed_official 0:a554658735bf 322 void USBHALHost::freeTD(volatile uint8_t * td) {
mbed_official 0:a554658735bf 323 int i;
mbed_official 0:a554658735bf 324 i = (td - usb_tdBuf) / TD_SIZE;
mbed_official 0:a554658735bf 325 tdBufAlloc[i] = false;
mbed_official 0:a554658735bf 326 }
mbed_official 0:a554658735bf 327
mbed_official 0:a554658735bf 328
mbed_official 0:a554658735bf 329 void USBHALHost::resetRootHub() {
embeddedartists 27:aa2fd412f1d3 330
embeddedartists 27:aa2fd412f1d3 331 DigitalOut usb2_vbus_en(P0_12);
embeddedartists 27:aa2fd412f1d3 332 usb2_vbus_en = 1;
embeddedartists 32:f2d129436056 333 ThisThread::sleep_for(100); /* USB 2.0 spec says at least 50ms delay before port reset */
embeddedartists 27:aa2fd412f1d3 334
mbed_official 0:a554658735bf 335 // Initiate port reset
samux 4:b320d68e98e7 336 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS;
mbed_official 24:868cbfe611a7 337
mbed_official 0:a554658735bf 338 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS);
mbed_official 24:868cbfe611a7 339
mbed_official 0:a554658735bf 340 // ...and clear port reset signal
mbed_official 0:a554658735bf 341 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
embeddedartists 27:aa2fd412f1d3 342
embeddedartists 27:aa2fd412f1d3 343 usb2_vbus_en = 0;
embeddedartists 27:aa2fd412f1d3 344
embeddedartists 27:aa2fd412f1d3 345 // Initiate port reset
embeddedartists 27:aa2fd412f1d3 346 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_PRS;
embeddedartists 27:aa2fd412f1d3 347
embeddedartists 27:aa2fd412f1d3 348 while (LPC_USB->HcRhPortStatus2 & OR_RH_PORT_PRS);
embeddedartists 27:aa2fd412f1d3 349
embeddedartists 27:aa2fd412f1d3 350 // ...and clear port reset signal
embeddedartists 27:aa2fd412f1d3 351 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_PRSC;
embeddedartists 27:aa2fd412f1d3 352
embeddedartists 27:aa2fd412f1d3 353 usb2_vbus_en = 1;
embeddedartists 32:f2d129436056 354 ThisThread::sleep_for(200); /* Wait for at least 100 MS after port reset */
mbed_official 0:a554658735bf 355 }
mbed_official 0:a554658735bf 356
mbed_official 0:a554658735bf 357
mbed_official 0:a554658735bf 358 void USBHALHost::_usbisr(void) {
mbed_official 0:a554658735bf 359 if (instHost) {
embeddedartists 33:819bbf04163b 360 instHost->UsbIrqhandler();
mbed_official 0:a554658735bf 361 }
mbed_official 0:a554658735bf 362 }
mbed_official 0:a554658735bf 363
mbed_official 0:a554658735bf 364 void USBHALHost::UsbIrqhandler() {
embeddedartists 33:819bbf04163b 365
mbed_official 0:a554658735bf 366 if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process?
mbed_official 0:a554658735bf 367 {
mbed_official 0:a554658735bf 368 uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable;
embeddedartists 27:aa2fd412f1d3 369
mbed_official 0:a554658735bf 370 // Root hub status change interrupt
mbed_official 24:868cbfe611a7 371 if (int_status & OR_INTR_STATUS_RHSC) {
embeddedartists 27:aa2fd412f1d3 372 if (LPC_USB->HcRhPortStatus2 & OR_RH_PORT_CSC) {
mbed_official 0:a554658735bf 373 if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) {
mbed_official 0:a554658735bf 374 // When DRWE is on, Connect Status Change
mbed_official 0:a554658735bf 375 // means a remote wakeup event.
mbed_official 0:a554658735bf 376 } else {
mbed_official 0:a554658735bf 377
mbed_official 0:a554658735bf 378 //Root device connected
embeddedartists 27:aa2fd412f1d3 379 if (LPC_USB->HcRhPortStatus2 & OR_RH_PORT_CCS) {
mbed_official 24:868cbfe611a7 380
embeddedartists 33:819bbf04163b 381 // wait 150ms to avoid bounce (removed since wait is not allowed in isr)
embeddedartists 33:819bbf04163b 382 //ThisThread::sleep_for(150);
mbed_official 24:868cbfe611a7 383
embeddedartists 27:aa2fd412f1d3 384 //Hub 0 (root hub), Port 2 (count starts at 1), Low or High speed
embeddedartists 27:aa2fd412f1d3 385 deviceConnected(0, 2, LPC_USB->HcRhPortStatus2 & OR_RH_PORT_LSDA);
mbed_official 24:868cbfe611a7 386 }
mbed_official 24:868cbfe611a7 387
mbed_official 0:a554658735bf 388 //Root device disconnected
mbed_official 24:868cbfe611a7 389 else {
mbed_official 24:868cbfe611a7 390
mbed_official 0:a554658735bf 391 if (!(int_status & OR_INTR_STATUS_WDH)) {
mbed_official 0:a554658735bf 392 usb_hcca->DoneHead = 0;
mbed_official 0:a554658735bf 393 }
mbed_official 24:868cbfe611a7 394
embeddedartists 33:819bbf04163b 395 // wait 200ms to avoid bounce (removed since wait is not allowed in isr)
embeddedartists 33:819bbf04163b 396 //wait_ms(200);
mbed_official 24:868cbfe611a7 397
embeddedartists 27:aa2fd412f1d3 398 deviceDisconnected(0, 2, NULL, usb_hcca->DoneHead & 0xFFFFFFFE);
mbed_official 24:868cbfe611a7 399
mbed_official 0:a554658735bf 400 if (int_status & OR_INTR_STATUS_WDH) {
mbed_official 0:a554658735bf 401 usb_hcca->DoneHead = 0;
mbed_official 0:a554658735bf 402 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
mbed_official 0:a554658735bf 403 }
mbed_official 0:a554658735bf 404 }
mbed_official 0:a554658735bf 405 }
embeddedartists 27:aa2fd412f1d3 406 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_CSC;
mbed_official 0:a554658735bf 407 }
embeddedartists 27:aa2fd412f1d3 408 if (LPC_USB->HcRhPortStatus2 & OR_RH_PORT_PRSC) {
embeddedartists 27:aa2fd412f1d3 409 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_PRSC;
mbed_official 0:a554658735bf 410 }
mbed_official 0:a554658735bf 411 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_RHSC;
mbed_official 0:a554658735bf 412 }
mbed_official 0:a554658735bf 413
mbed_official 0:a554658735bf 414 // Writeback Done Head interrupt
mbed_official 0:a554658735bf 415 if (int_status & OR_INTR_STATUS_WDH) {
mbed_official 0:a554658735bf 416 transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE);
mbed_official 0:a554658735bf 417 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
mbed_official 0:a554658735bf 418 }
mbed_official 0:a554658735bf 419 }
mbed_official 0:a554658735bf 420 }