Support Isochronous transfer additionally

Dependents:   USBHostC270_example_GR-PEACH USBHostDac_example USBHostDac_Audio_in_out

Fork of USBHost_custom by Renesas

Committer:
HinoNaka
Date:
Fri Apr 21 07:23:33 2017 +0000
Revision:
41:5c3ebf7372ee
Support Isochronous transfer

Who changed what in which revision?

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