Simple USBHost library for Nucleo F446RE/F411RE/F401RE FRDM-KL46Z/KL25Z/F64F LPC4088/LPC1768

Dependencies:   FATFileSystem

Dependents:   F401RE-BTstack_example F401RE-USBHostMSD_HelloWorld

Fork of KL46Z-USBHost by Norimasa Okamoto

簡易USBホストライブラリです。
official-USBHostの下位互換で対応プログラムを僅かな修正で動かすことが出来ます。

Platforms

  • Nucleo F446RE
  • Nucleo F411RE
  • Nucleo F401RE
  • FRDM-K64F
  • FRDM-KL46Z
  • FRDM-KL25Z
  • LPC4088
  • LPC1768

Nucleo F446RE/F411RE/F401REのUSB接続方法

ST morphoUSB
U5V (CN10-8)VBUS (1 RED)
PA11 (CN10-14)DM  (2 WHITE)
PA12 (CN10-12)DP  (3 GREEN)
GND (CN10-20)GND (4 BLACK)

Examples

Import programF446RE-USBHostMouse_HelloWorld

USBHostMouse Hello World for ST-Nucleo-F446RE

Import programF401RE-USBHostMSD_HelloWorld

Simple USBHost MSD(USB flash drive) for Nucleo F401RE/FRDM-KL46Z test program

Import programF401RE-USBHostC270_example

Simple USBHost WebCam test program

Import programK64F_USBHostC270_example

Simple USBHost C270 example

Import programF401RE-BTstack_example

BTstack for Nucleo F401RE/FRDM-KL46Z example program

Import programUSBHostRSSI_example

Bluetooth device discovery example program.

Import programKL46Z-USBHostGPS_HelloWorld

Simple USBHost GPS Dongle Receiver for FRDM-KL46Z test program

