Simple USBHost WebCam for EA LPC4088 QSB/LPC1768 test program

Dependencies:   LPC4088-USBHost mbed

EA LPC4088 QSB/LPC1768をUSBホストにしてWebカメラからJPEG画像を読み取るテストプログラムです。

The usage is the same as KL46Z-USBHostC270_example.
使い方はKL46Z-USBHostC270_exampleと同じです。
動作確認: Logitech C270,Logitech Q200R(Qcam Orbit AF)
/media/uploads/va009039/lpc4088-c270-480x360.jpg

Committer:
va009039
Date:
Thu Apr 24 05:38:45 2014 +0000
Revision:
0:c972ee42b455
first commit,sync rev.29.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:c972ee42b455 1 /* mbed USBHost Library
va009039 0:c972ee42b455 2 * Copyright (c) 2006-2013 ARM Limited
va009039 0:c972ee42b455 3 *
va009039 0:c972ee42b455 4 * Licensed under the Apache License, Version 2.0 (the "License");
va009039 0:c972ee42b455 5 * you may not use this file except in compliance with the License.
va009039 0:c972ee42b455 6 * You may obtain a copy of the License at
va009039 0:c972ee42b455 7 *
va009039 0:c972ee42b455 8 * http://www.apache.org/licenses/LICENSE-2.0
va009039 0:c972ee42b455 9 *
va009039 0:c972ee42b455 10 * Unless required by applicable law or agreed to in writing, software
va009039 0:c972ee42b455 11 * distributed under the License is distributed on an "AS IS" BASIS,
va009039 0:c972ee42b455 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
va009039 0:c972ee42b455 13 * See the License for the specific language governing permissions and
va009039 0:c972ee42b455 14 * limitations under the License.
va009039 0:c972ee42b455 15 */
va009039 0:c972ee42b455 16
va009039 0:c972ee42b455 17 #include "USBHALHost.h"
va009039 0:c972ee42b455 18 //#define _USB_DBG
va009039 0:c972ee42b455 19 #include "BaseUsbHostDebug.h"
va009039 0:c972ee42b455 20 #include "BaseUsbHostTest.h"
va009039 0:c972ee42b455 21
va009039 0:c972ee42b455 22 #ifndef CTASSERT
va009039 0:c972ee42b455 23 template <bool>struct CtAssert;
va009039 0:c972ee42b455 24 template <>struct CtAssert<true> {};
va009039 0:c972ee42b455 25 #define CTASSERT(A) CtAssert<A>();
va009039 0:c972ee42b455 26 #endif
va009039 0:c972ee42b455 27
va009039 0:c972ee42b455 28 #ifdef _USB_DBG
va009039 0:c972ee42b455 29 #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
va009039 0:c972ee42b455 30 #define USB_DBG_HEX(A,B) debug_hex(A,B)
va009039 0:c972ee42b455 31 void debug_hex(uint8_t* buf, int size);
va009039 0:c972ee42b455 32 #else
va009039 0:c972ee42b455 33 #define USB_DBG(...) while(0)
va009039 0:c972ee42b455 34 #define USB_DBG_HEX(A,B) while(0)
va009039 0:c972ee42b455 35 #endif
va009039 0:c972ee42b455 36
va009039 0:c972ee42b455 37 #ifdef _USB_TEST
va009039 0:c972ee42b455 38 #define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
va009039 0:c972ee42b455 39 #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
va009039 0:c972ee42b455 40 #else
va009039 0:c972ee42b455 41 #define USB_TEST_ASSERT(A) while(0)
va009039 0:c972ee42b455 42 #define USB_TEST_ASSERT_FALSE(A) while(0)
va009039 0:c972ee42b455 43 #endif
va009039 0:c972ee42b455 44
va009039 0:c972ee42b455 45 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
va009039 0:c972ee42b455 46
va009039 0:c972ee42b455 47 // bits of the USB/OTG clock control register
va009039 0:c972ee42b455 48 #define HOST_CLK_EN (1<<0)
va009039 0:c972ee42b455 49 #define DEV_CLK_EN (1<<1)
va009039 0:c972ee42b455 50 #define PORTSEL_CLK_EN (1<<3)
va009039 0:c972ee42b455 51 #define AHB_CLK_EN (1<<4)
va009039 0:c972ee42b455 52
va009039 0:c972ee42b455 53 // bits of the USB/OTG clock status register
va009039 0:c972ee42b455 54 #define HOST_CLK_ON (1<<0)
va009039 0:c972ee42b455 55 #define DEV_CLK_ON (1<<1)
va009039 0:c972ee42b455 56 #define PORTSEL_CLK_ON (1<<3)
va009039 0:c972ee42b455 57 #define AHB_CLK_ON (1<<4)
va009039 0:c972ee42b455 58
va009039 0:c972ee42b455 59 // we need host clock, OTG/portsel clock and AHB clock
va009039 0:c972ee42b455 60 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
va009039 0:c972ee42b455 61 #define FI 0x2EDF /* 12000 bits per frame (-1) */
va009039 0:c972ee42b455 62 #define DEFAULT_FMINTERVAL ((((6 * (FI - 210)) / 7) << 16) | FI)
va009039 0:c972ee42b455 63
va009039 0:c972ee42b455 64 USBHALHost* USBHALHost::instHost;
va009039 0:c972ee42b455 65
va009039 0:c972ee42b455 66 USBHALHost::USBHALHost() {
va009039 0:c972ee42b455 67 instHost = this;
va009039 0:c972ee42b455 68 }
va009039 0:c972ee42b455 69
va009039 0:c972ee42b455 70 void USBHALHost::init() {
va009039 0:c972ee42b455 71 NVIC_DisableIRQ(USB_IRQn);
va009039 0:c972ee42b455 72 m_pHcca = new HCCA();
va009039 0:c972ee42b455 73 init_hw_ohci(m_pHcca);
va009039 0:c972ee42b455 74 ResetRootHub();
va009039 0:c972ee42b455 75 NVIC_SetVector(USB_IRQn, (uint32_t)_usbisr);
va009039 0:c972ee42b455 76 NVIC_SetPriority(USB_IRQn, 0);
va009039 0:c972ee42b455 77 NVIC_EnableIRQ(USB_IRQn);
va009039 0:c972ee42b455 78
va009039 0:c972ee42b455 79 #ifndef BASE_USBHOST
va009039 0:c972ee42b455 80 USB_INFO("Simple USBHost Library for EA LPC4088 QSB");
va009039 0:c972ee42b455 81 bool lowSpeed = false;
va009039 0:c972ee42b455 82 addDevice(NULL, 0, lowSpeed);
va009039 0:c972ee42b455 83 #endif // BASE_USBHOST
va009039 0:c972ee42b455 84 }
va009039 0:c972ee42b455 85
va009039 0:c972ee42b455 86 void USBHALHost::init_hw_ohci(HCCA* pHcca) {
va009039 0:c972ee42b455 87 LPC_SC->PCONP &= ~(1UL<<31); //Cut power
va009039 0:c972ee42b455 88 wait(1);
va009039 0:c972ee42b455 89 LPC_SC->PCONP |= (1UL<<31); // turn on power for USB
va009039 0:c972ee42b455 90 LPC_USB->USBClkCtrl |= CLOCK_MASK; // Enable USB host clock, port selection and AHB clock
va009039 0:c972ee42b455 91 // Wait for clocks to become available
va009039 0:c972ee42b455 92 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
va009039 0:c972ee42b455 93 ;
va009039 0:c972ee42b455 94 LPC_USB->OTGStCtrl |= 1;
va009039 0:c972ee42b455 95 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
va009039 0:c972ee42b455 96
va009039 0:c972ee42b455 97 #if defined(TARGET_LPC1768)
va009039 0:c972ee42b455 98 LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));
va009039 0:c972ee42b455 99 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // 0x14000000
va009039 0:c972ee42b455 100 #elif defined(TARGET_LPC4088)
va009039 0:c972ee42b455 101 LPC_IOCON->P0_29 = 0x01; // USB_D+1
va009039 0:c972ee42b455 102 LPC_IOCON->P0_30 = 0x01; // USB_D-1
va009039 0:c972ee42b455 103 // DO NOT CHANGE P1_19.
va009039 0:c972ee42b455 104 #else
va009039 0:c972ee42b455 105 #error "target error"
va009039 0:c972ee42b455 106 #endif
va009039 0:c972ee42b455 107 DBG("initialize OHCI\n");
va009039 0:c972ee42b455 108 wait_ms(100); /* Wait 50 ms before apply reset */
va009039 0:c972ee42b455 109 TEST_ASSERT((LPC_USB->HcRevision&0xff) == 0x10); // check revision
va009039 0:c972ee42b455 110 LPC_USB->HcControl = 0; /* HARDWARE RESET */
va009039 0:c972ee42b455 111 LPC_USB->HcControlHeadED = 0; /* Initialize Control list head to Zero */
va009039 0:c972ee42b455 112 LPC_USB->HcBulkHeadED = 0; /* Initialize Bulk list head to Zero */
va009039 0:c972ee42b455 113 /* SOFTWARE RESET */
va009039 0:c972ee42b455 114 LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
va009039 0:c972ee42b455 115 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; /* Write Fm Interval and Largest Data Packet Counter */
va009039 0:c972ee42b455 116 LPC_USB->HcPeriodicStart = FI*90/100;
va009039 0:c972ee42b455 117 /* Put HC in operational state */
va009039 0:c972ee42b455 118 LPC_USB->HcControl = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
va009039 0:c972ee42b455 119 LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC; /* Set Global Power */
va009039 0:c972ee42b455 120 TEST_ASSERT(pHcca);
va009039 0:c972ee42b455 121 for (int i = 0; i < 32; i++) {
va009039 0:c972ee42b455 122 pHcca->InterruptTable[i] = NULL;
va009039 0:c972ee42b455 123 }
va009039 0:c972ee42b455 124 LPC_USB->HcHCCA = reinterpret_cast<uint32_t>(pHcca);
va009039 0:c972ee42b455 125 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
va009039 0:c972ee42b455 126 LPC_USB->HcInterruptEnable = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO;
va009039 0:c972ee42b455 127
va009039 0:c972ee42b455 128 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
va009039 0:c972ee42b455 129 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
va009039 0:c972ee42b455 130 }
va009039 0:c972ee42b455 131
va009039 0:c972ee42b455 132 void USBHALHost::ResetRootHub() {
va009039 0:c972ee42b455 133 wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */
va009039 0:c972ee42b455 134 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
va009039 0:c972ee42b455 135 DBG("Before loop\n");
va009039 0:c972ee42b455 136 while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
va009039 0:c972ee42b455 137 ;
va009039 0:c972ee42b455 138 LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
va009039 0:c972ee42b455 139 DBG("After loop\n");
va009039 0:c972ee42b455 140 wait_ms(200); /* Wait for 100 MS after port reset */
va009039 0:c972ee42b455 141 }
va009039 0:c972ee42b455 142
va009039 0:c972ee42b455 143 void USBHALHost::enable(ENDPOINT_TYPE type) {
va009039 0:c972ee42b455 144 switch(type) {
va009039 0:c972ee42b455 145 case CONTROL_ENDPOINT:
va009039 0:c972ee42b455 146 LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
va009039 0:c972ee42b455 147 LPC_USB->HcControl |= OR_CONTROL_CLE;
va009039 0:c972ee42b455 148 break;
va009039 0:c972ee42b455 149 case ISOCHRONOUS_ENDPOINT:
va009039 0:c972ee42b455 150 LPC_USB->HcControl |= OR_CONTROL_PLE;
va009039 0:c972ee42b455 151 break;
va009039 0:c972ee42b455 152 case BULK_ENDPOINT:
va009039 0:c972ee42b455 153 LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF;
va009039 0:c972ee42b455 154 LPC_USB->HcControl |= OR_CONTROL_BLE;
va009039 0:c972ee42b455 155 break;
va009039 0:c972ee42b455 156 case INTERRUPT_ENDPOINT:
va009039 0:c972ee42b455 157 LPC_USB->HcControl |= OR_CONTROL_PLE;
va009039 0:c972ee42b455 158 break;
va009039 0:c972ee42b455 159 }
va009039 0:c972ee42b455 160 }
va009039 0:c972ee42b455 161
va009039 0:c972ee42b455 162 void USBHALHost::token_init(USBEndpoint* ep) {
va009039 0:c972ee42b455 163 if (ep->m_pED == NULL) {
va009039 0:c972ee42b455 164 ep->m_pED = new HCED(ep);
va009039 0:c972ee42b455 165 USB_DBG_ED(ep->m_pED);
va009039 0:c972ee42b455 166 }
va009039 0:c972ee42b455 167 HCED* ed = ep->m_pED;
va009039 0:c972ee42b455 168 USBDeviceConnected* dev = ep->getDevice();
va009039 0:c972ee42b455 169 USB_TEST_ASSERT(dev);
va009039 0:c972ee42b455 170 if (dev) {
va009039 0:c972ee42b455 171 uint8_t devAddr = dev->getAddress();
va009039 0:c972ee42b455 172 USB_DBG("devAddr=%02x", devAddr);
va009039 0:c972ee42b455 173 ed->setFunctionAddress(devAddr);
va009039 0:c972ee42b455 174 }
va009039 0:c972ee42b455 175 uint16_t size = ep->getSize();
va009039 0:c972ee42b455 176 USB_DBG("MaxPacketSize=%d", size);
va009039 0:c972ee42b455 177 ed->setMaxPacketSize(size);
va009039 0:c972ee42b455 178 if (ed->HeadTd == NULL) {
va009039 0:c972ee42b455 179 HCTD* td = new HCTD(ep);
va009039 0:c972ee42b455 180 ed->TailTd = td;
va009039 0:c972ee42b455 181 ed->HeadTd = td;
va009039 0:c972ee42b455 182 switch(ep->getType()) {
va009039 0:c972ee42b455 183 case CONTROL_ENDPOINT:
va009039 0:c972ee42b455 184 ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED);
va009039 0:c972ee42b455 185 LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(ed);
va009039 0:c972ee42b455 186 break;
va009039 0:c972ee42b455 187 case BULK_ENDPOINT:
va009039 0:c972ee42b455 188 ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcBulkHeadED);
va009039 0:c972ee42b455 189 LPC_USB->HcBulkHeadED = reinterpret_cast<uint32_t>(ed);
va009039 0:c972ee42b455 190 break;
va009039 0:c972ee42b455 191 case INTERRUPT_ENDPOINT:
va009039 0:c972ee42b455 192 HCCA* pHcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
va009039 0:c972ee42b455 193 ed->Next = pHcca->InterruptTable[0];
va009039 0:c972ee42b455 194 pHcca->InterruptTable[0] = ed;
va009039 0:c972ee42b455 195 break;
va009039 0:c972ee42b455 196 }
va009039 0:c972ee42b455 197 USB_DBG_ED(ed);
va009039 0:c972ee42b455 198 }
va009039 0:c972ee42b455 199 }
va009039 0:c972ee42b455 200
va009039 0:c972ee42b455 201 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
va009039 0:c972ee42b455 202 token_init(ep);
va009039 0:c972ee42b455 203 HCED* ed = ep->m_pED;
va009039 0:c972ee42b455 204 HCTD* td = ed->TailTd;
va009039 0:c972ee42b455 205 setup->wLength = wLength;
va009039 0:c972ee42b455 206 TBUF* tbuf = new(sizeof(SETUP_PACKET))TBUF(setup, sizeof(SETUP_PACKET));
va009039 0:c972ee42b455 207 td->transfer(tbuf, sizeof(SETUP_PACKET));
va009039 0:c972ee42b455 208 td->Control |= TD_TOGGLE_0|TD_SETUP;
va009039 0:c972ee42b455 209 HCTD* blank = new HCTD(ep);
va009039 0:c972ee42b455 210 ed->enqueue(blank);
va009039 0:c972ee42b455 211 //DBG_ED(ed);
va009039 0:c972ee42b455 212 enable(ep->getType());
va009039 0:c972ee42b455 213
va009039 0:c972ee42b455 214 td = ep->get_queue_HCTD();
va009039 0:c972ee42b455 215 TEST_ASSERT(td);
va009039 0:c972ee42b455 216 int result = td->getLengthTransferred();
va009039 0:c972ee42b455 217 DBG_TD(td);
va009039 0:c972ee42b455 218 delete tbuf;
va009039 0:c972ee42b455 219 delete td;
va009039 0:c972ee42b455 220 return result;
va009039 0:c972ee42b455 221 }
va009039 0:c972ee42b455 222
va009039 0:c972ee42b455 223 int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
va009039 0:c972ee42b455 224 token_init(ep);
va009039 0:c972ee42b455 225 HCED* ed = ep->m_pED;
va009039 0:c972ee42b455 226 HCTD* td = ed->TailTd;
va009039 0:c972ee42b455 227 TBUF* tbuf = NULL;
va009039 0:c972ee42b455 228 if (data != NULL) {
va009039 0:c972ee42b455 229 tbuf = new(size)TBUF();
va009039 0:c972ee42b455 230 td->transfer(tbuf, size);
va009039 0:c972ee42b455 231 }
va009039 0:c972ee42b455 232 td->Control |= TD_IN;
va009039 0:c972ee42b455 233 HCTD* blank = new HCTD(ep);
va009039 0:c972ee42b455 234 ed->enqueue(blank);
va009039 0:c972ee42b455 235 USB_DBG_ED_IF(ed->EndpointNumber()==0, ed); // control transfer
va009039 0:c972ee42b455 236 enable(ep->getType());
va009039 0:c972ee42b455 237
va009039 0:c972ee42b455 238 td = ep->get_queue_HCTD();
va009039 0:c972ee42b455 239 TEST_ASSERT(td);
va009039 0:c972ee42b455 240 if (data != NULL) {
va009039 0:c972ee42b455 241 memcpy(data, tbuf->buf, size);
va009039 0:c972ee42b455 242 delete tbuf;
va009039 0:c972ee42b455 243 }
va009039 0:c972ee42b455 244 int result = td->getLengthTransferred();
va009039 0:c972ee42b455 245 delete td;
va009039 0:c972ee42b455 246 return result;
va009039 0:c972ee42b455 247 }
va009039 0:c972ee42b455 248
va009039 0:c972ee42b455 249 int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
va009039 0:c972ee42b455 250 token_init(ep);
va009039 0:c972ee42b455 251 HCED* ed = ep->m_pED;
va009039 0:c972ee42b455 252 HCTD* td = ed->TailTd;
va009039 0:c972ee42b455 253 TBUF* tbuf = NULL;
va009039 0:c972ee42b455 254 if (data != NULL) {
va009039 0:c972ee42b455 255 tbuf = new(size)TBUF(data, size);
va009039 0:c972ee42b455 256 td->transfer(tbuf, size);
va009039 0:c972ee42b455 257 }
va009039 0:c972ee42b455 258 td->Control |= TD_OUT;
va009039 0:c972ee42b455 259 HCTD* blank = new HCTD(ep);
va009039 0:c972ee42b455 260 ed->enqueue(blank);
va009039 0:c972ee42b455 261 DBG_ED(ed);
va009039 0:c972ee42b455 262 enable(ep->getType());
va009039 0:c972ee42b455 263
va009039 0:c972ee42b455 264 td = ep->get_queue_HCTD();
va009039 0:c972ee42b455 265 TEST_ASSERT(td);
va009039 0:c972ee42b455 266 if (data != NULL) {
va009039 0:c972ee42b455 267 delete tbuf;
va009039 0:c972ee42b455 268 }
va009039 0:c972ee42b455 269 int result = td->getLengthTransferred();
va009039 0:c972ee42b455 270 delete td;
va009039 0:c972ee42b455 271 return result;
va009039 0:c972ee42b455 272 }
va009039 0:c972ee42b455 273
va009039 0:c972ee42b455 274 void USBHALHost::token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
va009039 0:c972ee42b455 275 token_init(ep);
va009039 0:c972ee42b455 276 HCED* ed = ep->m_pED;
va009039 0:c972ee42b455 277 HCTD* td = ed->TailTd;
va009039 0:c972ee42b455 278 TBUF* tbuf = new(size)TBUF();
va009039 0:c972ee42b455 279 td->transfer(tbuf, size);
va009039 0:c972ee42b455 280 td->Control |= TD_IN;
va009039 0:c972ee42b455 281 HCTD* blank = new HCTD(ep);
va009039 0:c972ee42b455 282 ed->enqueue(blank);
va009039 0:c972ee42b455 283 enable(ep->getType());
va009039 0:c972ee42b455 284 }
va009039 0:c972ee42b455 285
va009039 0:c972ee42b455 286 USB_TYPE USBHALHost::token_inNB_result(USBEndpoint* ep) {
va009039 0:c972ee42b455 287 HCTD* td = ep->get_queue_HCTD(0);
va009039 0:c972ee42b455 288 if (td) {
va009039 0:c972ee42b455 289 int len = td->getLengthTransferred();
va009039 0:c972ee42b455 290 TBUF* tbuf = (TBUF*)td->buf_top;
va009039 0:c972ee42b455 291 memcpy(ep->getBufStart(), tbuf->buf, len);
va009039 0:c972ee42b455 292 ep->setLengthTransferred(len);
va009039 0:c972ee42b455 293 delete td;
va009039 0:c972ee42b455 294 delete tbuf;
va009039 0:c972ee42b455 295 return USB_TYPE_OK;
va009039 0:c972ee42b455 296 }
va009039 0:c972ee42b455 297 return USB_TYPE_PROCESSING;
va009039 0:c972ee42b455 298 }
va009039 0:c972ee42b455 299
va009039 0:c972ee42b455 300 void USBHALHost::_usbisr(void) {
va009039 0:c972ee42b455 301 if (instHost) {
va009039 0:c972ee42b455 302 instHost->UsbIrqhandler();
va009039 0:c972ee42b455 303 }
va009039 0:c972ee42b455 304 }
va009039 0:c972ee42b455 305
va009039 0:c972ee42b455 306 HCTD* td_reverse(HCTD* td)
va009039 0:c972ee42b455 307 {
va009039 0:c972ee42b455 308 HCTD* result = NULL;
va009039 0:c972ee42b455 309 HCTD* next;
va009039 0:c972ee42b455 310 while(td) {
va009039 0:c972ee42b455 311 next = const_cast<HCTD*>(td->Next);
va009039 0:c972ee42b455 312 td->Next = result;
va009039 0:c972ee42b455 313 result = td;
va009039 0:c972ee42b455 314 td = next;
va009039 0:c972ee42b455 315 }
va009039 0:c972ee42b455 316 return result;
va009039 0:c972ee42b455 317 }
va009039 0:c972ee42b455 318
va009039 0:c972ee42b455 319 void USBHALHost::UsbIrqhandler() {
va009039 0:c972ee42b455 320 if (!(LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable)) {
va009039 0:c972ee42b455 321 return;
va009039 0:c972ee42b455 322 }
va009039 0:c972ee42b455 323 m_report_irq++;
va009039 0:c972ee42b455 324 uint32_t status = LPC_USB->HcInterruptStatus;
va009039 0:c972ee42b455 325 if (status & OR_INTR_STATUS_FNO) {
va009039 0:c972ee42b455 326 m_report_FNO++;
va009039 0:c972ee42b455 327 }
va009039 0:c972ee42b455 328 if (status & OR_INTR_STATUS_WDH) {
va009039 0:c972ee42b455 329 union {
va009039 0:c972ee42b455 330 HCTD* done_td;
va009039 0:c972ee42b455 331 uint32_t lsb;
va009039 0:c972ee42b455 332 };
va009039 0:c972ee42b455 333 done_td = const_cast<HCTD*>(m_pHcca->DoneHead);
va009039 0:c972ee42b455 334 TEST_ASSERT(done_td);
va009039 0:c972ee42b455 335 m_pHcca->DoneHead = NULL; // reset
va009039 0:c972ee42b455 336 if (lsb & 1) { // error ?
va009039 0:c972ee42b455 337 lsb &= ~1;
va009039 0:c972ee42b455 338 }
va009039 0:c972ee42b455 339 HCTD* td = td_reverse(done_td);
va009039 0:c972ee42b455 340 while(td) {
va009039 0:c972ee42b455 341 USBEndpoint* ep = td->ep;
va009039 0:c972ee42b455 342 TEST_ASSERT(ep);
va009039 0:c972ee42b455 343 if (ep) {
va009039 0:c972ee42b455 344 ep->irqWdhHandler(td);
va009039 0:c972ee42b455 345 }
va009039 0:c972ee42b455 346 td = td->Next;
va009039 0:c972ee42b455 347 }
va009039 0:c972ee42b455 348 m_report_WDH++;
va009039 0:c972ee42b455 349 }
va009039 0:c972ee42b455 350 LPC_USB->HcInterruptStatus = status; // Clear Interrrupt Status
va009039 0:c972ee42b455 351 }
va009039 0:c972ee42b455 352
va009039 0:c972ee42b455 353 TBUF::TBUF(const void* data, int size) {
va009039 0:c972ee42b455 354 if (size > 0) {
va009039 0:c972ee42b455 355 memcpy(buf, data, size);
va009039 0:c972ee42b455 356 }
va009039 0:c972ee42b455 357 }
va009039 0:c972ee42b455 358
va009039 0:c972ee42b455 359 HCTD::HCTD(USBEndpoint* obj) {
va009039 0:c972ee42b455 360 CTASSERT(sizeof(HCTD) == 36);
va009039 0:c972ee42b455 361 TEST_ASSERT(obj);
va009039 0:c972ee42b455 362 Control = TD_CC|TD_ROUNDING;
va009039 0:c972ee42b455 363 CurrBufPtr = NULL;
va009039 0:c972ee42b455 364 Next = NULL;
va009039 0:c972ee42b455 365 BufEnd = NULL;
va009039 0:c972ee42b455 366 buf_top = NULL;
va009039 0:c972ee42b455 367 buf_size = 0;
va009039 0:c972ee42b455 368 ep = obj;
va009039 0:c972ee42b455 369 }
va009039 0:c972ee42b455 370
va009039 0:c972ee42b455 371 HCITD::HCITD(USBEndpoint* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
va009039 0:c972ee42b455 372 Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED
va009039 0:c972ee42b455 373 ((FrameCount-1) << 24)| // FC FrameCount
va009039 0:c972ee42b455 374 TD_DELAY_INT(0) | // DI DelayInterrupt
va009039 0:c972ee42b455 375 FrameNumber; // SF StartingFrame
va009039 0:c972ee42b455 376 BufferPage0 = const_cast<uint8_t*>(buf);
va009039 0:c972ee42b455 377 BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
va009039 0:c972ee42b455 378 Next = NULL;
va009039 0:c972ee42b455 379 ep = obj;
va009039 0:c972ee42b455 380 uint32_t addr = reinterpret_cast<uint32_t>(buf);
va009039 0:c972ee42b455 381 for(int i = 0; i < FrameCount; i++) {
va009039 0:c972ee42b455 382 uint16_t offset = addr & 0x0fff;
va009039 0:c972ee42b455 383 if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
va009039 0:c972ee42b455 384 offset |= 0x1000;
va009039 0:c972ee42b455 385 }
va009039 0:c972ee42b455 386 OffsetPSW[i] = 0xe000|offset;
va009039 0:c972ee42b455 387 addr += PacketSize;
va009039 0:c972ee42b455 388 }
va009039 0:c972ee42b455 389 }
va009039 0:c972ee42b455 390
va009039 0:c972ee42b455 391 HCED::HCED(USBEndpoint* ep) {
va009039 0:c972ee42b455 392 USBDeviceConnected* dev = ep->getDevice();
va009039 0:c972ee42b455 393 int devAddr = 0;
va009039 0:c972ee42b455 394 bool lowSpeed = false;
va009039 0:c972ee42b455 395 if (dev) {
va009039 0:c972ee42b455 396 devAddr = dev->getAddress();
va009039 0:c972ee42b455 397 lowSpeed = dev->getSpeed();
va009039 0:c972ee42b455 398 }
va009039 0:c972ee42b455 399 int ep_number = ep->getAddress();
va009039 0:c972ee42b455 400 int MaxPacketSize = ep->getSize();
va009039 0:c972ee42b455 401 Control = devAddr | /* USB address */
va009039 0:c972ee42b455 402 ((ep_number & 0x7F) << 7) | /* Endpoint address */
va009039 0:c972ee42b455 403 (ep_number!=0?(((ep_number&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
va009039 0:c972ee42b455 404 ((lowSpeed?1:0) << 13) | /* speed full=0 low=1 */
va009039 0:c972ee42b455 405 (MaxPacketSize << 16); /* MaxPkt Size */
va009039 0:c972ee42b455 406 TailTd = NULL;
va009039 0:c972ee42b455 407 HeadTd = NULL;
va009039 0:c972ee42b455 408 Next = NULL;
va009039 0:c972ee42b455 409 }
va009039 0:c972ee42b455 410
va009039 0:c972ee42b455 411 bool HCED::enqueue(HCTD* td) {
va009039 0:c972ee42b455 412 if (td) {
va009039 0:c972ee42b455 413 HCTD* tail = reinterpret_cast<HCTD*>(TailTd);
va009039 0:c972ee42b455 414 if (tail) {
va009039 0:c972ee42b455 415 tail->Next = td;
va009039 0:c972ee42b455 416 TailTd = reinterpret_cast<HCTD*>(td);
va009039 0:c972ee42b455 417 return true;
va009039 0:c972ee42b455 418 }
va009039 0:c972ee42b455 419 }
va009039 0:c972ee42b455 420 return false;
va009039 0:c972ee42b455 421 }
va009039 0:c972ee42b455 422
va009039 0:c972ee42b455 423 void HCED::init_queue(HCTD* td) {
va009039 0:c972ee42b455 424 TailTd = reinterpret_cast<HCTD*>(td);
va009039 0:c972ee42b455 425 HeadTd = reinterpret_cast<HCTD*>(td);
va009039 0:c972ee42b455 426 }
va009039 0:c972ee42b455 427
va009039 0:c972ee42b455 428 void HCCA::enqueue(HCED* ed) {
va009039 0:c972ee42b455 429 for(int i = 0; i < 32; i++) {
va009039 0:c972ee42b455 430 if (InterruptTable[i] == NULL) {
va009039 0:c972ee42b455 431 InterruptTable[i] = ed;
va009039 0:c972ee42b455 432 } else {
va009039 0:c972ee42b455 433 HCED* nextEd = InterruptTable[i];
va009039 0:c972ee42b455 434 while(nextEd->Next && nextEd->Next != ed) {
va009039 0:c972ee42b455 435 nextEd = nextEd->Next;
va009039 0:c972ee42b455 436 }
va009039 0:c972ee42b455 437 nextEd->Next = ed;
va009039 0:c972ee42b455 438 }
va009039 0:c972ee42b455 439 }
va009039 0:c972ee42b455 440 }
va009039 0:c972ee42b455 441
va009039 0:c972ee42b455 442