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:
Tue Feb 17 10:36:26 2015 +0100
Revision:
31:9a462d032742
Parent:
27:aa2fd412f1d3
Child:
32:f2d129436056
- Replaced wait_ms with Thread::wait
- Added TARGET_LPC4088_DM

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 27:aa2fd412f1d3 42 // Put the USB structures in the only memory accessible by the USB stack - the AHBSRAM0
embeddedartists 27:aa2fd412f1d3 43 static volatile uint8_t usb_buf[TOTAL_SIZE] __attribute__((section("AHBSRAM0"),aligned(256)));// __attribute__((section("AHBSRAM0"),aligned(256))); //256 bytes aligned!
embeddedartists 27:aa2fd412f1d3 44
embeddedartists 27:aa2fd412f1d3 45 // A very basic implementation of malloc to allocate in the AHBSRAM0
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 27:aa2fd412f1d3 54 static uint8_t safe_mem_data[SAFE_MEM_TO_USE] __attribute__((section("AHBSRAM0"),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 }
mbed_official 0:a554658735bf 81 }
mbed_official 0:a554658735bf 82
embeddedartists 27:aa2fd412f1d3 83 uint8_t* USBHALHost::getSafeMem(uint32_t size) {
embeddedartists 27:aa2fd412f1d3 84 uint8_t* result = NULL;
embeddedartists 27:aa2fd412f1d3 85 if (size > 512) {
embeddedartists 27:aa2fd412f1d3 86 USB_ERR("getSafeMem(%u) not supported", size);
embeddedartists 27:aa2fd412f1d3 87 } else {
embeddedartists 27:aa2fd412f1d3 88 safemem_mutex.lock();
embeddedartists 27:aa2fd412f1d3 89 for (int i = 0; i < SAFE_MEM_NUM_BLOCKS; i++) {
embeddedartists 27:aa2fd412f1d3 90 if (!safe_mem_list[i].used) {
embeddedartists 27:aa2fd412f1d3 91 safe_mem_list[i].used = true;
embeddedartists 27:aa2fd412f1d3 92 result = (uint8_t*)safe_mem_list[i].ptr;
embeddedartists 27:aa2fd412f1d3 93 break;
embeddedartists 27:aa2fd412f1d3 94 }
embeddedartists 27:aa2fd412f1d3 95 }
embeddedartists 27:aa2fd412f1d3 96 safemem_mutex.unlock();
embeddedartists 27:aa2fd412f1d3 97 }
embeddedartists 27:aa2fd412f1d3 98 if (result == NULL) {
embeddedartists 27:aa2fd412f1d3 99 USB_ERR("getSafeMem(%u) failed to allocate", size);
embeddedartists 27:aa2fd412f1d3 100 }
embeddedartists 27:aa2fd412f1d3 101 return result;
embeddedartists 27:aa2fd412f1d3 102 }
embeddedartists 27:aa2fd412f1d3 103
embeddedartists 27:aa2fd412f1d3 104 void USBHALHost::returnSafeMem(uint8_t* mem) {
embeddedartists 27:aa2fd412f1d3 105 safemem_mutex.lock();
embeddedartists 27:aa2fd412f1d3 106 int i;
embeddedartists 27:aa2fd412f1d3 107 for (i = 0; i < SAFE_MEM_NUM_BLOCKS; i++) {
embeddedartists 27:aa2fd412f1d3 108 if (safe_mem_list[i].ptr == mem) {
embeddedartists 27:aa2fd412f1d3 109 safe_mem_list[i].used = false;
embeddedartists 27:aa2fd412f1d3 110 break;
embeddedartists 27:aa2fd412f1d3 111 }
embeddedartists 27:aa2fd412f1d3 112 }
embeddedartists 27:aa2fd412f1d3 113 safemem_mutex.unlock();
embeddedartists 27:aa2fd412f1d3 114 if (i == SAFE_MEM_NUM_BLOCKS) {
embeddedartists 27:aa2fd412f1d3 115 USB_ERR("returnSafeMem(%p) not allocated", mem);
embeddedartists 27:aa2fd412f1d3 116 }
embeddedartists 27:aa2fd412f1d3 117 }
embeddedartists 27:aa2fd412f1d3 118
embeddedartists 27:aa2fd412f1d3 119
mbed_official 0:a554658735bf 120 void USBHALHost::init() {
mbed_official 0:a554658735bf 121 NVIC_DisableIRQ(USB_IRQn);
mbed_official 24:868cbfe611a7 122
mbed_official 0:a554658735bf 123 //Cut power
mbed_official 0:a554658735bf 124 LPC_SC->PCONP &= ~(1UL<<31);
embeddedartists 31:9a462d032742 125 Thread::wait(1000);
mbed_official 0:a554658735bf 126
mbed_official 0:a554658735bf 127 // turn on power for USB
mbed_official 0:a554658735bf 128 LPC_SC->PCONP |= (1UL<<31);
mbed_official 0:a554658735bf 129
mbed_official 0:a554658735bf 130 // Enable USB host clock, port selection and AHB clock
embeddedartists 27:aa2fd412f1d3 131 LPC_USB->USBClkCtrl = 0x19;
mbed_official 0:a554658735bf 132
mbed_official 0:a554658735bf 133 // Wait for clocks to become available
embeddedartists 27:aa2fd412f1d3 134 while ((LPC_USB->USBClkSt & 0x19) != 0x19);
mbed_official 0:a554658735bf 135
mbed_official 0:a554658735bf 136 // it seems the bits[0:1] mean the following
mbed_official 0:a554658735bf 137 // 0: U1=device, U2=host
mbed_official 0:a554658735bf 138 // 1: U1=host, U2=host
mbed_official 0:a554658735bf 139 // 2: reserved
mbed_official 0:a554658735bf 140 // 3: U1=host, U2=device
mbed_official 0:a554658735bf 141 // NB: this register is only available if OTG clock (aka "port select") is enabled!!
embeddedartists 27:aa2fd412f1d3 142 LPC_USB->OTGStCtrl = 1;
mbed_official 0:a554658735bf 143
mbed_official 0:a554658735bf 144 // configure USB D+/D- pins
embeddedartists 27:aa2fd412f1d3 145
embeddedartists 27:aa2fd412f1d3 146 LPC_IOCON->P0_29 &= ~0x9F; // USB_D+1
embeddedartists 27:aa2fd412f1d3 147 LPC_IOCON->P0_29 |= 0x01; // USB_D+1
embeddedartists 27:aa2fd412f1d3 148 LPC_IOCON->P0_30 &= ~0x9F; // USB_D-1
embeddedartists 27:aa2fd412f1d3 149 LPC_IOCON->P0_30 |= 0x01; // USB_D-1
embeddedartists 27:aa2fd412f1d3 150
embeddedartists 27:aa2fd412f1d3 151 LPC_IOCON->P0_31 &= ~0x9F; // USB_D+2
embeddedartists 27:aa2fd412f1d3 152 LPC_IOCON->P0_31 |= 0x01; // USB_D+2
embeddedartists 27:aa2fd412f1d3 153
embeddedartists 27:aa2fd412f1d3 154 LPC_IOCON->P1_30 &= ~0x1F; // USB_PWRD2
embeddedartists 27:aa2fd412f1d3 155 LPC_IOCON->P1_30 |= 0x01; // USB_PWRD2
embeddedartists 27:aa2fd412f1d3 156 LPC_IOCON->P1_31 &= ~0x1F; // USB_OVRCR2
embeddedartists 27:aa2fd412f1d3 157 LPC_IOCON->P1_31 |= 0x01; // USB_OVRCR2
embeddedartists 27:aa2fd412f1d3 158
embeddedartists 27:aa2fd412f1d3 159 LPC_IOCON->P0_14 &= ~0x1F; // USB ID Pin as GPIO, output, high
embeddedartists 27:aa2fd412f1d3 160 LPC_GPIO0->DIR |= (1<<14);
embeddedartists 27:aa2fd412f1d3 161 LPC_GPIO0->SET = (1<<14);
embeddedartists 27:aa2fd412f1d3 162 LPC_IOCON->P4_31 &= ~0x1F; // USB CONN Pin as GPIO, output, low
embeddedartists 27:aa2fd412f1d3 163 LPC_GPIO4->DIR |= (1UL<<31);
embeddedartists 27:aa2fd412f1d3 164 LPC_GPIO4->CLR = (1UL<<31);
embeddedartists 27:aa2fd412f1d3 165
embeddedartists 27:aa2fd412f1d3 166 USB_DBG("initialize OHCI\n");
embeddedartists 27:aa2fd412f1d3 167
embeddedartists 27:aa2fd412f1d3 168 // Wait 100 ms before apply reset
embeddedartists 31:9a462d032742 169 Thread::wait(100);
mbed_official 0:a554658735bf 170
mbed_official 0:a554658735bf 171 LPC_USB->HcControl = 0; // HARDWARE RESET
mbed_official 0:a554658735bf 172 LPC_USB->HcControlHeadED = 0; // Initialize Control list head to Zero
mbed_official 0:a554658735bf 173 LPC_USB->HcBulkHeadED = 0; // Initialize Bulk list head to Zero
mbed_official 0:a554658735bf 174
mbed_official 0:a554658735bf 175 // software reset
mbed_official 0:a554658735bf 176 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
mbed_official 24:868cbfe611a7 177
mbed_official 0:a554658735bf 178 // Write Fm Interval and Largest Data Packet Counter
mbed_official 0:a554658735bf 179 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL;
mbed_official 0:a554658735bf 180 LPC_USB->HcPeriodicStart = FI * 90 / 100;
mbed_official 0:a554658735bf 181
mbed_official 0:a554658735bf 182 // Put HC in operational state
mbed_official 0:a554658735bf 183 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
embeddedartists 27:aa2fd412f1d3 184
mbed_official 0:a554658735bf 185 // Set Global Power
mbed_official 0:a554658735bf 186 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;
mbed_official 0:a554658735bf 187
mbed_official 0:a554658735bf 188 LPC_USB->HcHCCA = (uint32_t)(usb_hcca);
mbed_official 24:868cbfe611a7 189
mbed_official 0:a554658735bf 190 // Clear Interrrupt Status
mbed_official 0:a554658735bf 191 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
mbed_official 0:a554658735bf 192
mbed_official 0:a554658735bf 193 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC;
mbed_official 0:a554658735bf 194
mbed_official 0:a554658735bf 195 // Enable the USB Interrupt
mbed_official 0:a554658735bf 196 NVIC_SetVector(USB_IRQn, (uint32_t)(_usbisr));
mbed_official 0:a554658735bf 197 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
mbed_official 0:a554658735bf 198 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
embeddedartists 27:aa2fd412f1d3 199 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_CSC;
embeddedartists 27:aa2fd412f1d3 200 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_PRSC;
embeddedartists 27:aa2fd412f1d3 201
embeddedartists 27:aa2fd412f1d3 202 resetRootHub();
mbed_official 0:a554658735bf 203
embeddedartists 27:aa2fd412f1d3 204 NVIC_SetPriority(USB_IRQn, 0);
mbed_official 0:a554658735bf 205 NVIC_EnableIRQ(USB_IRQn);
mbed_official 0:a554658735bf 206
embeddedartists 27:aa2fd412f1d3 207 if (LPC_USB->HcRhPortStatus2 & OR_RH_PORT_CCS) {
mbed_official 0:a554658735bf 208 //Device connected
embeddedartists 31:9a462d032742 209 Thread::wait(150);
embeddedartists 27:aa2fd412f1d3 210 USB_DBG("Device connected (%08x)\n\r", LPC_USB->HcRhPortStatus2);
embeddedartists 27:aa2fd412f1d3 211 deviceConnected(0, 2, LPC_USB->HcRhPortStatus2 & OR_RH_PORT_LSDA);
mbed_official 0:a554658735bf 212 }
mbed_official 0:a554658735bf 213 }
mbed_official 0:a554658735bf 214
mbed_official 0:a554658735bf 215 uint32_t USBHALHost::controlHeadED() {
mbed_official 0:a554658735bf 216 return LPC_USB->HcControlHeadED;
mbed_official 0:a554658735bf 217 }
mbed_official 0:a554658735bf 218
mbed_official 0:a554658735bf 219 uint32_t USBHALHost::bulkHeadED() {
mbed_official 0:a554658735bf 220 return LPC_USB->HcBulkHeadED;
mbed_official 0:a554658735bf 221 }
mbed_official 0:a554658735bf 222
mbed_official 0:a554658735bf 223 uint32_t USBHALHost::interruptHeadED() {
mbed_official 0:a554658735bf 224 return usb_hcca->IntTable[0];
mbed_official 0:a554658735bf 225 }
mbed_official 0:a554658735bf 226
mbed_official 0:a554658735bf 227 void USBHALHost::updateBulkHeadED(uint32_t addr) {
mbed_official 0:a554658735bf 228 LPC_USB->HcBulkHeadED = addr;
mbed_official 0:a554658735bf 229 }
mbed_official 0:a554658735bf 230
mbed_official 0:a554658735bf 231
mbed_official 0:a554658735bf 232 void USBHALHost::updateControlHeadED(uint32_t addr) {
mbed_official 0:a554658735bf 233 LPC_USB->HcControlHeadED = addr;
mbed_official 0:a554658735bf 234 }
mbed_official 0:a554658735bf 235
mbed_official 0:a554658735bf 236 void USBHALHost::updateInterruptHeadED(uint32_t addr) {
mbed_official 0:a554658735bf 237 usb_hcca->IntTable[0] = addr;
mbed_official 0:a554658735bf 238 }
mbed_official 0:a554658735bf 239
mbed_official 0:a554658735bf 240
mbed_official 0:a554658735bf 241 void USBHALHost::enableList(ENDPOINT_TYPE type) {
mbed_official 0:a554658735bf 242 switch(type) {
mbed_official 0:a554658735bf 243 case CONTROL_ENDPOINT:
mbed_official 0:a554658735bf 244 LPC_USB->HcCommandStatus = OR_CMD_STATUS_CLF;
mbed_official 0:a554658735bf 245 LPC_USB->HcControl |= OR_CONTROL_CLE;
mbed_official 0:a554658735bf 246 break;
mbed_official 0:a554658735bf 247 case ISOCHRONOUS_ENDPOINT:
mbed_official 0:a554658735bf 248 break;
mbed_official 0:a554658735bf 249 case BULK_ENDPOINT:
mbed_official 0:a554658735bf 250 LPC_USB->HcCommandStatus = OR_CMD_STATUS_BLF;
mbed_official 0:a554658735bf 251 LPC_USB->HcControl |= OR_CONTROL_BLE;
mbed_official 0:a554658735bf 252 break;
mbed_official 0:a554658735bf 253 case INTERRUPT_ENDPOINT:
mbed_official 0:a554658735bf 254 LPC_USB->HcControl |= OR_CONTROL_PLE;
mbed_official 0:a554658735bf 255 break;
mbed_official 0:a554658735bf 256 }
mbed_official 0:a554658735bf 257 }
mbed_official 0:a554658735bf 258
mbed_official 0:a554658735bf 259
mbed_official 0:a554658735bf 260 bool USBHALHost::disableList(ENDPOINT_TYPE type) {
mbed_official 0:a554658735bf 261 switch(type) {
mbed_official 0:a554658735bf 262 case CONTROL_ENDPOINT:
mbed_official 0:a554658735bf 263 if(LPC_USB->HcControl & OR_CONTROL_CLE) {
mbed_official 0:a554658735bf 264 LPC_USB->HcControl &= ~OR_CONTROL_CLE;
mbed_official 0:a554658735bf 265 return true;
mbed_official 0:a554658735bf 266 }
mbed_official 0:a554658735bf 267 return false;
mbed_official 0:a554658735bf 268 case ISOCHRONOUS_ENDPOINT:
mbed_official 0:a554658735bf 269 return false;
mbed_official 0:a554658735bf 270 case BULK_ENDPOINT:
mbed_official 0:a554658735bf 271 if(LPC_USB->HcControl & OR_CONTROL_BLE){
mbed_official 0:a554658735bf 272 LPC_USB->HcControl &= ~OR_CONTROL_BLE;
mbed_official 0:a554658735bf 273 return true;
mbed_official 0:a554658735bf 274 }
mbed_official 0:a554658735bf 275 return false;
mbed_official 0:a554658735bf 276 case INTERRUPT_ENDPOINT:
mbed_official 0:a554658735bf 277 if(LPC_USB->HcControl & OR_CONTROL_PLE) {
mbed_official 0:a554658735bf 278 LPC_USB->HcControl &= ~OR_CONTROL_PLE;
mbed_official 0:a554658735bf 279 return true;
mbed_official 0:a554658735bf 280 }
mbed_official 0:a554658735bf 281 return false;
mbed_official 0:a554658735bf 282 }
mbed_official 0:a554658735bf 283 return false;
mbed_official 0:a554658735bf 284 }
mbed_official 0:a554658735bf 285
mbed_official 0:a554658735bf 286
mbed_official 0:a554658735bf 287 void USBHALHost::memInit() {
mbed_official 0:a554658735bf 288 usb_hcca = (volatile HCCA *)usb_buf;
mbed_official 0:a554658735bf 289 usb_edBuf = usb_buf + HCCA_SIZE;
mbed_official 0:a554658735bf 290 usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE);
mbed_official 0:a554658735bf 291 }
mbed_official 0:a554658735bf 292
mbed_official 0:a554658735bf 293 volatile uint8_t * USBHALHost::getED() {
mbed_official 0:a554658735bf 294 for (int i = 0; i < MAX_ENDPOINT; i++) {
mbed_official 0:a554658735bf 295 if ( !edBufAlloc[i] ) {
mbed_official 0:a554658735bf 296 edBufAlloc[i] = true;
mbed_official 0:a554658735bf 297 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE);
mbed_official 0:a554658735bf 298 }
mbed_official 0:a554658735bf 299 }
embeddedartists 27:aa2fd412f1d3 300 USB_ERR("Could not allocate ED\r\n");
embeddedartists 27:aa2fd412f1d3 301 return NULL;
mbed_official 0:a554658735bf 302 }
mbed_official 0:a554658735bf 303
mbed_official 0:a554658735bf 304 volatile uint8_t * USBHALHost::getTD() {
mbed_official 0:a554658735bf 305 int i;
mbed_official 0:a554658735bf 306 for (i = 0; i < MAX_TD; i++) {
mbed_official 0:a554658735bf 307 if ( !tdBufAlloc[i] ) {
mbed_official 0:a554658735bf 308 tdBufAlloc[i] = true;
mbed_official 0:a554658735bf 309 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE);
mbed_official 0:a554658735bf 310 }
mbed_official 0:a554658735bf 311 }
embeddedartists 27:aa2fd412f1d3 312 USB_ERR("Could not allocate TD\r\n");
embeddedartists 27:aa2fd412f1d3 313 return NULL;
mbed_official 0:a554658735bf 314 }
mbed_official 0:a554658735bf 315
mbed_official 0:a554658735bf 316
mbed_official 0:a554658735bf 317 void USBHALHost::freeED(volatile uint8_t * ed) {
mbed_official 0:a554658735bf 318 int i;
mbed_official 0:a554658735bf 319 i = (ed - usb_edBuf) / ED_SIZE;
mbed_official 0:a554658735bf 320 edBufAlloc[i] = false;
mbed_official 0:a554658735bf 321 }
mbed_official 0:a554658735bf 322
mbed_official 0:a554658735bf 323 void USBHALHost::freeTD(volatile uint8_t * td) {
mbed_official 0:a554658735bf 324 int i;
mbed_official 0:a554658735bf 325 i = (td - usb_tdBuf) / TD_SIZE;
mbed_official 0:a554658735bf 326 tdBufAlloc[i] = false;
mbed_official 0:a554658735bf 327 }
mbed_official 0:a554658735bf 328
mbed_official 0:a554658735bf 329
mbed_official 0:a554658735bf 330 void USBHALHost::resetRootHub() {
embeddedartists 27:aa2fd412f1d3 331
embeddedartists 27:aa2fd412f1d3 332 DigitalOut usb2_vbus_en(P0_12);
embeddedartists 27:aa2fd412f1d3 333 usb2_vbus_en = 1;
embeddedartists 31:9a462d032742 334 Thread::wait(100); /* USB 2.0 spec says at least 50ms delay before port reset */
embeddedartists 27:aa2fd412f1d3 335
mbed_official 0:a554658735bf 336 // Initiate port reset
samux 4:b320d68e98e7 337 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS;
mbed_official 24:868cbfe611a7 338
mbed_official 0:a554658735bf 339 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS);
mbed_official 24:868cbfe611a7 340
mbed_official 0:a554658735bf 341 // ...and clear port reset signal
mbed_official 0:a554658735bf 342 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
embeddedartists 27:aa2fd412f1d3 343
embeddedartists 27:aa2fd412f1d3 344 usb2_vbus_en = 0;
embeddedartists 27:aa2fd412f1d3 345
embeddedartists 27:aa2fd412f1d3 346 // Initiate port reset
embeddedartists 27:aa2fd412f1d3 347 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_PRS;
embeddedartists 27:aa2fd412f1d3 348
embeddedartists 27:aa2fd412f1d3 349 while (LPC_USB->HcRhPortStatus2 & OR_RH_PORT_PRS);
embeddedartists 27:aa2fd412f1d3 350
embeddedartists 27:aa2fd412f1d3 351 // ...and clear port reset signal
embeddedartists 27:aa2fd412f1d3 352 LPC_USB->HcRhPortStatus2 = OR_RH_PORT_PRSC;
embeddedartists 27:aa2fd412f1d3 353
embeddedartists 27:aa2fd412f1d3 354 usb2_vbus_en = 1;
embeddedartists 31:9a462d032742 355 Thread::wait(200); /* Wait for at least 100 MS after port reset */
mbed_official 0:a554658735bf 356 }
mbed_official 0:a554658735bf 357
mbed_official 0:a554658735bf 358
mbed_official 0:a554658735bf 359 void USBHALHost::_usbisr(void) {
mbed_official 0:a554658735bf 360 if (instHost) {
mbed_official 0:a554658735bf 361 instHost->UsbIrqhandler();
mbed_official 0:a554658735bf 362 }
mbed_official 0:a554658735bf 363 }
mbed_official 0:a554658735bf 364
mbed_official 0:a554658735bf 365 void USBHALHost::UsbIrqhandler() {
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
samux 4:b320d68e98e7 381 // wait 150ms to avoid bounce
samux 4:b320d68e98e7 382 wait_ms(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
samux 4:b320d68e98e7 395 // wait 200ms to avoid bounce
samux 4:b320d68e98e7 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 }