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