Committer:
va009039
Date:
Sun May 01 03:18:11 2016 +0000
Revision:
23:4ab8bc835303
Parent:
18:61554f238584
add ST-Nucleo-F446RE

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 18:61554f238584 1 /* mbed USBHost Library
va009039 18:61554f238584 2 * Copyright (c) 2006-2013 ARM Limited
va009039 18:61554f238584 3 *
va009039 18:61554f238584 4 * Licensed under the Apache License, Version 2.0 (the "License");
va009039 18:61554f238584 5 * you may not use this file except in compliance with the License.
va009039 18:61554f238584 6 * You may obtain a copy of the License at
va009039 18:61554f238584 7 *
va009039 18:61554f238584 8 * http://www.apache.org/licenses/LICENSE-2.0
va009039 18:61554f238584 9 *
va009039 18:61554f238584 10 * Unless required by applicable law or agreed to in writing, software
va009039 18:61554f238584 11 * distributed under the License is distributed on an "AS IS" BASIS,
va009039 18:61554f238584 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
va009039 18:61554f238584 13 * See the License for the specific language governing permissions and
va009039 18:61554f238584 14 * limitations under the License.
va009039 18:61554f238584 15 */
va009039 18:61554f238584 16
va009039 18:61554f238584 17 #if defined(TARGET_LPC4088)||defined(TARGET_LPC1768)
va009039 18:61554f238584 18 #include "USBHALHost.h"
va009039 18:61554f238584 19
va009039 18:61554f238584 20 #ifndef CTASSERT
va009039 18:61554f238584 21 template <bool>struct CtAssert;
va009039 18:61554f238584 22 template <>struct CtAssert<true> {};
va009039 18:61554f238584 23 #define CTASSERT(A) CtAssert<A>();
va009039 18:61554f238584 24 #endif
va009039 18:61554f238584 25
va009039 18:61554f238584 26 #ifdef _USB_DBG
va009039 18:61554f238584 27 #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
va009039 18:61554f238584 28 #define USB_DBG_HEX(A,B) debug_hex(A,B)
va009039 18:61554f238584 29 #define USB_DBG_ED(A) while(0)
va009039 18:61554f238584 30 #define USB_DBG_TD(A) while(0)
va009039 18:61554f238584 31 #define USB_DBG_ED_IF(A,B) while(0)
va009039 18:61554f238584 32 void debug_hex(uint8_t* buf, int size);
va009039 18:61554f238584 33 #else
va009039 18:61554f238584 34 #define USB_DBG(...) while(0)
va009039 18:61554f238584 35 #define USB_DBG_ED(A) while(0)
va009039 18:61554f238584 36 #define USB_DBG_TD(A) while(0)
va009039 18:61554f238584 37 #define USB_DBG_ED_IF(A,B) while(0)
va009039 18:61554f238584 38 #define USB_DBG_HEX(A,B) while(0)
va009039 18:61554f238584 39 #endif
va009039 18:61554f238584 40
va009039 18:61554f238584 41 #define USB_TRACE1(A) while(0)
va009039 18:61554f238584 42
va009039 18:61554f238584 43 #ifdef _USB_TEST
va009039 18:61554f238584 44 #undef USB_TEST_ASSERT
va009039 18:61554f238584 45 void usb_test_assert_internal(const char *expr, const char *file, int line);
va009039 18:61554f238584 46 #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
va009039 18:61554f238584 47 #else
va009039 18:61554f238584 48 #define USB_TEST_ASSERT(EXPR) while(0)
va009039 18:61554f238584 49 #endif
va009039 18:61554f238584 50
va009039 18:61554f238584 51 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
va009039 18:61554f238584 52
va009039 18:61554f238584 53 // bits of the USB/OTG clock control register
va009039 18:61554f238584 54 #define HOST_CLK_EN (1<<0)
va009039 18:61554f238584 55 #define DEV_CLK_EN (1<<1)
va009039 18:61554f238584 56 #define PORTSEL_CLK_EN (1<<3)
va009039 18:61554f238584 57 #define AHB_CLK_EN (1<<4)
va009039 18:61554f238584 58
va009039 18:61554f238584 59 // bits of the USB/OTG clock status register
va009039 18:61554f238584 60 #define HOST_CLK_ON (1<<0)
va009039 18:61554f238584 61 #define DEV_CLK_ON (1<<1)
va009039 18:61554f238584 62 #define PORTSEL_CLK_ON (1<<3)
va009039 18:61554f238584 63 #define AHB_CLK_ON (1<<4)
va009039 18:61554f238584 64
va009039 18:61554f238584 65 // we need host clock, OTG/portsel clock and AHB clock
va009039 18:61554f238584 66 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
va009039 18:61554f238584 67 #define FI 0x2EDF /* 12000 bits per frame (-1) */
va009039 18:61554f238584 68 #define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI)
va009039 18:61554f238584 69
va009039 18:61554f238584 70 USBHALHost* USBHALHost::instHost;
va009039 18:61554f238584 71
va009039 18:61554f238584 72 USBHALHost::USBHALHost() {
va009039 18:61554f238584 73 instHost = this;
va009039 18:61554f238584 74 }
va009039 18:61554f238584 75
va009039 18:61554f238584 76 void USBHALHost::init() {
va009039 18:61554f238584 77 NVIC_DisableIRQ(USB_IRQn);
va009039 18:61554f238584 78 m_pHcca = new HCCA();
va009039 18:61554f238584 79 init_hw_ohci(m_pHcca);
va009039 18:61554f238584 80 ResetRootHub();
va009039 18:61554f238584 81 NVIC_SetVector(USB_IRQn, (uint32_t)_usbisr);
va009039 18:61554f238584 82 NVIC_SetPriority(USB_IRQn, 0);
va009039 18:61554f238584 83 NVIC_EnableIRQ(USB_IRQn);
va009039 18:61554f238584 84
va009039 18:61554f238584 85 USB_INFO("Simple USBHost Library for LPC4088/LPC1768");
va009039 18:61554f238584 86 bool lowSpeed = wait_attach();
va009039 18:61554f238584 87 addDevice(NULL, 0, lowSpeed);
va009039 18:61554f238584 88 }
va009039 18:61554f238584 89
va009039 18:61554f238584 90 void USBHALHost::init_hw_ohci(HCCA* pHcca) {
va009039 18:61554f238584 91 LPC_SC->PCONP &= ~(1UL<<31); //Cut power
va009039 18:61554f238584 92 wait_ms(1000);
va009039 18:61554f238584 93 LPC_SC->PCONP |= (1UL<<31); // turn on power for USB
va009039 18:61554f238584 94 LPC_USB->USBClkCtrl |= CLOCK_MASK; // Enable USB host clock, port selection and AHB clock
va009039 18:61554f238584 95 // Wait for clocks to become available
va009039 18:61554f238584 96 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
va009039 18:61554f238584 97 ;
va009039 18:61554f238584 98 LPC_USB->OTGStCtrl |= 1;
va009039 18:61554f238584 99 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
va009039 18:61554f238584 100
va009039 18:61554f238584 101 #if defined(TARGET_LPC1768)
va009039 18:61554f238584 102 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
va009039 18:61554f238584 103 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000
va009039 18:61554f238584 104 #elif defined(TARGET_LPC4088)
va009039 18:61554f238584 105 LPC_IOCON->P0_29 = 0x01; // USB_D+1
va009039 18:61554f238584 106 LPC_IOCON->P0_30 = 0x01; // USB_D-1
va009039 18:61554f238584 107 // DO NOT CHANGE P1_19.
va009039 18:61554f238584 108 #else
va009039 18:61554f238584 109 #error "target error"
va009039 18:61554f238584 110 #endif
va009039 18:61554f238584 111 USB_DBG("initialize OHCI\n");
va009039 18:61554f238584 112 wait_ms(100); /* Wait 50 ms before apply reset */
va009039 18:61554f238584 113 USB_TEST_ASSERT((LPC_USB->HcRevision&0xff) == 0x10); // check revision
va009039 18:61554f238584 114 LPC_USB->HcControl = 0; /* HARDWARE RESET */
va009039 18:61554f238584 115 LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */
va009039 18:61554f238584 116 LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */
va009039 18:61554f238584 117 /* SOFTWARE RESET */
va009039 18:61554f238584 118 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
va009039 18:61554f238584 119 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */
va009039 18:61554f238584 120 LPC_USB->HcPeriodicStart = FI*90/100;
va009039 18:61554f238584 121 /* Put HC in operational state */
va009039 18:61554f238584 122 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
va009039 18:61554f238584 123 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */
va009039 18:61554f238584 124 USB_TEST_ASSERT(pHcca);
va009039 18:61554f238584 125 for (int i = 0; i < 32; i++) {
va009039 18:61554f238584 126 pHcca->InterruptTable[i] = NULL;
va009039 18:61554f238584 127 }
va009039 18:61554f238584 128 LPC_USB->HcHCCA = reinterpret_cast<uint32_t>(pHcca);
va009039 18:61554f238584 129 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
va009039 18:61554f238584 130 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO;
va009039 18:61554f238584 131
va009039 18:61554f238584 132 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
va009039 18:61554f238584 133 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
va009039 18:61554f238584 134 }
va009039 18:61554f238584 135
va009039 18:61554f238584 136 void USBHALHost::ResetRootHub() {
va009039 18:61554f238584 137 wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */
va009039 18:61554f238584 138 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
va009039 18:61554f238584 139 USB_DBG("Before loop\n");
va009039 18:61554f238584 140 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
va009039 18:61554f238584 141 ;
va009039 18:61554f238584 142 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
va009039 18:61554f238584 143 USB_DBG("After loop\n");
va009039 18:61554f238584 144 wait_ms(200); /* Wait for 100 MS after port reset */
va009039 18:61554f238584 145 }
va009039 18:61554f238584 146
va009039 18:61554f238584 147 bool USBHALHost::wait_attach() {
va009039 18:61554f238584 148 bool lowSpeed = false;
va009039 18:61554f238584 149 uint32_t status = LPC_USB->HcRhPortStatus1;
va009039 18:61554f238584 150 if (status & OR_RH_PORT_LSDA) { // lowSpeedDeviceAttached
va009039 18:61554f238584 151 lowSpeed = true;
va009039 18:61554f238584 152 }
va009039 18:61554f238584 153 return lowSpeed;
va009039 18:61554f238584 154 }
va009039 18:61554f238584 155
va009039 18:61554f238584 156 void enable(ENDPOINT_TYPE type) {
va009039 18:61554f238584 157 switch(type) {
va009039 18:61554f238584 158 case CONTROL_ENDPOINT:
va009039 18:61554f238584 159 LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
va009039 18:61554f238584 160 LPC_USB->HcControl |= OR_CONTROL_CLE;
va009039 18:61554f238584 161 break;
va009039 18:61554f238584 162 case ISOCHRONOUS_ENDPOINT:
va009039 18:61554f238584 163 LPC_USB->HcControl |= OR_CONTROL_PLE;
va009039 18:61554f238584 164 break;
va009039 18:61554f238584 165 case BULK_ENDPOINT:
va009039 18:61554f238584 166 LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF;
va009039 18:61554f238584 167 LPC_USB->HcControl |= OR_CONTROL_BLE;
va009039 18:61554f238584 168 break;
va009039 18:61554f238584 169 case INTERRUPT_ENDPOINT:
va009039 18:61554f238584 170 LPC_USB->HcControl |= OR_CONTROL_PLE;
va009039 18:61554f238584 171 break;
va009039 18:61554f238584 172 }
va009039 18:61554f238584 173 }
va009039 18:61554f238584 174
va009039 18:61554f238584 175 void USBHALHost::token_init(USBEndpoint* ep) {
va009039 18:61554f238584 176 HCED* ed = ep->getHALData<HCED*>();
va009039 18:61554f238584 177 if (ed == NULL) {
va009039 18:61554f238584 178 ed = new HCED(ep);
va009039 18:61554f238584 179 ep->setHALData<HCED*>(ed);
va009039 18:61554f238584 180 }
va009039 18:61554f238584 181 USBDeviceConnected* dev = ep->getDevice();
va009039 18:61554f238584 182 USB_TEST_ASSERT(dev);
va009039 18:61554f238584 183 if (dev) {
va009039 18:61554f238584 184 uint8_t devAddr = dev->getAddress();
va009039 18:61554f238584 185 USB_DBG("devAddr=%02x", devAddr);
va009039 18:61554f238584 186 ed->setFunctionAddress(devAddr);
va009039 18:61554f238584 187 }
va009039 18:61554f238584 188 uint16_t size = ep->getSize();
va009039 18:61554f238584 189 USB_DBG("MaxPacketSize=%d", size);
va009039 18:61554f238584 190 ed->setMaxPacketSize(size);
va009039 18:61554f238584 191 if (ed->HeadTd == NULL) {
va009039 18:61554f238584 192 HCTD* td = new HCTD(ed);
va009039 18:61554f238584 193 ed->TailTd = td;
va009039 18:61554f238584 194 ed->HeadTd = td;
va009039 18:61554f238584 195 switch(ep->getType()) {
va009039 18:61554f238584 196 case CONTROL_ENDPOINT:
va009039 18:61554f238584 197 ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED);
va009039 18:61554f238584 198 LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(ed);
va009039 18:61554f238584 199 break;
va009039 18:61554f238584 200 case BULK_ENDPOINT:
va009039 18:61554f238584 201 ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcBulkHeadED);
va009039 18:61554f238584 202 LPC_USB->HcBulkHeadED = reinterpret_cast<uint32_t>(ed);
va009039 18:61554f238584 203 break;
va009039 18:61554f238584 204 case INTERRUPT_ENDPOINT:
va009039 18:61554f238584 205 HCCA* pHcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
va009039 18:61554f238584 206 ed->Next = pHcca->InterruptTable[0];
va009039 18:61554f238584 207 pHcca->InterruptTable[0] = ed;
va009039 18:61554f238584 208 break;
va009039 18:61554f238584 209 }
va009039 18:61554f238584 210 }
va009039 18:61554f238584 211 }
va009039 18:61554f238584 212
va009039 18:61554f238584 213 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
va009039 18:61554f238584 214 token_init(ep);
va009039 18:61554f238584 215 HCED* ed = ep->getHALData<HCED*>();
va009039 18:61554f238584 216 HCTD* td = ed->TailTd;
va009039 18:61554f238584 217 setup->wLength = wLength;
va009039 18:61554f238584 218 TBUF* tbuf = new(sizeof(SETUP_PACKET))TBUF(setup, sizeof(SETUP_PACKET));
va009039 18:61554f238584 219 td->transfer(tbuf, sizeof(SETUP_PACKET));
va009039 18:61554f238584 220 td->Control |= TD_TOGGLE_0|TD_SETUP; // DATA0
va009039 18:61554f238584 221 HCTD* blank = new HCTD(ed);
va009039 18:61554f238584 222 ed->enqueue(blank);
va009039 18:61554f238584 223 //DBG_ED(ed);
va009039 18:61554f238584 224 enable(ep->getType());
va009039 18:61554f238584 225
va009039 18:61554f238584 226 td = ed->get_queue_HCTD();
va009039 18:61554f238584 227 USB_TEST_ASSERT(td);
va009039 18:61554f238584 228 int result = td->getLengthTransferred();
va009039 18:61554f238584 229 USB_DBG_TD(td);
va009039 18:61554f238584 230 delete tbuf;
va009039 18:61554f238584 231 delete td;
va009039 18:61554f238584 232 return result;
va009039 18:61554f238584 233 }
va009039 18:61554f238584 234
va009039 18:61554f238584 235 static HCED* getHCED_iso(USBEndpoint* ep) {
va009039 18:61554f238584 236 HCED* ed = ep->getHALData<HCED*>();
va009039 18:61554f238584 237 if (ed != NULL) {
va009039 18:61554f238584 238 return ed;
va009039 18:61554f238584 239 }
va009039 18:61554f238584 240 ed = new HCED(ep);
va009039 18:61554f238584 241 ep->setHALData<HCED*>(ed);
va009039 18:61554f238584 242 ed->setFormat(); // F Format ITD
va009039 18:61554f238584 243 ed->iso.FrameCount = ep->ohci.frameCount;
va009039 18:61554f238584 244 ed->iso.queue_limit = ep->ohci.queueLimit;
va009039 18:61554f238584 245 ed->iso.queue_count = 0;
va009039 18:61554f238584 246 ed->iso.Current_FrameCount = 0;
va009039 18:61554f238584 247 ed->iso.Current_itd = NULL;
va009039 18:61554f238584 248 ed->iso.FrameNumber = LPC_USB->HcFmNumber + 10; // after 10msec
va009039 18:61554f238584 249 HCITD* itd = ed->new_HCITD();
va009039 18:61554f238584 250 ed->init_queue(reinterpret_cast<HCTD*>(itd));
va009039 18:61554f238584 251 HCCA* hcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
va009039 18:61554f238584 252 hcca->enqueue(ed);
va009039 18:61554f238584 253 LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable
va009039 18:61554f238584 254 LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable
va009039 18:61554f238584 255 return ed;
va009039 18:61554f238584 256 }
va009039 18:61554f238584 257
va009039 18:61554f238584 258 static void enablePeriodic() {
va009039 18:61554f238584 259 LPC_USB->HcControl |= OR_CONTROL_PLE;
va009039 18:61554f238584 260 }
va009039 18:61554f238584 261
va009039 18:61554f238584 262 HCITD* isochronousReceive(USBEndpoint* ep) {
va009039 18:61554f238584 263 HCED* ed = getHCED_iso(ep);
va009039 18:61554f238584 264 USB_TEST_ASSERT(ed);
va009039 18:61554f238584 265 while(ed->iso.queue_count < ed->iso.queue_limit) {
va009039 18:61554f238584 266 HCITD* blank_itd = ed->new_HCITD();
va009039 18:61554f238584 267 if (ed->enqueue(reinterpret_cast<HCTD*>(blank_itd))) {
va009039 18:61554f238584 268 ed->iso.queue_count++;
va009039 18:61554f238584 269 }
va009039 18:61554f238584 270 enablePeriodic();
va009039 18:61554f238584 271 }
va009039 18:61554f238584 272
va009039 18:61554f238584 273 HCITD* itd = ed->get_queue_HCITD();
va009039 18:61554f238584 274 if (itd) {
va009039 18:61554f238584 275 ed->iso.queue_count--;
va009039 18:61554f238584 276 }
va009039 18:61554f238584 277 return itd;
va009039 18:61554f238584 278 }
va009039 18:61554f238584 279
va009039 18:61554f238584 280 int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
va009039 18:61554f238584 281 HCED* ed = getHCED_iso(ep);
va009039 18:61554f238584 282 if (ed->iso.Current_FrameCount == 0) {
va009039 18:61554f238584 283 HCITD* itd = isochronousReceive(ep);
va009039 18:61554f238584 284 if (itd == NULL) {
va009039 18:61554f238584 285 return -1;
va009039 18:61554f238584 286 }
va009039 18:61554f238584 287 if (itd->ConditionCode() != 0) {
va009039 18:61554f238584 288 delete itd;
va009039 18:61554f238584 289 return -1;
va009039 18:61554f238584 290 }
va009039 18:61554f238584 291 ed->iso.Current_itd = itd;
va009039 18:61554f238584 292 }
va009039 18:61554f238584 293
va009039 18:61554f238584 294 HCITD* itd = ed->iso.Current_itd;
va009039 18:61554f238584 295 int fc = ed->iso.Current_FrameCount;
va009039 18:61554f238584 296 int result = -1;
va009039 18:61554f238584 297 uint8_t cc = itd->ConditionCode(fc);
va009039 18:61554f238584 298 if (cc == 0 || cc == 9) {
va009039 18:61554f238584 299 result = itd->Length(fc);
va009039 18:61554f238584 300 memcpy(data, itd->Buffer(fc), result);
va009039 18:61554f238584 301 }
va009039 18:61554f238584 302
va009039 18:61554f238584 303 if (++ed->iso.Current_FrameCount >= itd->FrameCount()) {
va009039 18:61554f238584 304 ed->iso.Current_FrameCount = 0;
va009039 18:61554f238584 305 delete ed->iso.Current_itd;
va009039 18:61554f238584 306 }
va009039 18:61554f238584 307 return result;
va009039 18:61554f238584 308 }
va009039 18:61554f238584 309
va009039 18:61554f238584 310 int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, int size) {
va009039 18:61554f238584 311 token_init(ep);
va009039 18:61554f238584 312 HCED* ed = ep->getHALData<HCED*>();
va009039 18:61554f238584 313 HCTD* td = ed->TailTd;
va009039 18:61554f238584 314 TBUF* tbuf = NULL;
va009039 18:61554f238584 315 if (data != NULL) {
va009039 18:61554f238584 316 tbuf = new(size)TBUF();
va009039 18:61554f238584 317 td->transfer(tbuf, size);
va009039 18:61554f238584 318 }
va009039 18:61554f238584 319 td->Control |= TD_IN;
va009039 18:61554f238584 320 HCTD* blank = new HCTD(ed);
va009039 18:61554f238584 321 ed->enqueue(blank);
va009039 18:61554f238584 322 USB_DBG_ED_IF(ed->EndpointNumber()==0, ed); // control transfer
va009039 18:61554f238584 323 enable(ep->getType());
va009039 18:61554f238584 324
va009039 18:61554f238584 325 td = ed->get_queue_HCTD();
va009039 18:61554f238584 326 USB_TEST_ASSERT(td);
va009039 18:61554f238584 327 if (data != NULL) {
va009039 18:61554f238584 328 memcpy(data, tbuf->buf, size);
va009039 18:61554f238584 329 delete tbuf;
va009039 18:61554f238584 330 }
va009039 18:61554f238584 331 int result = td->getLengthTransferred();
va009039 18:61554f238584 332 delete td;
va009039 18:61554f238584 333 return result;
va009039 18:61554f238584 334 }
va009039 18:61554f238584 335
va009039 18:61554f238584 336 int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, int size) {
va009039 18:61554f238584 337 token_init(ep);
va009039 18:61554f238584 338 HCED* ed = ep->getHALData<HCED*>();
va009039 18:61554f238584 339 HCTD* td = ed->TailTd;
va009039 18:61554f238584 340 TBUF* tbuf = NULL;
va009039 18:61554f238584 341 if (data != NULL) {
va009039 18:61554f238584 342 tbuf = new(size)TBUF(data, size);
va009039 18:61554f238584 343 td->transfer(tbuf, size);
va009039 18:61554f238584 344 }
va009039 18:61554f238584 345 td->Control |= TD_OUT;
va009039 18:61554f238584 346 HCTD* blank = new HCTD(ed);
va009039 18:61554f238584 347 ed->enqueue(blank);
va009039 18:61554f238584 348 USB_DBG_ED(ed);
va009039 18:61554f238584 349 enable(ep->getType());
va009039 18:61554f238584 350
va009039 18:61554f238584 351 td = ed->get_queue_HCTD();
va009039 18:61554f238584 352 USB_TEST_ASSERT(td);
va009039 18:61554f238584 353 if (data != NULL) {
va009039 18:61554f238584 354 delete tbuf;
va009039 18:61554f238584 355 }
va009039 18:61554f238584 356 int result = td->getLengthTransferred();
va009039 18:61554f238584 357 delete td;
va009039 18:61554f238584 358 return result;
va009039 18:61554f238584 359 }
va009039 18:61554f238584 360
va009039 18:61554f238584 361 void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
va009039 18:61554f238584 362 token_init(ep);
va009039 18:61554f238584 363 HCED* ed = ep->getHALData<HCED*>();
va009039 18:61554f238584 364 HCTD* td = ed->TailTd;
va009039 18:61554f238584 365 TBUF* tbuf = new(size)TBUF();
va009039 18:61554f238584 366 td->transfer(tbuf, size);
va009039 18:61554f238584 367 td->Control |= TD_IN;
va009039 18:61554f238584 368 HCTD* blank = new HCTD(ed);
va009039 18:61554f238584 369 ed->enqueue(blank);
va009039 18:61554f238584 370 enable(ep->getType());
va009039 18:61554f238584 371 }
va009039 18:61554f238584 372
va009039 18:61554f238584 373 USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) {
va009039 18:61554f238584 374 HCED* ed = ep->getHALData<HCED*>();
va009039 18:61554f238584 375 if (ed == NULL) {
va009039 18:61554f238584 376 return USB_TYPE_ERROR;
va009039 18:61554f238584 377 }
va009039 18:61554f238584 378 HCTD* td = ed->get_queue_HCTD(0);
va009039 18:61554f238584 379 if (td) {
va009039 18:61554f238584 380 int len = td->getLengthTransferred();
va009039 18:61554f238584 381 TBUF* tbuf = (TBUF*)td->buf_top;
va009039 18:61554f238584 382 memcpy(ep->getBufStart(), tbuf->buf, len);
va009039 18:61554f238584 383 ep->setLengthTransferred(len);
va009039 18:61554f238584 384 ep->setState((USB_TYPE)td->ConditionCode());
va009039 18:61554f238584 385 delete td;
va009039 18:61554f238584 386 delete tbuf;
va009039 18:61554f238584 387 return USB_TYPE_OK;
va009039 18:61554f238584 388 }
va009039 18:61554f238584 389 return USB_TYPE_PROCESSING;
va009039 18:61554f238584 390 }
va009039 18:61554f238584 391
va009039 18:61554f238584 392 void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) {
va009039 18:61554f238584 393 USB_TEST_ASSERT(toggle == 1);
va009039 18:61554f238584 394 HCED* ed = ep->getHALData<HCED*>();
va009039 18:61554f238584 395 ed->setToggle(toggle);
va009039 18:61554f238584 396 }
va009039 18:61554f238584 397
va009039 18:61554f238584 398 void USBHALHost::_usbisr(void) {
va009039 18:61554f238584 399 if (instHost) {
va009039 18:61554f238584 400 instHost->UsbIrqhandler();
va009039 18:61554f238584 401 }
va009039 18:61554f238584 402 }
va009039 18:61554f238584 403
va009039 18:61554f238584 404 HCTD* td_reverse(HCTD* td)
va009039 18:61554f238584 405 {
va009039 18:61554f238584 406 HCTD* result = NULL;
va009039 18:61554f238584 407 HCTD* next;
va009039 18:61554f238584 408 while(td) {
va009039 18:61554f238584 409 next = const_cast<HCTD*>(td->Next);
va009039 18:61554f238584 410 td->Next = result;
va009039 18:61554f238584 411 result = td;
va009039 18:61554f238584 412 td = next;
va009039 18:61554f238584 413 }
va009039 18:61554f238584 414 return result;
va009039 18:61554f238584 415 }
va009039 18:61554f238584 416
va009039 18:61554f238584 417 void USBHALHost::UsbIrqhandler() {
va009039 18:61554f238584 418 if (!(LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable)) {
va009039 18:61554f238584 419 return;
va009039 18:61554f238584 420 }
va009039 18:61554f238584 421 m_report_irq++;
va009039 18:61554f238584 422 uint32_t status = LPC_USB->HcInterruptStatus;
va009039 18:61554f238584 423 if (status & OR_INTR_STATUS_FNO) {
va009039 18:61554f238584 424 m_report_FNO++;
va009039 18:61554f238584 425 }
va009039 18:61554f238584 426 if (status & OR_INTR_STATUS_WDH) {
va009039 18:61554f238584 427 union {
va009039 18:61554f238584 428 HCTD* done_td;
va009039 18:61554f238584 429 uint32_t lsb;
va009039 18:61554f238584 430 };
va009039 18:61554f238584 431 done_td = const_cast<HCTD*>(m_pHcca->DoneHead);
va009039 18:61554f238584 432 USB_TEST_ASSERT(done_td);
va009039 18:61554f238584 433 m_pHcca->DoneHead = NULL; // reset
va009039 18:61554f238584 434 if (lsb & 1) { // error ?
va009039 18:61554f238584 435 lsb &= ~1;
va009039 18:61554f238584 436 }
va009039 18:61554f238584 437 HCTD* td = td_reverse(done_td);
va009039 18:61554f238584 438 while(td) {
va009039 18:61554f238584 439 HCED* ed = td->parent;
va009039 18:61554f238584 440 USB_TEST_ASSERT(ed);
va009039 18:61554f238584 441 if (ed) {
va009039 18:61554f238584 442 ed->irqWdhHandler(td);
va009039 18:61554f238584 443 }
va009039 18:61554f238584 444 td = td->Next;
va009039 18:61554f238584 445 }
va009039 18:61554f238584 446 m_report_WDH++;
va009039 18:61554f238584 447 }
va009039 18:61554f238584 448 LPC_USB->HcInterruptStatus = status; // Clear Interrrupt Status
va009039 18:61554f238584 449 }
va009039 18:61554f238584 450
va009039 18:61554f238584 451 TBUF::TBUF(const void* data, int size) {
va009039 18:61554f238584 452 if (size > 0) {
va009039 18:61554f238584 453 memcpy(buf, data, size);
va009039 18:61554f238584 454 }
va009039 18:61554f238584 455 }
va009039 18:61554f238584 456
va009039 18:61554f238584 457 HCTD::HCTD(HCED* obj) {
va009039 18:61554f238584 458 CTASSERT(sizeof(HCTD) == 36);
va009039 18:61554f238584 459 USB_TEST_ASSERT(obj);
va009039 18:61554f238584 460 Control = TD_CC|TD_ROUNDING;
va009039 18:61554f238584 461 CurrBufPtr = NULL;
va009039 18:61554f238584 462 Next = NULL;
va009039 18:61554f238584 463 BufEnd = NULL;
va009039 18:61554f238584 464 buf_top = NULL;
va009039 18:61554f238584 465 buf_size = 0;
va009039 18:61554f238584 466 parent = obj;
va009039 18:61554f238584 467 }
va009039 18:61554f238584 468
va009039 18:61554f238584 469 HCITD::HCITD(HCED* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
va009039 18:61554f238584 470 Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED
va009039 18:61554f238584 471 ((FrameCount-1) << 24)| // FC FrameCount
va009039 18:61554f238584 472 TD_DELAY_INT(0) | // DI DelayInterrupt
va009039 18:61554f238584 473 FrameNumber; // SF StartingFrame
va009039 18:61554f238584 474 BufferPage0 = const_cast<uint8_t*>(buf);
va009039 18:61554f238584 475 BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
va009039 18:61554f238584 476 Next = NULL;
va009039 18:61554f238584 477 parent = obj;
va009039 18:61554f238584 478 uint32_t addr = reinterpret_cast<uint32_t>(buf);
va009039 18:61554f238584 479 for(int i = 0; i < FrameCount; i++) {
va009039 18:61554f238584 480 uint16_t offset = addr & 0x0fff;
va009039 18:61554f238584 481 if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
va009039 18:61554f238584 482 offset |= 0x1000;
va009039 18:61554f238584 483 }
va009039 18:61554f238584 484 OffsetPSW[i] = 0xe000|offset;
va009039 18:61554f238584 485 addr += PacketSize;
va009039 18:61554f238584 486 }
va009039 18:61554f238584 487 }
va009039 18:61554f238584 488
va009039 18:61554f238584 489 uint8_t* HCITD::Buffer(int fc) {
va009039 18:61554f238584 490 int offset = fc * parent->getMaxPacketSize();
va009039 18:61554f238584 491 return const_cast<uint8_t*>(buf) + offset;
va009039 18:61554f238584 492 }
va009039 18:61554f238584 493
va009039 18:61554f238584 494 HCED::HCED(USBEndpoint* ep) {
va009039 18:61554f238584 495 CTASSERT(sizeof(HCED) <= (64*2));
va009039 18:61554f238584 496 USBDeviceConnected* dev = ep->getDevice();
va009039 18:61554f238584 497 int devAddr = 0;
va009039 18:61554f238584 498 bool lowSpeed = false;
va009039 18:61554f238584 499 if (dev) {
va009039 18:61554f238584 500 devAddr = dev->getAddress();
va009039 18:61554f238584 501 lowSpeed = dev->getSpeed();
va009039 18:61554f238584 502 }
va009039 18:61554f238584 503 int ep_number = ep->getAddress();
va009039 18:61554f238584 504 int MaxPacketSize = ep->getSize();
va009039 18:61554f238584 505 Control = devAddr | /* USB address */
va009039 18:61554f238584 506 ((ep_number & 0x7F) << 7) | /* Endpoint address */
va009039 18:61554f238584 507 (ep_number!=0?(((ep_number&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
va009039 18:61554f238584 508 ((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */
va009039 18:61554f238584 509 (MaxPacketSize << 16); /* MaxPkt Size */
va009039 18:61554f238584 510 TailTd = NULL;
va009039 18:61554f238584 511 HeadTd = NULL;
va009039 18:61554f238584 512 Next = NULL;
va009039 18:61554f238584 513 }
va009039 18:61554f238584 514
va009039 18:61554f238584 515 bool HCED::enqueue(HCTD* td) {
va009039 18:61554f238584 516 if (td) {
va009039 18:61554f238584 517 HCTD* tail = reinterpret_cast<HCTD*>(TailTd);
va009039 18:61554f238584 518 if (tail) {
va009039 18:61554f238584 519 tail->Next = td;
va009039 18:61554f238584 520 TailTd = reinterpret_cast<HCTD*>(td);
va009039 18:61554f238584 521 return true;
va009039 18:61554f238584 522 }
va009039 18:61554f238584 523 }
va009039 18:61554f238584 524 return false;
va009039 18:61554f238584 525 }
va009039 18:61554f238584 526
va009039 18:61554f238584 527 void HCED::init_queue(HCTD* td) {
va009039 18:61554f238584 528 TailTd = reinterpret_cast<HCTD*>(td);
va009039 18:61554f238584 529 HeadTd = reinterpret_cast<HCTD*>(td);
va009039 18:61554f238584 530 }
va009039 18:61554f238584 531
va009039 18:61554f238584 532 void HCED::setToggle(uint8_t toggle) {
va009039 18:61554f238584 533 uint32_t c = reinterpret_cast<uint32_t>(HeadTd);
va009039 18:61554f238584 534 if (toggle == 0) { // DATA0
va009039 18:61554f238584 535 c &= ~0x02;
va009039 18:61554f238584 536 } else { // DATA1
va009039 18:61554f238584 537 c |= 0x02;
va009039 18:61554f238584 538 }
va009039 18:61554f238584 539 HeadTd = reinterpret_cast<HCTD*>(c);
va009039 18:61554f238584 540 }
va009039 18:61554f238584 541
va009039 18:61554f238584 542 uint8_t HCED::getToggle() {
va009039 18:61554f238584 543 uint32_t c = reinterpret_cast<uint32_t>(HeadTd);
va009039 18:61554f238584 544 return (c&0x02) ? 1 : 0;
va009039 18:61554f238584 545 }
va009039 18:61554f238584 546
va009039 18:61554f238584 547 HCTD* HCED::get_queue_HCTD(uint32_t millisec)
va009039 18:61554f238584 548 {
va009039 18:61554f238584 549 for(int i = 0; i < 16; i++) {
va009039 18:61554f238584 550 osEvent evt = done_queue_get(millisec);
va009039 18:61554f238584 551 if (evt.status == osEventMessage) {
va009039 18:61554f238584 552 HCTD* td = reinterpret_cast<HCTD*>(evt.value.p);
va009039 18:61554f238584 553 USB_TEST_ASSERT(td);
va009039 18:61554f238584 554 uint8_t cc = td->ConditionCode();
va009039 18:61554f238584 555 if (cc != 0) {
va009039 18:61554f238584 556 m_ConditionCode = cc;
va009039 18:61554f238584 557 USB_DBG_TD(td);
va009039 18:61554f238584 558 }
va009039 18:61554f238584 559 return td;
va009039 18:61554f238584 560 } else if (evt.status == osOK) {
va009039 18:61554f238584 561 continue;
va009039 18:61554f238584 562 } else if (evt.status == osEventTimeout) {
va009039 18:61554f238584 563 return NULL;
va009039 18:61554f238584 564 } else {
va009039 18:61554f238584 565 USB_DBG("evt.status: %02x\n", evt.status);
va009039 18:61554f238584 566 USB_TEST_ASSERT(evt.status == osEventMessage);
va009039 18:61554f238584 567 }
va009039 18:61554f238584 568 }
va009039 18:61554f238584 569 return NULL;
va009039 18:61554f238584 570 }
va009039 18:61554f238584 571
va009039 18:61554f238584 572 HCITD* HCED::get_queue_HCITD() {
va009039 18:61554f238584 573 osEvent evt = done_queue_get(0);
va009039 18:61554f238584 574 if (evt.status == osEventMessage) {
va009039 18:61554f238584 575 HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
va009039 18:61554f238584 576 USB_TEST_ASSERT(itd);
va009039 18:61554f238584 577 return itd;
va009039 18:61554f238584 578 }
va009039 18:61554f238584 579 return NULL;
va009039 18:61554f238584 580 }
va009039 18:61554f238584 581 HCITD* HCED::new_HCITD() {
va009039 18:61554f238584 582 uint16_t mps = getMaxPacketSize();
va009039 18:61554f238584 583 int total_size = mps * iso.FrameCount;
va009039 18:61554f238584 584 HCITD* itd = new(total_size)HCITD(this, iso.FrameNumber, iso.FrameCount, mps);
va009039 18:61554f238584 585 iso.FrameNumber += iso.FrameCount;
va009039 18:61554f238584 586 return itd;
va009039 18:61554f238584 587 }
va009039 18:61554f238584 588
va009039 18:61554f238584 589 void HCCA::enqueue(HCED* ed) {
va009039 18:61554f238584 590 for(int i = 0; i < 32; i++) {
va009039 18:61554f238584 591 if (InterruptTable[i] == NULL) {
va009039 18:61554f238584 592 InterruptTable[i] = ed;
va009039 18:61554f238584 593 } else {
va009039 18:61554f238584 594 HCED* nextEd = InterruptTable[i];
va009039 18:61554f238584 595 while(nextEd->Next && nextEd->Next != ed) {
va009039 18:61554f238584 596 nextEd = nextEd->Next;
va009039 18:61554f238584 597 }
va009039 18:61554f238584 598 nextEd->Next = ed;
va009039 18:61554f238584 599 }
va009039 18:61554f238584 600 }
va009039 18:61554f238584 601 }
va009039 18:61554f238584 602
va009039 18:61554f238584 603 #endif // defined(TARGET_LPC4088)||defined(TARGET_LPC1768)
va009039 18:61554f238584 604