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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHALHost_LPC4088.cpp Source File

USBHALHost_LPC4088.cpp

00001 /* mbed USBHost Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #if defined(TARGET_LPC4088)||defined(TARGET_LPC1768)
00018 #include "USBHALHost.h"
00019 
00020 #ifndef CTASSERT
00021 template <bool>struct CtAssert;
00022 template <>struct CtAssert<true> {};
00023 #define CTASSERT(A) CtAssert<A>();
00024 #endif
00025 
00026 #ifdef _USB_DBG
00027 #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
00028 #define USB_DBG_HEX(A,B) debug_hex(A,B)
00029 #define USB_DBG_ED(A) while(0)
00030 #define USB_DBG_TD(A) while(0)
00031 #define USB_DBG_ED_IF(A,B) while(0)
00032 void debug_hex(uint8_t* buf, int size);
00033 #else
00034 #define USB_DBG(...) while(0)
00035 #define USB_DBG_ED(A) while(0)
00036 #define USB_DBG_TD(A) while(0)
00037 #define USB_DBG_ED_IF(A,B) while(0)
00038 #define USB_DBG_HEX(A,B) while(0)
00039 #endif
00040 
00041 #define USB_TRACE1(A) while(0)
00042 
00043 #ifdef _USB_TEST
00044 #undef USB_TEST_ASSERT
00045 void usb_test_assert_internal(const char *expr, const char *file, int line);
00046 #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
00047 #else
00048 #define USB_TEST_ASSERT(EXPR) while(0)
00049 #endif
00050 
00051 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
00052 
00053 // bits of the USB/OTG clock control register
00054 #define HOST_CLK_EN     (1<<0)
00055 #define DEV_CLK_EN      (1<<1)
00056 #define PORTSEL_CLK_EN  (1<<3)
00057 #define AHB_CLK_EN      (1<<4)
00058 
00059 // bits of the USB/OTG clock status register
00060 #define HOST_CLK_ON     (1<<0)
00061 #define DEV_CLK_ON      (1<<1)
00062 #define PORTSEL_CLK_ON  (1<<3)
00063 #define AHB_CLK_ON      (1<<4)
00064 
00065 // we need host clock, OTG/portsel clock and AHB clock
00066 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
00067 #define  FI                     0x2EDF           /* 12000 bits per frame (-1) */
00068 #define  DEFAULT_FMINTERVAL     ((((6 * (FI - 210)) / 7) << 16) | FI)
00069 
00070 USBHALHost* USBHALHost::instHost;
00071 
00072 USBHALHost::USBHALHost() {
00073     instHost = this;
00074 }
00075 
00076 void USBHALHost::init() {
00077     NVIC_DisableIRQ(USB_IRQn);
00078     m_pHcca = new HCCA();
00079     init_hw_ohci(m_pHcca);
00080     ResetRootHub();
00081     NVIC_SetVector(USB_IRQn, (uint32_t)_usbisr);
00082     NVIC_SetPriority(USB_IRQn, 0);
00083     NVIC_EnableIRQ(USB_IRQn);
00084 
00085     USB_INFO("Simple USBHost Library for LPC4088/LPC1768");
00086     bool lowSpeed = wait_attach();
00087     addDevice(NULL, 0, lowSpeed);
00088 }
00089 
00090 void USBHALHost::init_hw_ohci(HCCA* pHcca) {
00091     LPC_SC->PCONP &= ~(1UL<<31);    //Cut power
00092     wait_ms(1000);
00093     LPC_SC->PCONP |= (1UL<<31);     // turn on power for USB
00094     LPC_USB->USBClkCtrl |= CLOCK_MASK; // Enable USB host clock, port selection and AHB clock
00095     // Wait for clocks to become available
00096     while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
00097         ;
00098     LPC_USB->OTGStCtrl |= 1;
00099     LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;
00100     
00101 #if defined(TARGET_LPC1768)
00102     LPC_PINCON->PINSEL1 &= ~((3<<26) | (3<<28));  
00103     LPC_PINCON->PINSEL1 |=  ((1<<26)|(1<<28));     // 0x14000000
00104 #elif defined(TARGET_LPC4088)
00105     LPC_IOCON->P0_29 = 0x01; // USB_D+1
00106     LPC_IOCON->P0_30 = 0x01; // USB_D-1
00107     // DO NOT CHANGE P1_19.
00108 #else
00109 #error "target error"
00110 #endif
00111     USB_DBG("initialize OHCI\n");
00112     wait_ms(100);                                   /* Wait 50 ms before apply reset              */
00113     USB_TEST_ASSERT((LPC_USB->HcRevision&0xff) == 0x10); // check revision
00114     LPC_USB->HcControl       = 0;                       /* HARDWARE RESET                             */
00115     LPC_USB->HcControlHeadED = 0;                       /* Initialize Control list head to Zero       */
00116     LPC_USB->HcBulkHeadED    = 0;                       /* Initialize Bulk list head to Zero          */
00117                                                         /* SOFTWARE RESET                             */
00118     LPC_USB->HcCommandStatus = OR_CMD_STATUS_HCR;
00119     LPC_USB->HcFmInterval    = DEFAULT_FMINTERVAL;      /* Write Fm Interval and Largest Data Packet Counter */
00120     LPC_USB->HcPeriodicStart = FI*90/100;
00121                                                       /* Put HC in operational state                */
00122     LPC_USB->HcControl  = (LPC_USB->HcControl & (~OR_CONTROL_HCFS)) | OR_CONTROL_HC_OPER;
00123     LPC_USB->HcRhStatus = OR_RH_STATUS_LPSC;            /* Set Global Power */
00124     USB_TEST_ASSERT(pHcca);
00125     for (int i = 0; i < 32; i++) {
00126         pHcca->InterruptTable[i] = NULL;
00127     }
00128     LPC_USB->HcHCCA = reinterpret_cast<uint32_t>(pHcca);
00129     LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; /* Clear Interrrupt Status */
00130     LPC_USB->HcInterruptEnable  = OR_INTR_ENABLE_MIE|OR_INTR_ENABLE_WDH|OR_INTR_ENABLE_FNO;
00131 
00132     LPC_USB->HcRhPortStatus1 = OR_RH_PORT_CSC;
00133     LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC;
00134 }
00135 
00136 void USBHALHost::ResetRootHub() {
00137     wait_ms(100); /* USB 2.0 spec says at least 50ms delay before port reset */
00138     LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRS; // Initiate port reset
00139     USB_DBG("Before loop\n");
00140     while (LPC_USB->HcRhPortStatus1 & OR_RH_PORT_PRS)
00141       ;
00142     LPC_USB->HcRhPortStatus1 = OR_RH_PORT_PRSC; // ...and clear port reset signal
00143     USB_DBG("After loop\n");
00144     wait_ms(200); /* Wait for 100 MS after port reset  */
00145 }
00146 
00147 bool USBHALHost::wait_attach() {
00148     bool lowSpeed = false;
00149     uint32_t status = LPC_USB->HcRhPortStatus1;
00150     if (status & OR_RH_PORT_LSDA) { // lowSpeedDeviceAttached
00151         lowSpeed = true;
00152     }
00153     return lowSpeed;
00154 }
00155 
00156 void enable(ENDPOINT_TYPE type) {
00157     switch(type) {
00158         case CONTROL_ENDPOINT:
00159             LPC_USB->HcCommandStatus |= OR_CMD_STATUS_CLF;
00160             LPC_USB->HcControl |= OR_CONTROL_CLE;
00161             break;
00162         case ISOCHRONOUS_ENDPOINT:
00163             LPC_USB->HcControl |= OR_CONTROL_PLE;
00164             break;
00165         case BULK_ENDPOINT:
00166             LPC_USB->HcCommandStatus |= OR_CMD_STATUS_BLF;
00167             LPC_USB->HcControl |= OR_CONTROL_BLE;
00168             break;
00169         case INTERRUPT_ENDPOINT:
00170             LPC_USB->HcControl |= OR_CONTROL_PLE;
00171             break;
00172     }
00173 }
00174 
00175 void USBHALHost::token_init(USBEndpoint* ep) {
00176     HCED* ed = ep->getHALData<HCED*>();
00177     if (ed == NULL) {
00178         ed = new HCED(ep);
00179         ep->setHALData<HCED*>(ed);
00180     }
00181     USBDeviceConnected* dev = ep->getDevice();
00182     USB_TEST_ASSERT(dev);
00183     if (dev) {
00184         uint8_t devAddr = dev->getAddress();
00185         USB_DBG("devAddr=%02x", devAddr);
00186         ed->setFunctionAddress(devAddr);
00187     }
00188     uint16_t size = ep->getSize();
00189     USB_DBG("MaxPacketSize=%d", size);
00190     ed->setMaxPacketSize(size);
00191     if (ed->HeadTd == NULL) {
00192         HCTD* td = new HCTD(ed);
00193         ed->TailTd = td;
00194         ed->HeadTd = td;
00195         switch(ep->getType()) {
00196             case CONTROL_ENDPOINT:
00197                 ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcControlHeadED);
00198                 LPC_USB->HcControlHeadED = reinterpret_cast<uint32_t>(ed);
00199                 break;
00200             case BULK_ENDPOINT:
00201                 ed->Next = reinterpret_cast<HCED*>(LPC_USB->HcBulkHeadED);
00202                 LPC_USB->HcBulkHeadED = reinterpret_cast<uint32_t>(ed);
00203                 break;
00204             case INTERRUPT_ENDPOINT:
00205                 HCCA* pHcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
00206                 ed->Next = pHcca->InterruptTable[0];
00207                 pHcca->InterruptTable[0] = ed;
00208                 break;
00209         }
00210     }
00211 }
00212 
00213 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
00214     token_init(ep);
00215     HCED* ed = ep->getHALData<HCED*>();
00216     HCTD* td = ed->TailTd;
00217     setup->wLength = wLength;
00218     TBUF* tbuf = new(sizeof(SETUP_PACKET))TBUF(setup, sizeof(SETUP_PACKET));
00219     td->transfer(tbuf, sizeof(SETUP_PACKET));
00220     td->Control |= TD_TOGGLE_0|TD_SETUP; // DATA0
00221     HCTD* blank = new HCTD(ed);
00222     ed->enqueue(blank);
00223     //DBG_ED(ed);
00224     enable(ep->getType());
00225 
00226     td = ed->get_queue_HCTD();
00227     USB_TEST_ASSERT(td);
00228     int result = td->getLengthTransferred();
00229     USB_DBG_TD(td);
00230     delete tbuf;
00231     delete td;
00232     return result;
00233 }
00234 
00235 static HCED* getHCED_iso(USBEndpoint* ep) {
00236     HCED* ed = ep->getHALData<HCED*>();
00237     if (ed != NULL) {
00238         return ed;
00239     }
00240     ed = new HCED(ep);
00241     ep->setHALData<HCED*>(ed);
00242     ed->setFormat(); // F Format ITD
00243     ed->iso.FrameCount = ep->ohci.frameCount;
00244     ed->iso.queue_limit = ep->ohci.queueLimit;
00245     ed->iso.queue_count = 0;
00246     ed->iso.Current_FrameCount = 0;
00247     ed->iso.Current_itd = NULL;
00248     ed->iso.FrameNumber = LPC_USB->HcFmNumber + 10; // after 10msec
00249     HCITD* itd = ed->new_HCITD();
00250     ed->init_queue(reinterpret_cast<HCTD*>(itd)); 
00251     HCCA* hcca = reinterpret_cast<HCCA*>(LPC_USB->HcHCCA);
00252     hcca->enqueue(ed);
00253     LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable
00254     LPC_USB->HcControl |= OR_CONTROL_IE;  // IsochronousEnable
00255     return ed;
00256 }
00257 
00258 static void enablePeriodic() {
00259     LPC_USB->HcControl |= OR_CONTROL_PLE;
00260 }
00261 
00262 HCITD* isochronousReceive(USBEndpoint* ep) {
00263     HCED* ed = getHCED_iso(ep);
00264     USB_TEST_ASSERT(ed);
00265     while(ed->iso.queue_count < ed->iso.queue_limit) {
00266         HCITD* blank_itd = ed->new_HCITD();
00267         if (ed->enqueue(reinterpret_cast<HCTD*>(blank_itd))) {
00268             ed->iso.queue_count++;
00269         }
00270         enablePeriodic();
00271     }
00272     
00273     HCITD* itd = ed->get_queue_HCITD();
00274     if (itd) {
00275         ed->iso.queue_count--;
00276     }
00277     return itd;
00278 }
00279 
00280 int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
00281     HCED* ed = getHCED_iso(ep);
00282     if (ed->iso.Current_FrameCount == 0) {
00283         HCITD* itd = isochronousReceive(ep);
00284         if (itd == NULL) {
00285             return -1;
00286         }
00287         if (itd->ConditionCode() != 0) {
00288             delete itd;
00289             return -1;
00290         }
00291         ed->iso.Current_itd = itd;
00292     }
00293 
00294     HCITD* itd = ed->iso.Current_itd;
00295     int fc = ed->iso.Current_FrameCount;
00296     int result = -1;
00297     uint8_t cc = itd->ConditionCode(fc);
00298     if (cc == 0 || cc == 9) {
00299         result = itd->Length(fc);
00300         memcpy(data, itd->Buffer(fc), result);
00301     }
00302 
00303     if (++ed->iso.Current_FrameCount >= itd->FrameCount()) {
00304         ed->iso.Current_FrameCount = 0;
00305         delete ed->iso.Current_itd;
00306     }
00307     return result;
00308 }
00309 
00310 int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, int size) {
00311     token_init(ep);
00312     HCED* ed = ep->getHALData<HCED*>();
00313     HCTD* td = ed->TailTd;
00314     TBUF* tbuf = NULL;
00315     if (data != NULL) {
00316         tbuf = new(size)TBUF();
00317         td->transfer(tbuf, size);
00318     }
00319     td->Control |= TD_IN;
00320     HCTD* blank = new HCTD(ed);
00321     ed->enqueue(blank);
00322     USB_DBG_ED_IF(ed->EndpointNumber()==0, ed); // control transfer
00323     enable(ep->getType());
00324 
00325     td = ed->get_queue_HCTD();
00326     USB_TEST_ASSERT(td);
00327     if (data != NULL) {
00328         memcpy(data, tbuf->buf, size);
00329         delete tbuf;
00330     }
00331     int result = td->getLengthTransferred();
00332     delete td;
00333     return result;
00334 }
00335 
00336 int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, int size) {
00337     token_init(ep);
00338     HCED* ed = ep->getHALData<HCED*>();
00339     HCTD* td = ed->TailTd;
00340     TBUF* tbuf = NULL;
00341     if (data != NULL) {
00342         tbuf = new(size)TBUF(data, size);
00343         td->transfer(tbuf, size);
00344     }
00345     td->Control |= TD_OUT;
00346     HCTD* blank = new HCTD(ed);
00347     ed->enqueue(blank);
00348     USB_DBG_ED(ed);
00349     enable(ep->getType());
00350 
00351     td = ed->get_queue_HCTD();
00352     USB_TEST_ASSERT(td);
00353     if (data != NULL) {
00354         delete tbuf;
00355     }
00356     int result = td->getLengthTransferred();
00357     delete td;
00358     return result;
00359 }
00360 
00361 void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
00362     token_init(ep);
00363     HCED* ed = ep->getHALData<HCED*>();
00364     HCTD* td = ed->TailTd;
00365     TBUF* tbuf = new(size)TBUF();
00366     td->transfer(tbuf, size);
00367     td->Control |= TD_IN;
00368     HCTD* blank = new HCTD(ed);
00369     ed->enqueue(blank);
00370     enable(ep->getType());
00371 }
00372 
00373 USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) {
00374     HCED* ed = ep->getHALData<HCED*>();
00375     if (ed == NULL) {
00376         return USB_TYPE_ERROR;
00377     }
00378     HCTD* td = ed->get_queue_HCTD(0);
00379     if (td) {
00380         int len = td->getLengthTransferred();
00381         TBUF* tbuf = (TBUF*)td->buf_top;
00382         memcpy(ep->getBufStart(), tbuf->buf, len);
00383         ep->setLengthTransferred(len);
00384         ep->setState((USB_TYPE)td->ConditionCode());
00385         delete td;
00386         delete tbuf;
00387         return USB_TYPE_OK;
00388     }
00389     return USB_TYPE_PROCESSING;
00390 }
00391 
00392 void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) {
00393     USB_TEST_ASSERT(toggle == 1);
00394     HCED* ed = ep->getHALData<HCED*>();
00395     ed->setToggle(toggle);
00396 }
00397 
00398 void USBHALHost::_usbisr(void) {
00399     if (instHost) {
00400         instHost->UsbIrqhandler();
00401     }
00402 }
00403 
00404 HCTD* td_reverse(HCTD* td)
00405 {
00406     HCTD* result = NULL;
00407     HCTD* next;
00408     while(td) {
00409         next = const_cast<HCTD*>(td->Next);
00410         td->Next = result;
00411         result = td;
00412         td = next;
00413     }
00414     return result;
00415 }
00416 
00417 void USBHALHost::UsbIrqhandler() {
00418     if (!(LPC_USB->HcInterruptStatus & LPC_USB->HcInterruptEnable)) {
00419         return;
00420     }
00421     m_report_irq++;
00422     uint32_t status = LPC_USB->HcInterruptStatus;
00423     if (status & OR_INTR_STATUS_FNO) {
00424         m_report_FNO++;
00425     }
00426     if (status & OR_INTR_STATUS_WDH) {
00427         union {
00428             HCTD* done_td;
00429             uint32_t lsb;
00430         };
00431         done_td = const_cast<HCTD*>(m_pHcca->DoneHead);
00432         USB_TEST_ASSERT(done_td);
00433         m_pHcca->DoneHead = NULL; // reset
00434         if (lsb & 1) { // error ?
00435             lsb &= ~1;
00436         }
00437         HCTD* td = td_reverse(done_td);
00438         while(td) {
00439             HCED* ed = td->parent;
00440             USB_TEST_ASSERT(ed);
00441             if (ed) {
00442                 ed->irqWdhHandler(td);
00443             }
00444             td = td->Next;
00445         }
00446         m_report_WDH++;
00447     }
00448     LPC_USB->HcInterruptStatus = status; // Clear Interrrupt Status
00449 }
00450 
00451 TBUF::TBUF(const void* data, int size) {
00452     if (size > 0) {
00453         memcpy(buf, data, size);
00454     }
00455 }
00456 
00457 HCTD::HCTD(HCED* obj) {
00458     CTASSERT(sizeof(HCTD) == 36);
00459     USB_TEST_ASSERT(obj);
00460     Control = TD_CC|TD_ROUNDING;
00461     CurrBufPtr = NULL;
00462     Next = NULL;
00463     BufEnd = NULL;
00464     buf_top = NULL;
00465     buf_size = 0;
00466     parent = obj;
00467 }
00468 
00469 HCITD::HCITD(HCED* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
00470     Control = 0xe0000000           | // CC ConditionCode NOT ACCESSED
00471              ((FrameCount-1) << 24)| // FC FrameCount
00472                   TD_DELAY_INT(0)  | // DI DelayInterrupt
00473                  FrameNumber;        // SF StartingFrame
00474     BufferPage0 = const_cast<uint8_t*>(buf);
00475     BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
00476     Next = NULL; 
00477     parent = obj;
00478     uint32_t addr = reinterpret_cast<uint32_t>(buf);
00479     for(int i = 0; i < FrameCount; i++) {
00480         uint16_t offset = addr & 0x0fff;
00481         if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
00482             offset |= 0x1000;
00483         }
00484         OffsetPSW[i] = 0xe000|offset;
00485         addr += PacketSize;
00486     }
00487 }
00488 
00489 uint8_t* HCITD::Buffer(int fc) {
00490     int offset = fc * parent->getMaxPacketSize();
00491     return const_cast<uint8_t*>(buf) + offset;
00492 }
00493 
00494 HCED::HCED(USBEndpoint* ep) {
00495     CTASSERT(sizeof(HCED) <= (64*2));
00496     USBDeviceConnected* dev = ep->getDevice();
00497     int devAddr = 0;
00498     bool lowSpeed = false;
00499     if (dev) {
00500         devAddr = dev->getAddress();
00501         lowSpeed = dev->getSpeed();
00502     }
00503     int ep_number = ep->getAddress();
00504     int MaxPacketSize = ep->getSize();
00505         Control =  devAddr        | /* USB address */
00506         ((ep_number & 0x7F) << 7) | /* Endpoint address */
00507         (ep_number!=0?(((ep_number&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
00508         ((lowSpeed?1:0) << 13)    | /* speed full=0 low=1 */
00509         (MaxPacketSize << 16);      /* MaxPkt Size */
00510         TailTd = NULL;
00511         HeadTd = NULL;
00512         Next = NULL;
00513 }
00514 
00515 bool HCED::enqueue(HCTD* td) {
00516     if (td) {
00517         HCTD* tail = reinterpret_cast<HCTD*>(TailTd);
00518         if (tail) {
00519             tail->Next = td;
00520             TailTd = reinterpret_cast<HCTD*>(td);
00521             return true;
00522         }
00523     }
00524     return false;
00525 }
00526 
00527 void HCED::init_queue(HCTD* td) {
00528     TailTd = reinterpret_cast<HCTD*>(td);
00529     HeadTd = reinterpret_cast<HCTD*>(td); 
00530 }
00531 
00532 void HCED::setToggle(uint8_t toggle) {
00533     uint32_t c = reinterpret_cast<uint32_t>(HeadTd);
00534     if (toggle == 0) { // DATA0
00535         c &= ~0x02;
00536     } else { // DATA1
00537         c |= 0x02;
00538     }
00539     HeadTd = reinterpret_cast<HCTD*>(c);
00540 }
00541 
00542 uint8_t HCED::getToggle() {
00543     uint32_t c = reinterpret_cast<uint32_t>(HeadTd);
00544     return (c&0x02) ? 1 : 0;
00545 }
00546 
00547 HCTD* HCED::get_queue_HCTD(uint32_t millisec)
00548 {
00549     for(int i = 0; i < 16; i++) {
00550         osEvent evt = done_queue_get(millisec);
00551         if (evt.status == osEventMessage) {
00552             HCTD* td = reinterpret_cast<HCTD*>(evt.value.p);
00553             USB_TEST_ASSERT(td);
00554             uint8_t cc = td->ConditionCode();
00555             if (cc != 0) {
00556                 m_ConditionCode = cc;
00557                 USB_DBG_TD(td);
00558             }
00559             return td;
00560         } else if (evt.status == osOK) {
00561             continue;
00562         } else if (evt.status == osEventTimeout) {
00563             return NULL;
00564         } else {
00565             USB_DBG("evt.status: %02x\n", evt.status);
00566             USB_TEST_ASSERT(evt.status == osEventMessage);
00567         }
00568     }
00569     return NULL;
00570 }
00571 
00572 HCITD* HCED::get_queue_HCITD() {
00573     osEvent evt = done_queue_get(0);
00574     if (evt.status == osEventMessage) {
00575         HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
00576         USB_TEST_ASSERT(itd);
00577         return itd;
00578     }
00579     return NULL;
00580 }
00581 HCITD* HCED::new_HCITD() {
00582     uint16_t mps = getMaxPacketSize();
00583     int total_size = mps * iso.FrameCount;
00584     HCITD* itd = new(total_size)HCITD(this, iso.FrameNumber, iso.FrameCount, mps);
00585     iso.FrameNumber += iso.FrameCount;
00586     return itd;
00587 }
00588 
00589 void HCCA::enqueue(HCED* ed) {
00590     for(int i = 0; i < 32; i++) {
00591         if (InterruptTable[i] == NULL) {
00592             InterruptTable[i] = ed;
00593         } else {
00594             HCED* nextEd = InterruptTable[i];
00595             while(nextEd->Next && nextEd->Next != ed) {
00596                 nextEd = nextEd->Next;
00597             }
00598             nextEd->Next = ed;
00599         }
00600     }
00601 }
00602 
00603 #endif // defined(TARGET_LPC4088)||defined(TARGET_LPC1768)
00604