Almost identical to USBHostShell; reads all endpoint descriptors
Dependents: myBlueUSB mbed_TANK_Kinect myBlueUSB_ros myBlueUSB_localfix
Diff: USBHost.cpp
- Revision:
- 1:05d0fe737d3b
- Parent:
- 0:d6bff1c2dab1
--- a/USBHost.cpp Mon Apr 04 16:42:56 2011 +0000 +++ b/USBHost.cpp Wed May 04 09:12:55 2011 +0000 @@ -23,6 +23,7 @@ #include "mbed.h" #include "USBHost.h" +#include "Utils.h" // Config (default uses x bytes) #define MAX_DEVICES 8 // Max number of devices @@ -560,15 +561,16 @@ // Pop the last TD from the list HCTD* Reverse(HCTD* current) - { + { //int n = 0; HCTD *result = NULL,*temp; while (current) - { + { //n++; temp = (HCTD*)current->Next; current->Next = (u32)result; result = current; current = temp; } + //if (n>1) printf("%d TD's on Done Queue\n", n); return result; } @@ -576,17 +578,19 @@ // Control endpoints use a state machine to progress through the transfers void ProcessDoneQueue(u32 tdList) { - HCTD* list = Reverse((HCTD*)tdList); + HCTD* list = Reverse((HCTD*)tdList);//because completed transfers were added to the head of the list while (list) - { + {//horrible hack: an Endpoint starts with an HCED and an HCTD and apparently all HCTDs are contained in Endpoints this way + //furthermore the sizeof an HCTD equeals the size of an HCED, hence the next expression gives indeed the Endpoint* for the HCTD Endpoint* endpoint = (Endpoint*)(list-1); list = (HCTD*)list->Next; int ep = endpoint->Address(); bool in = endpoint->Flags & 0x80; int status = (endpoint->TDHead.Control >> 28) & 0xF; - +//the printf below is essential for correct working !?!? remove it and some messages will be missed //LOG("ProcessDoneQueue %02X %08X\n",ep,endpoint->TDHead.Control); - +wait_us(0);//200, 100, 50, 20, 10, 5, 2, 1,0 works, deleting the statement does not work +//I suspect it has to do with interrupt priorities rather than with delays if (status != 0) { LOG("ProcessDoneQueue status %02X %d\n",ep,status); @@ -595,19 +599,22 @@ switch (endpoint->CurrentState) { case Endpoint::SetupQueued: - if (endpoint->Length == 0) + if (endpoint->Length == 0){ Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Skip Data Phase - else + } else {//here is a potential deadlock + //printf("Deadlock Avoidance, ep=%02x, in=%d\n", ep, in);//with printf before transfer -> no deadlock Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued); // Setup is done, now Data + //printf("SetupQueued->DataQueued\n");//with printf after Transfer ->deadlock + } break; case Endpoint::DataQueued: if (endpoint->TDHead.CurrBufPtr) endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data; - if (ep == 0) + if (ep == 0){ Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Data is done, now Status, Control only - else + } else endpoint->CurrentState = Endpoint::Idle; break; @@ -909,10 +916,21 @@ head = _controller.CommunicationArea.DoneHead; // Writeback Done _controller.CommunicationArea.DoneHead = 0; } - LPC_USB->HcInterruptStatus = int_status; +// LPC_USB->HcInterruptStatus = int_status; - if (head) - _controller.ProcessDoneQueue(head); // TODO - low bit can be set BUGBUG + if (head){ + _controller.ProcessDoneQueue(head & ~1U); // TODO - low bit can be set BUGBUG + if (head & 1) { + int othercause = int_status ^ WritebackDoneHead; + printf("HcInterruptStatus = %08X\n", int_status); + } + } + else + int othercause = int_status; + LPC_USB->HcInterruptStatus = int_status; +//See page 435 of OHCI Specification +//if the LSb=1 int_status should be checked for other causes +//if the head=0 there are no TDs on the DoneQueue and int_status should be checked to see what caused this interrupt } //====================================================================================