USBHOST lib for STM

Dependents:   door-access-controller-dev

Committer:
jamike
Date:
Wed Apr 26 20:08:31 2017 +0000
Revision:
6:d3ac9e1c0035
Parent:
1:ab240722d7ef
fix error in read and write

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 1 /* mbed USBHost Library
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 2 * Copyright (c) 2006-2013 ARM Limited
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 3 *
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 4 * Licensed under the Apache License, Version 2.0 (the "License");
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 5 * you may not use this file except in compliance with the License.
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 6 * You may obtain a copy of the License at
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 7 *
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 8 * http://www.apache.org/licenses/LICENSE-2.0
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 9 *
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 10 * Unless required by applicable law or agreed to in writing, software
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 11 * distributed under the License is distributed on an "AS IS" BASIS,
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 13 * See the License for the specific language governing permissions and
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 14 * limitations under the License.
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 15 */
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 16
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 17 #if defined(TARGET_LPC1768) || defined(TARGET_LPC2460)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 18
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 19 #include "mbed.h"
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 20 #include "USBHALHost.h"
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 21 #include "dbg.h"
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 22
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 23 // bits of the USB/OTG clock control register
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 24 #define HOST_CLK_EN (1<<0)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 25 #define DEV_CLK_EN (1<<1)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 26 #define PORTSEL_CLK_EN (1<<3)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 27 #define AHB_CLK_EN (1<<4)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 28
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 29 // bits of the USB/OTG clock status register
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 30 #define HOST_CLK_ON (1<<0)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 31 #define DEV_CLK_ON (1<<1)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 32 #define PORTSEL_CLK_ON (1<<3)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 33 #define AHB_CLK_ON (1<<4)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 34
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 35 // we need host clock, OTG/portsel clock and AHB clock
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 36 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 37
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 38 #define HCCA_SIZE sizeof(HCCA)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 39 #define ED_SIZE sizeof(HCED)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 40 #define TD_SIZE sizeof(HCTD)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 41
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 42 #define TOTAL_SIZE (HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE) + (MAX_TD*TD_SIZE))
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 43
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 44 static volatile uint8_t usb_buf[TOTAL_SIZE] __attribute((section("AHBSRAM1"),aligned(256))); //256 bytes aligned!
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 45
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 46 USBHALHost * USBHALHost::instHost;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 47
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 48 USBHALHost::USBHALHost() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 49 instHost = this;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 50 memInit();
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 51 memset((void*)usb_hcca, 0, HCCA_SIZE);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 52 for (int i = 0; i < MAX_ENDPOINT; i++) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 53 edBufAlloc[i] = false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 54 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 55 for (int i = 0; i < MAX_TD; i++) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 56 tdBufAlloc[i] = false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 57 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 58 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 59
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 60 void USBHALHost::init() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 61 NVIC_DisableIRQ(USB_IRQn);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 62
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 63 //Cut power
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 64 LPC_SC->PCONP &= ~(1UL<<31);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 65 wait_ms(100);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 66
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 67 // turn on power for USB
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 68 LPC_SC->PCONP |= (1UL<<31);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 69
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 70 // Enable USB host clock, port selection and AHB clock
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 71 LPC_USB->USBClkCtrl |= CLOCK_MASK;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 72
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 73 // Wait for clocks to become available
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 74 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 75
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 76 // it seems the bits[0:1] mean the following
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 77 // 0: U1=device, U2=host
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 78 // 1: U1=host, U2=host
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 79 // 2: reserved
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 80 // 3: U1=host, U2=device
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 81 // NB: this register is only available if OTG clock (aka "port select") is enabled!!
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 82 // since we don't care about port 2, set just bit 0 to 1 (U1=host)
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 83 LPC_USB->OTGStCtrl |= 1;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 84
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 85 // now that we've configured the ports, we can turn off the portsel clock
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 86 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 87
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 88 // configure USB D+/D- pins
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 89 // P0[29] = USB_D+, 01
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 90 // P0[30] = USB_D-, 01
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 91 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 92 LPC_PINCON->PINSEL1 |= ((1<<26) | (1<<28));
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 93
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 94 LPC_USB->HcControl = 0; // HARDWARE RESET
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 95 LPC_USB->HcControlHeadED = 0; // Initialize Control list head to Zero
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 96 LPC_USB->HcBulkHeadED = 0; // Initialize Bulk list head to Zero
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 97
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 98 // Wait 100 ms before apply reset
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 99 wait_ms(100);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 100
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 101 // software reset
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 102 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 103
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 104 // Write Fm Interval and Largest Data Packet Counter
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 105 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 106 LPC_USB->HcPeriodicStart = FI * 90 / 100;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 107
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 108 // Put HC in operational state
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 109 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 110 // Set Global Power
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 111 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 112
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 113 LPC_USB->HcHCCA = (uint32_t)(usb_hcca);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 114
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 115 // Clear Interrrupt Status
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 116 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 117
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 118 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE | OR_INTR_ENABLE_WDH | OR_INTR_ENABLE_RHSC;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 119
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 120 // Enable the USB Interrupt
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 121 NVIC_SetVector(USB_IRQn, (uint32_t)(_usbisr));
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 122 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 123 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 124
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 125 NVIC_EnableIRQ(USB_IRQn);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 126
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 127 // Check for any connected devices
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 128 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 129 //Device connected
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 130 wait_ms(150);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 131 USB_DBG("Device connected (%08x)\n\r", LPC_USB->HcRhPortStatus1);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 132 deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 133 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 134 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 135
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 136 uint32_t USBHALHost::controlHeadED() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 137 return LPC_USB->HcControlHeadED;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 138 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 139
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 140 uint32_t USBHALHost::bulkHeadED() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 141 return LPC_USB->HcBulkHeadED;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 142 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 143
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 144 uint32_t USBHALHost::interruptHeadED() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 145 return usb_hcca->IntTable[0];
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 146 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 147
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 148 void USBHALHost::updateBulkHeadED(uint32_t addr) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 149 LPC_USB->HcBulkHeadED = addr;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 150 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 151
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 152
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 153 void USBHALHost::updateControlHeadED(uint32_t addr) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 154 LPC_USB->HcControlHeadED = addr;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 155 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 156
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 157 void USBHALHost::updateInterruptHeadED(uint32_t addr) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 158 usb_hcca->IntTable[0] = addr;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 159 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 160
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 161
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 162 void USBHALHost::enableList(ENDPOINT_TYPE type) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 163 switch(type) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 164 case CONTROL_ENDPOINT:
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 165 LPC_USB->HcCommandStatus = OR_CMD_STATUS_CLF;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 166 LPC_USB->HcControl |= OR_CONTROL_CLE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 167 break;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 168 case ISOCHRONOUS_ENDPOINT:
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 169 break;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 170 case BULK_ENDPOINT:
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 171 LPC_USB->HcCommandStatus = OR_CMD_STATUS_BLF;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 172 LPC_USB->HcControl |= OR_CONTROL_BLE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 173 break;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 174 case INTERRUPT_ENDPOINT:
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 175 LPC_USB->HcControl |= OR_CONTROL_PLE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 176 break;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 177 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 178 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 179
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 180
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 181 bool USBHALHost::disableList(ENDPOINT_TYPE type) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 182 switch(type) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 183 case CONTROL_ENDPOINT:
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 184 if(LPC_USB->HcControl & OR_CONTROL_CLE) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 185 LPC_USB->HcControl &= ~OR_CONTROL_CLE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 186 return true;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 187 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 188 return false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 189 case ISOCHRONOUS_ENDPOINT:
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 190 return false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 191 case BULK_ENDPOINT:
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 192 if(LPC_USB->HcControl & OR_CONTROL_BLE){
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 193 LPC_USB->HcControl &= ~OR_CONTROL_BLE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 194 return true;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 195 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 196 return false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 197 case INTERRUPT_ENDPOINT:
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 198 if(LPC_USB->HcControl & OR_CONTROL_PLE) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 199 LPC_USB->HcControl &= ~OR_CONTROL_PLE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 200 return true;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 201 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 202 return false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 203 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 204 return false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 205 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 206
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 207
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 208 void USBHALHost::memInit() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 209 usb_hcca = (volatile HCCA *)usb_buf;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 210 usb_edBuf = usb_buf + HCCA_SIZE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 211 usb_tdBuf = usb_buf + HCCA_SIZE + (MAX_ENDPOINT*ED_SIZE);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 212 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 213
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 214 volatile uint8_t * USBHALHost::getED() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 215 for (int i = 0; i < MAX_ENDPOINT; i++) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 216 if ( !edBufAlloc[i] ) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 217 edBufAlloc[i] = true;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 218 return (volatile uint8_t *)(usb_edBuf + i*ED_SIZE);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 219 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 220 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 221 perror("Could not allocate ED\r\n");
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 222 return NULL; //Could not alloc ED
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 223 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 224
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 225 volatile uint8_t * USBHALHost::getTD() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 226 int i;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 227 for (i = 0; i < MAX_TD; i++) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 228 if ( !tdBufAlloc[i] ) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 229 tdBufAlloc[i] = true;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 230 return (volatile uint8_t *)(usb_tdBuf + i*TD_SIZE);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 231 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 232 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 233 perror("Could not allocate TD\r\n");
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 234 return NULL; //Could not alloc TD
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 235 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 236
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 237
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 238 void USBHALHost::freeED(volatile uint8_t * ed) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 239 int i;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 240 i = (ed - usb_edBuf) / ED_SIZE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 241 edBufAlloc[i] = false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 242 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 243
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 244 void USBHALHost::freeTD(volatile uint8_t * td) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 245 int i;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 246 i = (td - usb_tdBuf) / TD_SIZE;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 247 tdBufAlloc[i] = false;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 248 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 249
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 250
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 251 void USBHALHost::resetRootHub() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 252 // Initiate port reset
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 253 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 254
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 255 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 256
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 257 // ...and clear port reset signal
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 258 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 259 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 260
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 261
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 262 void USBHALHost::_usbisr(void) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 263 if (instHost) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 264 instHost->UsbIrqhandler();
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 265 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 266 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 267
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 268 void USBHALHost::UsbIrqhandler() {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 269 if( LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable ) //Is there something to actually process?
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 270 {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 271
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 272 uint32_t int_status = LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 273
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 274 // Root hub status change interrupt
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 275 if (int_status & OR_INTR_STATUS_RHSC) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 276 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CSC) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 277 if (LPC_USB->HcRhStatus & OR_RH_STATUS_DRWE) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 278 // When DRWE is on, Connect Status Change
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 279 // means a remote wakeup event.
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 280 } else {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 281
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 282 //Root device connected
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 283 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_CCS) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 284
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 285 // wait 150ms to avoid bounce
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 286 wait_ms(150);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 287
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 288 //Hub 0 (root hub), Port 1 (count starts at 1), Low or High speed
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 289 deviceConnected(0, 1, LPC_USB->HcRhPortStatus1 & OR_RH_PORT_LSDA);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 290 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 291
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 292 //Root device disconnected
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 293 else {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 294
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 295 if (!(int_status & OR_INTR_STATUS_WDH)) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 296 usb_hcca->DoneHead = 0;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 297 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 298
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 299 // wait 200ms to avoid bounce
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 300 wait_ms(200);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 301
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 302 deviceDisconnected(0, 1, NULL, usb_hcca->DoneHead & 0xFFFFFFFE);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 303
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 304 if (int_status & OR_INTR_STATUS_WDH) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 305 usb_hcca->DoneHead = 0;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 306 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 307 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 308 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 309 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 310 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 311 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 312 if (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRSC) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 313 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 314 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 315 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_RHSC;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 316 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 317
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 318 // Writeback Done Head interrupt
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 319 if (int_status & OR_INTR_STATUS_WDH) {
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 320 transferCompleted(usb_hcca->DoneHead & 0xFFFFFFFE);
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 321 LPC_USB->HcInterruptStatus = OR_INTR_STATUS_WDH;
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 322 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 323 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 324 }
frq08711@LMECWL0871.LME.ST.COM 1:ab240722d7ef 325 #endif