Simple USBHost library for Nucleo F446RE/F411RE/F401RE FRDM-KL46Z/KL25Z/F64F LPC4088/LPC1768

Dependencies:   FATFileSystem

Dependents:   F401RE-BTstack_example F401RE-USBHostMSD_HelloWorld

Fork of KL46Z-USBHost by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHALHost_LPC4088.h Source File

USBHALHost_LPC4088.h

00001 /* mbed USBHost Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016  
00017 #pragma once
00018 #include "mbed.h"
00019 #include "rtos.h"
00020 #include "USBHostTypes.h"
00021 #include "USBEndpoint.h"
00022 
00023 #if defined(TARGET_LPC4088)
00024 #define HcRevision      Revision
00025 #define HcControl       Control
00026 #define HcCommandStatus CommandStatus
00027 #define HcInterruptStatus InterruptStatus
00028 #define HcInterruptEnable InterruptEnable
00029 #define HcHCCA          HCCA
00030 #define HcControlHeadED ControlHeadED
00031 #define HcBulkHeadED    BulkHeadED
00032 #define HcFmInterval    FmInterval
00033 #define HcFmNumber      FmNumber
00034 #define HcPeriodicStart PeriodicStart
00035 #define HcRhStatus      RhStatus
00036 #define HcRhPortStatus1 RhPortStatus1
00037 #define OTGStCtrl       StCtrl
00038 #endif
00039 // ------------------ HcControl Register ---------------------
00040 #define  OR_CONTROL_PLE                 0x00000004
00041 #define  OR_CONTROL_IE                  0x00000008
00042 #define  OR_CONTROL_CLE                 0x00000010
00043 #define  OR_CONTROL_BLE                 0x00000020
00044 #define  OR_CONTROL_HCFS                0x000000C0
00045 #define  OR_CONTROL_HC_OPER             0x00000080
00046 // ----------------- HcCommandStatus Register -----------------
00047 #define  OR_CMD_STATUS_HCR              0x00000001
00048 #define  OR_CMD_STATUS_CLF              0x00000002
00049 #define  OR_CMD_STATUS_BLF              0x00000004
00050 // --------------- HcInterruptStatus Register -----------------
00051 #define  OR_INTR_STATUS_WDH             0x00000002
00052 #define  OR_INTR_STATUS_UE              0x00000010
00053 #define  OR_INTR_STATUS_FNO             0x00000020
00054 #define  OR_INTR_STATUS_RHSC            0x00000040
00055 // --------------- HcInterruptEnable Register -----------------
00056 #define  OR_INTR_ENABLE_WDH             0x00000002
00057 #define  OR_INTR_ENABLE_FNO             0x00000020
00058 #define  OR_INTR_ENABLE_RHSC            0x00000040
00059 #define  OR_INTR_ENABLE_MIE             0x80000000
00060 // ---------------- HcRhDescriptorA Register ------------------
00061 #define  OR_RH_STATUS_LPSC              0x00010000
00062 #define  OR_RH_STATUS_DRWE              0x00008000
00063 // -------------- HcRhPortStatus[1:NDP] Register --------------
00064 #define  OR_RH_PORT_CCS                 0x00000001
00065 #define  OR_RH_PORT_PRS                 0x00000010
00066 #define  OR_RH_PORT_LSDA                0x00000200
00067 #define  OR_RH_PORT_CSC                 0x00010000
00068 #define  OR_RH_PORT_PRSC                0x00100000
00069 
00070 // TRANSFER DESCRIPTOR CONTROL FIELDS
00071 #define  TD_ROUNDING     (uint32_t)(0x00040000) /* Buffer Rounding */
00072 #define  TD_SETUP        (uint32_t)(0x00000000) /* Direction of Setup Packet */
00073 #define  TD_IN           (uint32_t)(0x00100000) /* Direction In */
00074 #define  TD_OUT          (uint32_t)(0x00080000) /* Direction Out */
00075 #define  TD_DELAY_INT(x) (uint32_t)((x) << 21)  /* Delay Interrupt */
00076 #define  TD_DI           (uint32_t)(7<<21)      /* desable interrupt */
00077 #define  TD_TOGGLE_0     (uint32_t)(0x02000000) /* Toggle 0 */
00078 #define  TD_TOGGLE_1     (uint32_t)(0x03000000) /* Toggle 1 */
00079 #define  TD_CC           (uint32_t)(0xF0000000) /* Completion Code */
00080 
00081 void* usb_ram_malloc(size_t size, int aligment); // USBHALHost2_LPC4088.cpp
00082 void usb_ram_free(void* p);
00083 
00084 struct TBUF {
00085     uint8_t buf[0];
00086     TBUF(const void* data = NULL, int size = 0);
00087     void* operator new(size_t size, int buf_size) { return usb_ram_malloc(size+buf_size, 4); }
00088     void operator delete(void* p) { usb_ram_free(p); }
00089 };
00090 
00091 class HCED;
00092 
00093 struct HCTD {    // HostController Transfer Descriptor
00094     __IO uint32_t Control;    // +0 Transfer descriptor control
00095     __IO uint8_t* CurrBufPtr; // +4 Physical address of current buffer pointer
00096     HCTD* Next;               // +8 Physical pointer to next Transfer Descriptor
00097     uint8_t*  BufEnd;         // +12 Physical address of end of buffer
00098     uint8_t* buf_top;         // +16 Buffer start address
00099     uint16_t buf_size;        // +20 buffer size size
00100     uint8_t _dummy[10];       // +22 dummy
00101     HCED* parent;             // +32 HCED object
00102                               // +36
00103     HCTD(HCED* ed);
00104     void* operator new(size_t size) { return usb_ram_malloc(size, 16); }
00105     void operator delete(void* p) { usb_ram_free(p); }
00106 
00107     void transfer(TBUF* tbuf, int len) {
00108         CurrBufPtr = tbuf->buf;
00109         buf_top = tbuf->buf;
00110         buf_size = len;
00111         BufEnd = const_cast<uint8_t*>(tbuf->buf)+len-1;
00112     }
00113     int getLengthTransferred() {
00114         if (CurrBufPtr) {
00115             return CurrBufPtr - buf_top;
00116         }
00117         return buf_size;
00118     }
00119     int status() {
00120         if (CurrBufPtr) {
00121             return CurrBufPtr - buf_top;
00122         }
00123         return buf_size;
00124     }
00125     
00126     uint8_t ConditionCode() {
00127         return Control>>28;
00128     }    
00129 }; 
00130 
00131 struct HCITD {    // HostController Isochronous Transfer Descriptor
00132     __IO uint32_t Control;      // +0 Transfer descriptor control
00133     uint8_t*  BufferPage0;      // +4 Buffer Page 0
00134     HCITD* Next;                // +8 Physical pointer to next Isochronous Transfer Descriptor
00135     uint8_t*  BufferEnd;        // +12 buffer End
00136     __IO uint16_t OffsetPSW[8]; // +16 Offset/PSW
00137     HCED* parent;               // +32 HCED object
00138     __IO uint8_t buf[0];        // +36 buffer
00139                                 // +36
00140     HCITD(HCED* ed, uint16_t FrameNumber, int FrameCount, uint16_t PacketSize);
00141     uint8_t* Buffer(int fc);
00142     void* operator new(size_t size, int buf_size) { return usb_ram_malloc(size+buf_size, 32); }
00143     void operator delete(void* p) { usb_ram_free(p); }
00144 
00145     uint16_t StartingFrame() {
00146         return Control & 0xffff;
00147     }
00148 
00149     uint8_t FrameCount() {
00150         return ((Control>>24)&7)+1;
00151     }    
00152 
00153     uint8_t ConditionCode() {
00154         return Control>>28;
00155     }
00156 
00157     uint8_t ConditionCode(int fc) {
00158         uint16_t psw = OffsetPSW[fc];
00159         return psw>>12;
00160     }
00161 
00162     uint16_t Length(int fc) {
00163         uint16_t psw = OffsetPSW[fc];
00164         return psw & 0x7ff;
00165     }
00166 };
00167 
00168 #define HCTD_QUEUE_SIZE 3
00169 
00170 struct HCED {    // HostController EndPoint Descriptor
00171     __IO uint32_t Control; // +0 Endpoint descriptor control
00172     HCTD* TailTd;          // +4 Physical address of tail in Transfer descriptor list
00173     __IO HCTD* HeadTd;     // +8 Physcial address of head in Transfer descriptor list
00174     HCED* Next;            // +12 Physical address of next Endpoint descriptor
00175                            // +16
00176     uint8_t m_ConditionCode;
00177     Queue<HCTD, HCTD_QUEUE_SIZE> _done_queue; // TD done queue
00178     struct {
00179         uint8_t queue_count;
00180         uint8_t queue_limit;
00181         uint16_t FrameNumber;
00182         uint8_t FrameCount; // 1-8
00183         HCITD* Current_itd;
00184         uint8_t Current_FrameCount;
00185     } iso;
00186     inline osEvent done_queue_get(uint32_t millisec) { return _done_queue.get(millisec); }
00187     inline void irqWdhHandler(HCTD* td) {_done_queue.put(td);} // WDH
00188     HCTD* get_queue_HCTD(uint32_t millisec=osWaitForever);
00189     HCITD* get_queue_HCITD();
00190     HCITD* new_HCITD();
00191     HCED(USBEndpoint* ep);
00192     void* operator new(size_t size) { return usb_ram_malloc(size, 16); }
00193     void operator delete(void* p) { usb_ram_free(p); }
00194 
00195     uint8_t FunctionAddress() {
00196         return Control & 0x7f;
00197     }
00198 
00199     uint8_t EndpointNumber() {
00200         return (Control>>7) & 0x7f;
00201     }
00202 
00203     int Speed() {
00204         return (Control>>13)&1;
00205     }
00206 
00207     void setFunctionAddress(int addr) {
00208         Control &= ~0x7f;
00209         Control |= addr;
00210     }
00211 
00212     void setMaxPacketSize(uint16_t size) {
00213         Control &= ~0x07ff0000;
00214         Control |= size<<16;
00215     }
00216 
00217     uint16_t getMaxPacketSize() {
00218         return (Control>>16)&0x7ff;
00219     }
00220 
00221     void setToggle(uint8_t toggle);
00222     uint8_t getToggle();
00223 
00224     int Skip() {
00225         return (Control>>14) & 1;
00226     }
00227 
00228     void setSkip() {
00229         Control |= (1<<14);
00230     }
00231 
00232     void setFormat() {
00233         Control |= (1<<15);
00234     }
00235 
00236     bool enqueue(HCTD* td);
00237     void init_queue(HCTD* td);
00238 };
00239 
00240 struct HCCA {    // Host Controller Communication Area
00241     HCED* InterruptTable[32]; // +0 Interrupt Table
00242     __IO uint16_t FrameNumber;// +128 Frame Number
00243     __IO uint16_t Pad1;       // +130
00244     __IO HCTD* DoneHead;      // +132 Done Head
00245     uint8_t Reserved[116];    // +136 Reserved for future use
00246     uint8_t Unknown[4];       // +252 Unused
00247                               // +256
00248     void* operator new(size_t size) { return usb_ram_malloc(size, 256); }
00249     void operator delete(void* p) { usb_ram_free(p); }
00250     void enqueue(HCED* ed);
00251 };
00252 
00253 class USBHALHost {
00254 protected:
00255     USBHALHost();
00256     void init();
00257     virtual bool addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) = 0;
00258     int token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength = 0);
00259     int token_iso_in(USBEndpoint* ep, uint8_t* data, int size);
00260     int multi_token_in(USBEndpoint* ep, uint8_t* data = NULL, int size = 0);
00261     int multi_token_out(USBEndpoint* ep, const uint8_t* data = NULL, int size = 0);
00262     void multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size);
00263     USB_TYPE multi_token_inNB_result(USBEndpoint* ep);
00264     void setToggle(USBEndpoint* ep, uint8_t toggle);
00265 
00266     // report
00267     uint32_t m_report_irq; 
00268     uint32_t m_report_RHSC;
00269     uint32_t m_report_FNO; 
00270     uint32_t m_report_WDH;  
00271     uint32_t m_report_sp;
00272 
00273 private:
00274     void init_hw_ohci(HCCA* pHcca);
00275     void ResetRootHub();
00276     void token_init(USBEndpoint* ep);
00277     static void _usbisr(void);
00278     void UsbIrqhandler();
00279     HCCA* m_pHcca;
00280     bool wait_attach();
00281     bool root_lowSpeed;
00282     static USBHALHost * instHost;
00283 };
00284