doku newon / DokuUSBHostWithIso

Dependencies:   FATFileSystem mbed-rtos

Dependents:   Peach_AudioChannelDividerAndCompensator

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBIsochronous.h Source File

USBIsochronous.h

00001 // USBIsochronous.h
00002 #pragma once
00003 #if !defined (__CC_ARM) && (!defined (_POSIX_C_SOURCE) || (_POSIX_C_SOURCE < 200112L))
00004 #include <malloc.h>
00005 #endif
00006 
00007 class IsochronousEp;
00008 struct HCITD {    // HostController Isochronous Transfer Descriptor
00009     __IO uint32_t Control;      // +0 Transfer descriptor control
00010     uint8_t*  BufferPage0;      // +4 Buffer Page 0
00011     HCITD* Next;                // +8 Physical pointer to next Isochronous Transfer Descriptor
00012     uint8_t*  BufferEnd;        // +12 buffer End
00013     __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW
00014     IsochronousEp* ep;          // +32 endpoint object
00015     __IO uint8_t buf[0];        // +36 buffer
00016                                 // +36
00017     HCITD(IsochronousEp* obj, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize);
00018 
00019     inline void* operator new(size_t size, int buf_size) {
00020         void* p;
00021 //      uint32_t addr;
00022 #if !defined (__CC_ARM) && (!defined (_POSIX_C_SOURCE) || (_POSIX_C_SOURCE < 200112L))
00023         // バッファ先頭アドレスは、下位12ビットが0となっていると好都合
00024         // アイソクロナスパケットが小さい間は問題が無いが、大きくなると、異常を生じる様子。
00025         // 獲得されるメモリアドレスは時によるので、運がよければ動作するが、12ビットアラインにすれば、確実に動くように思われる
00026         //p = memalign(32, size+buf_size);というオリジナルの記述では下位4ビットしか0になってない。
00027         p = memalign(0x1000, size+buf_size);
00028         return p;
00029 #else
00030         // バッファ先頭アドレスは、下位12ビットが0となっていると好都合
00031         //p = posix_memalign(&p, 32, size+buf_size);というオリジナルの記述では下位4ビットしか0になってない。
00032         if (posix_memalign(&p, 0x1000, size+buf_size) == 0) {
00033         //if (posix_memalign(&p, 32, size+buf_size) == 0) {
00034             return p;
00035         }
00036         return NULL;
00037 #endif
00038     }
00039 
00040 //    inline void* operator new(size_t size, int buf_size) {
00041 //        void* p;
00042 //#if !defined (__CC_ARM) && (!defined (_POSIX_C_SOURCE) || (_POSIX_C_SOURCE < 200112L))
00043 //        p = memalign(32, size+buf_size);
00044 //        return p;
00045 //#else
00046 //        if (posix_memalign(&p, 32, size+buf_size) == 0) {
00047 //            return p;
00048 //        }
00049 //        return NULL;
00050 //#endif
00051 //    }
00052 
00053     inline void operator delete(void* p) {
00054         free(p);
00055     }
00056 
00057     inline uint16_t StartingFrame() {
00058         return Control & 0xffff;
00059     }
00060 
00061     inline void SetStartingFrame(uint16_t FrameNumber) {
00062         Control = (Control & 0xffff0000) | FrameNumber;
00063     }
00064 
00065     inline uint8_t FrameCount() {
00066         return ((Control>>24)&7)+1;
00067     }    
00068 
00069     inline uint8_t ConditionCode() {
00070         return Control>>28;
00071     }
00072 };
00073 
00074 struct _HCED {    // HostController EndPoint Descriptor
00075     __IO uint32_t Control; // +0 Endpoint descriptor control
00076     HCTD* TailTd;          // +4 Physical address of tail in Transfer descriptor list
00077     __IO HCTD* HeadTd;     // +8 Physcial address of head in Transfer descriptor list
00078     _HCED* Next;           // +12 Physical address of next Endpoint descriptor
00079                            // +16
00080     _HCED(int addr, uint8_t ep, uint16_t size, int lowSpeed = 0) {
00081         Control =  addr            | /* USB address */
00082         ((ep & 0x7F) << 7)         | /* Endpoint address */
00083         (ep!=0?(((ep&0x80)?2:1) << 11):0)| /* direction : Out = 1, 2 = In */
00084         ((lowSpeed?1:0) << 13)     | /* speed full=0 low=1 */
00085         (size << 16);                /* MaxPkt Size */
00086         Next = NULL;
00087     }
00088 
00089     inline void* operator new(size_t size) {
00090         void* p;
00091 #if !defined (__CC_ARM) && (!defined (_POSIX_C_SOURCE) || (_POSIX_C_SOURCE < 200112L))
00092         p = memalign(16, size);
00093         return p;
00094 #else
00095         if (posix_memalign(&p, 16, size) == 0) {
00096             return p;
00097         }
00098         return NULL;
00099 #endif
00100     }
00101 
00102     inline void operator delete(void* p) {
00103         free(p);
00104     }
00105 
00106     inline uint8_t FunctionAddress() {
00107         return Control & 0x7f;
00108     }
00109 
00110     inline int Speed() {
00111         return (Control>>13)&1;
00112     }
00113 
00114     inline void setFunctionAddress(int addr) {
00115         Control &= ~0x7f;
00116         Control |= addr;
00117     }
00118 
00119     inline void setMaxPacketSize(uint16_t size) {
00120         Control &= ~0xffff0000;
00121         Control |= size<<16;
00122     }
00123 
00124     int Skip() {
00125         return (Control>>14) & 1;
00126     }
00127 
00128     void setSkip() {
00129         Control |= (1<<14);
00130     }
00131 
00132     void setFormat() {
00133         Control |= (1<<15);
00134     }
00135 
00136     template<typename T>
00137     inline bool enqueue(T* td) {
00138         if (td) {
00139             T* tail = reinterpret_cast<T*>(TailTd);
00140             if (tail) {
00141                 tail->Next = td;
00142                 TailTd = reinterpret_cast<HCTD*>(td);
00143                 return true;
00144             }
00145         }
00146         return false;
00147     }
00148 
00149     template<typename T>
00150     inline T* dequeue() {
00151         T* head = reinterpret_cast<T*>(reinterpret_cast<uint32_t>(HeadTd)&~3); // delete Halted and Toggle Carry bit
00152         T* tail = reinterpret_cast<T*>(TailTd);
00153         if (head == NULL || tail == NULL || head == tail) {
00154             return NULL;
00155         }
00156         HeadTd = reinterpret_cast<HCTD*>(head->Next);
00157         return head;
00158     }
00159     template<typename T>
00160     void init_queue(T* td) {
00161         TailTd = reinterpret_cast<HCTD*>(td);
00162         HeadTd = reinterpret_cast<HCTD*>(td); 
00163     }
00164 };
00165 
00166 struct _HCCA {    // Host Controller Communication Area
00167     _HCED* InterruptTable[32]; // +0 Interrupt Table
00168     __IO uint16_t FrameNumber;// +128 Frame Number
00169     __IO uint16_t Pad1;       // +130
00170     __IO HCTD* DoneHead;      // +132 Done Head
00171     uint8_t Reserved[116];    // +136 Reserved for future use
00172     uint8_t Unknown[4];       // +252 Unused
00173                               // +256
00174     inline void* operator new(size_t size) {
00175         void* p;
00176 #if !defined (__CC_ARM) && (!defined (_POSIX_C_SOURCE) || (_POSIX_C_SOURCE < 200112L))
00177         p = memalign(256, size);
00178         return p;
00179 #else
00180         if (posix_memalign(&p, 256, size) == 0) {
00181             return p;
00182         }
00183         return NULL;
00184 #endif
00185     }
00186 
00187     inline void operator delete(void* p) {
00188         free(p);
00189     }
00190     
00191     inline void enqueue(_HCED* ed) {
00192         for(int i = 0; i < 32; i++) {
00193             if (InterruptTable[i] == NULL) {
00194                 InterruptTable[i] = ed;
00195             } else {
00196                 _HCED* nextEd = InterruptTable[i];
00197                 while(nextEd->Next && nextEd->Next != ed) {
00198                     nextEd = nextEd->Next;
00199                 }
00200                 nextEd->Next = ed;
00201             }
00202         }
00203     }
00204     
00205     inline void dequeue(_HCED* ed) {
00206          for(int i = 0; i < 32; i++) {
00207             if (InterruptTable[i] == ed) {
00208                 InterruptTable[i] = ed->Next;
00209             } else if (InterruptTable[i]) {
00210                 _HCED* nextEd = InterruptTable[i];
00211                 while(nextEd) {
00212                     if (nextEd->Next == ed) {
00213                         nextEd->Next = ed->Next;
00214                         break;
00215                     }
00216                     nextEd = nextEd->Next;
00217                 }
00218             }
00219          }
00220     }
00221 };
00222 
00223 //doku #define HCITD_QUEUE_SIZE 3
00224 #define HCITD_QUEUE_SIZE 11
00225 
00226 class IsochronousEp {
00227 public:
00228     void init(int addr, uint8_t ep, uint16_t size, uint8_t frameCount = 4, uint8_t queueLimit = HCITD_QUEUE_SIZE);
00229     void reset(int delay_ms = 100);
00230     HCITD* isochronousReceive(int timeout_ms);
00231     int isochronousSend(uint8_t* buf, int len, int timeout_ms);
00232     HCITD* get_queue_HCITD(int timeout_ms);
00233     uint16_t m_PacketSize;
00234     void disconnect();
00235     void irqWdhHandler(HCITD* itd) {m_queue.put(itd);} // WDH
00236     int getQueueNum() {return m_itd_queue_count;}
00237 private:
00238     HCITD* new_HCITD(IsochronousEp* obj);
00239     Queue<HCITD, HCITD_QUEUE_SIZE> m_queue; // ITD done queue
00240     int m_itd_queue_count;
00241     int m_itd_queue_limit;
00242     uint16_t m_FrameNumber;
00243     int m_FrameCount; // 1-8
00244     void enable();
00245     _HCED* m_pED;
00246 };