see: http://mbed.org/users/okini3939/notebook/wifi_webcam/

Dependencies:   GSwifiInterface_ap_webcam USBHost mbed

Committer:
okini3939
Date:
Fri Jun 06 00:44:06 2014 +0000
Revision:
0:8558bdecb0fa
1st build

Who changed what in which revision?

UserRevisionLine numberNew contents of line
okini3939 0:8558bdecb0fa 1 // USBIsochronous.cpp
okini3939 0:8558bdecb0fa 2 #include "USBHostConf.h"
okini3939 0:8558bdecb0fa 3 #include "USBHost.h"
okini3939 0:8558bdecb0fa 4 #include "USBIsochronous.h"
okini3939 0:8558bdecb0fa 5
okini3939 0:8558bdecb0fa 6 //#define ISO_DEBUG 1
okini3939 0:8558bdecb0fa 7 #ifdef ISO_DEBUG
okini3939 0:8558bdecb0fa 8 #define ISO_DBG(x, ...) std::printf("[%s:%d]"x"\r\n", __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
okini3939 0:8558bdecb0fa 9 #else
okini3939 0:8558bdecb0fa 10 #define ISO_DBG(...) while(0);
okini3939 0:8558bdecb0fa 11 #endif
okini3939 0:8558bdecb0fa 12
okini3939 0:8558bdecb0fa 13 #define TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
okini3939 0:8558bdecb0fa 14
okini3939 0:8558bdecb0fa 15 HCITD::HCITD(IsochronousEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize) {
okini3939 0:8558bdecb0fa 16 Control = 0xe0000000 | // CC ConditionCode NOT ACCESSED
okini3939 0:8558bdecb0fa 17 ((FrameCount-1) << 24)| // FC FrameCount
okini3939 0:8558bdecb0fa 18 TD_DELAY_INT(0) | // DI DelayInterrupt
okini3939 0:8558bdecb0fa 19 FrameNumber; // SF StartingFrame
okini3939 0:8558bdecb0fa 20 BufferPage0 = const_cast<uint8_t*>(buf);
okini3939 0:8558bdecb0fa 21 BufferEnd = const_cast<uint8_t*>(buf) + PacketSize * FrameCount - 1;
okini3939 0:8558bdecb0fa 22 Next = NULL;
okini3939 0:8558bdecb0fa 23 ep = obj;
okini3939 0:8558bdecb0fa 24 uint32_t addr = reinterpret_cast<uint32_t>(buf);
okini3939 0:8558bdecb0fa 25 for(int i = 0; i < FrameCount; i++) {
okini3939 0:8558bdecb0fa 26 uint16_t offset = addr & 0x0fff;
okini3939 0:8558bdecb0fa 27 if ((addr&0xfffff000) == (reinterpret_cast<uint32_t>(BufferEnd)&0xfffff000)) {
okini3939 0:8558bdecb0fa 28 offset |= 0x1000;
okini3939 0:8558bdecb0fa 29 }
okini3939 0:8558bdecb0fa 30 OffsetPSW[i] = 0xe000|offset;
okini3939 0:8558bdecb0fa 31 addr += PacketSize;
okini3939 0:8558bdecb0fa 32 }
okini3939 0:8558bdecb0fa 33 }
okini3939 0:8558bdecb0fa 34
okini3939 0:8558bdecb0fa 35 void IsochronousEp::init(int addr, uint8_t ep, uint16_t size, uint8_t frameCount, uint8_t queueLimit)
okini3939 0:8558bdecb0fa 36 {
okini3939 0:8558bdecb0fa 37 //ISO_DBG("%p FA:%d EP:%02X MPS:%d\n", this, addr, ep, size);
okini3939 0:8558bdecb0fa 38 TEST_ASSERT(addr >= 1);
okini3939 0:8558bdecb0fa 39 TEST_ASSERT(size >= 8 && size <= 1023);
okini3939 0:8558bdecb0fa 40 m_pED = new _HCED(addr, ep, size);
okini3939 0:8558bdecb0fa 41 TEST_ASSERT(m_pED);
okini3939 0:8558bdecb0fa 42
okini3939 0:8558bdecb0fa 43 m_pED->setFormat(); // F Format ITD
okini3939 0:8558bdecb0fa 44
okini3939 0:8558bdecb0fa 45 TEST_ASSERT(size >= 128 && size <= 1023);
okini3939 0:8558bdecb0fa 46 m_PacketSize = size;
okini3939 0:8558bdecb0fa 47 TEST_ASSERT(frameCount >= 1 && frameCount <= 8);
okini3939 0:8558bdecb0fa 48 m_FrameCount = frameCount;
okini3939 0:8558bdecb0fa 49 TEST_ASSERT(queueLimit >= 1 && queueLimit <= HCITD_QUEUE_SIZE);
okini3939 0:8558bdecb0fa 50 m_itd_queue_limit = queueLimit;
okini3939 0:8558bdecb0fa 51
okini3939 0:8558bdecb0fa 52 m_itd_queue_count = 0;
okini3939 0:8558bdecb0fa 53 reset();
okini3939 0:8558bdecb0fa 54 HCITD* itd = new_HCITD(this);
okini3939 0:8558bdecb0fa 55 m_pED->init_queue<HCITD>(itd);
okini3939 0:8558bdecb0fa 56 TEST_ASSERT(itd);
okini3939 0:8558bdecb0fa 57 if (itd == NULL) {
okini3939 0:8558bdecb0fa 58 return;
okini3939 0:8558bdecb0fa 59 }
okini3939 0:8558bdecb0fa 60 _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA);
okini3939 0:8558bdecb0fa 61 TEST_ASSERT(hcca);
okini3939 0:8558bdecb0fa 62 if (hcca == NULL) {
okini3939 0:8558bdecb0fa 63 return;
okini3939 0:8558bdecb0fa 64 }
okini3939 0:8558bdecb0fa 65 hcca->enqueue(m_pED);
okini3939 0:8558bdecb0fa 66 }
okini3939 0:8558bdecb0fa 67
okini3939 0:8558bdecb0fa 68 void IsochronousEp::reset(int delay_ms)
okini3939 0:8558bdecb0fa 69 {
okini3939 0:8558bdecb0fa 70 m_FrameNumber = LPC_USB->HcFmNumber + delay_ms;
okini3939 0:8558bdecb0fa 71 }
okini3939 0:8558bdecb0fa 72
okini3939 0:8558bdecb0fa 73 HCITD* IsochronousEp::new_HCITD(IsochronousEp* obj)
okini3939 0:8558bdecb0fa 74 {
okini3939 0:8558bdecb0fa 75 HCITD* itd = new(m_PacketSize*m_FrameCount)HCITD(obj, m_FrameNumber, m_FrameCount, m_PacketSize);
okini3939 0:8558bdecb0fa 76 if (itd == NULL) {
okini3939 0:8558bdecb0fa 77 return NULL;
okini3939 0:8558bdecb0fa 78 }
okini3939 0:8558bdecb0fa 79 m_FrameNumber += m_FrameCount;
okini3939 0:8558bdecb0fa 80 return itd;
okini3939 0:8558bdecb0fa 81 }
okini3939 0:8558bdecb0fa 82
okini3939 0:8558bdecb0fa 83 HCITD* IsochronousEp::isochronousReceive(int timeout_ms)
okini3939 0:8558bdecb0fa 84 {
okini3939 0:8558bdecb0fa 85 TEST_ASSERT(m_itd_queue_count >= 0);
okini3939 0:8558bdecb0fa 86 while(m_itd_queue_count < m_itd_queue_limit) {
okini3939 0:8558bdecb0fa 87 if (m_pED == NULL) {
okini3939 0:8558bdecb0fa 88 ISO_DBG("m_pED is NULL");
okini3939 0:8558bdecb0fa 89 break;
okini3939 0:8558bdecb0fa 90 }
okini3939 0:8558bdecb0fa 91 if (m_pED->Skip()) {
okini3939 0:8558bdecb0fa 92 break;
okini3939 0:8558bdecb0fa 93 }
okini3939 0:8558bdecb0fa 94 HCITD* blank_itd = new_HCITD(this);
okini3939 0:8558bdecb0fa 95 TEST_ASSERT(blank_itd);
okini3939 0:8558bdecb0fa 96 if (m_pED->enqueue<HCITD>(blank_itd)) {
okini3939 0:8558bdecb0fa 97 m_itd_queue_count++;
okini3939 0:8558bdecb0fa 98 }
okini3939 0:8558bdecb0fa 99 enable(); // Enable Periodic
okini3939 0:8558bdecb0fa 100 }
okini3939 0:8558bdecb0fa 101
okini3939 0:8558bdecb0fa 102 HCITD* itd = get_queue_HCITD(timeout_ms);
okini3939 0:8558bdecb0fa 103 if (itd) {
okini3939 0:8558bdecb0fa 104 m_itd_queue_count--;
okini3939 0:8558bdecb0fa 105 }
okini3939 0:8558bdecb0fa 106 return itd;
okini3939 0:8558bdecb0fa 107 }
okini3939 0:8558bdecb0fa 108
okini3939 0:8558bdecb0fa 109 int IsochronousEp::isochronousSend(uint8_t* buf, int len, int timeout_ms)
okini3939 0:8558bdecb0fa 110 {
okini3939 0:8558bdecb0fa 111 //ISO_DBG("buf: %p, len: %d", buf, len);
okini3939 0:8558bdecb0fa 112 HCITD* itd = get_queue_HCITD(timeout_ms);
okini3939 0:8558bdecb0fa 113 if (itd) {
okini3939 0:8558bdecb0fa 114 delete itd;
okini3939 0:8558bdecb0fa 115 m_itd_queue_count--;
okini3939 0:8558bdecb0fa 116 TEST_ASSERT(m_itd_queue_count >= 0);
okini3939 0:8558bdecb0fa 117 }
okini3939 0:8558bdecb0fa 118 TEST_ASSERT(m_itd_queue_count >= 0);
okini3939 0:8558bdecb0fa 119 if(m_itd_queue_count < m_itd_queue_limit) {
okini3939 0:8558bdecb0fa 120 if (m_pED == NULL) {
okini3939 0:8558bdecb0fa 121 ISO_DBG("m_pED is NULL");
okini3939 0:8558bdecb0fa 122 return 0;
okini3939 0:8558bdecb0fa 123 }
okini3939 0:8558bdecb0fa 124 if (m_pED->Skip()) {
okini3939 0:8558bdecb0fa 125 return 0;
okini3939 0:8558bdecb0fa 126 }
okini3939 0:8558bdecb0fa 127 itd = new_HCITD(this);
okini3939 0:8558bdecb0fa 128 TEST_ASSERT(itd);
okini3939 0:8558bdecb0fa 129 //ISO_DBG("m_pED: %p itd: %p", m_pED, itd);
okini3939 0:8558bdecb0fa 130 memcpy(const_cast<uint8_t*>(itd->buf), buf, len);
okini3939 0:8558bdecb0fa 131 if (m_pED->enqueue<HCITD>(itd)) {
okini3939 0:8558bdecb0fa 132 m_itd_queue_count++;
okini3939 0:8558bdecb0fa 133 }
okini3939 0:8558bdecb0fa 134 enable(); // Enable Periodic
okini3939 0:8558bdecb0fa 135 //ISO_DBG("m_itd_queue_count: %d", m_itd_queue_count);
okini3939 0:8558bdecb0fa 136 return len;
okini3939 0:8558bdecb0fa 137 }
okini3939 0:8558bdecb0fa 138 return 0;
okini3939 0:8558bdecb0fa 139 }
okini3939 0:8558bdecb0fa 140
okini3939 0:8558bdecb0fa 141 HCITD* IsochronousEp::get_queue_HCITD(int timeout_ms)
okini3939 0:8558bdecb0fa 142 {
okini3939 0:8558bdecb0fa 143 Timer t;
okini3939 0:8558bdecb0fa 144 t.reset();
okini3939 0:8558bdecb0fa 145 t.start();
okini3939 0:8558bdecb0fa 146 do {
okini3939 0:8558bdecb0fa 147 osEvent evt = m_queue.get(0);
okini3939 0:8558bdecb0fa 148 if (evt.status == osEventMessage) {
okini3939 0:8558bdecb0fa 149 HCITD* itd = reinterpret_cast<HCITD*>(evt.value.p);
okini3939 0:8558bdecb0fa 150 TEST_ASSERT(itd);
okini3939 0:8558bdecb0fa 151 return itd;
okini3939 0:8558bdecb0fa 152 } else if (evt.status == osOK) {
okini3939 0:8558bdecb0fa 153 ;
okini3939 0:8558bdecb0fa 154 } else if (evt.status == osEventTimeout) {
okini3939 0:8558bdecb0fa 155 break;
okini3939 0:8558bdecb0fa 156 } else {
okini3939 0:8558bdecb0fa 157 ISO_DBG("evt.status: %02x\n", evt.status);
okini3939 0:8558bdecb0fa 158 TEST_ASSERT(evt.status == osEventMessage);
okini3939 0:8558bdecb0fa 159 break;
okini3939 0:8558bdecb0fa 160 }
okini3939 0:8558bdecb0fa 161 } while(t.read_ms() < timeout_ms);
okini3939 0:8558bdecb0fa 162 return NULL;
okini3939 0:8558bdecb0fa 163 }
okini3939 0:8558bdecb0fa 164
okini3939 0:8558bdecb0fa 165 void IsochronousEp::enable()
okini3939 0:8558bdecb0fa 166 {
okini3939 0:8558bdecb0fa 167 LPC_USB->HcControl |= OR_CONTROL_PLE;
okini3939 0:8558bdecb0fa 168 }
okini3939 0:8558bdecb0fa 169
okini3939 0:8558bdecb0fa 170 void IsochronousEp::disconnect()
okini3939 0:8558bdecb0fa 171 {
okini3939 0:8558bdecb0fa 172 m_pED->setSkip(); // skip bit on
okini3939 0:8558bdecb0fa 173 ISO_DBG("rtos-queue: %d", m_itd_queue_count);
okini3939 0:8558bdecb0fa 174 int queue_count = m_itd_queue_count;
okini3939 0:8558bdecb0fa 175 Timer t;
okini3939 0:8558bdecb0fa 176 t.reset();
okini3939 0:8558bdecb0fa 177 t.start();
okini3939 0:8558bdecb0fa 178 do {
okini3939 0:8558bdecb0fa 179 HCITD* itd = get_queue_HCITD(10);
okini3939 0:8558bdecb0fa 180 if (itd) {
okini3939 0:8558bdecb0fa 181 ISO_DBG("delete ITD:%p from rtos-queue %d ms", itd, t.read_ms());
okini3939 0:8558bdecb0fa 182 delete itd;
okini3939 0:8558bdecb0fa 183 queue_count--;
okini3939 0:8558bdecb0fa 184 t.reset();
okini3939 0:8558bdecb0fa 185 }
okini3939 0:8558bdecb0fa 186 } while(t.read_ms() < 50);
okini3939 0:8558bdecb0fa 187 ISO_DBG("rtos-queue: %d, %d ms", queue_count, t.read_ms());
okini3939 0:8558bdecb0fa 188 TEST_ASSERT(queue_count >= 0);
okini3939 0:8558bdecb0fa 189 while(1) {
okini3939 0:8558bdecb0fa 190 HCITD* itd = m_pED->dequeue<HCITD>();
okini3939 0:8558bdecb0fa 191 if (itd == NULL) {
okini3939 0:8558bdecb0fa 192 break;
okini3939 0:8558bdecb0fa 193 }
okini3939 0:8558bdecb0fa 194 ISO_DBG("delete ITD:%p from ED(%p)-queue", itd, m_pED);
okini3939 0:8558bdecb0fa 195 delete itd;
okini3939 0:8558bdecb0fa 196 TEST_ASSERT(queue_count > 0);
okini3939 0:8558bdecb0fa 197 queue_count--;
okini3939 0:8558bdecb0fa 198 }
okini3939 0:8558bdecb0fa 199 TEST_ASSERT(queue_count == 0);
okini3939 0:8558bdecb0fa 200 HCITD* tail = reinterpret_cast<HCITD*>(m_pED->TailTd);
okini3939 0:8558bdecb0fa 201 ISO_DBG("delete ITD:%p from ED(%p)-tail", tail, m_pED);
okini3939 0:8558bdecb0fa 202 TEST_ASSERT(tail);
okini3939 0:8558bdecb0fa 203 delete tail;
okini3939 0:8558bdecb0fa 204 m_pED->init_queue<HCITD>(NULL);
okini3939 0:8558bdecb0fa 205
okini3939 0:8558bdecb0fa 206 _HCCA* hcca = reinterpret_cast<_HCCA*>(LPC_USB->HcHCCA);
okini3939 0:8558bdecb0fa 207 TEST_ASSERT(hcca);
okini3939 0:8558bdecb0fa 208 hcca->dequeue(m_pED);
okini3939 0:8558bdecb0fa 209 ISO_DBG("delete ED:%p", m_pED);
okini3939 0:8558bdecb0fa 210 delete m_pED;
okini3939 0:8558bdecb0fa 211 m_pED = NULL;
okini3939 0:8558bdecb0fa 212 }