see: http://mbed.org/users/okini3939/notebook/wifi_webcam/
Dependencies: GSwifiInterface_ap_webcam USBHost mbed
USBHostC270/USBisochronous/USBIsochronous.cpp@0:8558bdecb0fa, 2014-06-06 (annotated)
- Committer:
- okini3939
- Date:
- Fri Jun 06 00:44:06 2014 +0000
- Revision:
- 0:8558bdecb0fa
1st build
Who changed what in which revision?
User | Revision | Line number | New 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 | } |