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

簡易USBホストライブラリです。
official-USBHostの下位互換で対応プログラムを僅かな修正で動かすことが出来ます。

Platforms

  • Nucleo F446RE
  • Nucleo F411RE
  • Nucleo F401RE
  • FRDM-K64F
  • FRDM-KL46Z
  • FRDM-KL25Z
  • LPC4088
  • LPC1768

Nucleo F446RE/F411RE/F401REのUSB接続方法

ST morphoUSB
U5V (CN10-8)VBUS (1 RED)
PA11 (CN10-14)DM  (2 WHITE)
PA12 (CN10-12)DP  (3 GREEN)
GND (CN10-20)GND (4 BLACK)

Examples

Import programF446RE-USBHostMouse_HelloWorld

USBHostMouse Hello World for ST-Nucleo-F446RE

Import programF401RE-USBHostMSD_HelloWorld

Simple USBHost MSD(USB flash drive) for Nucleo F401RE/FRDM-KL46Z test program

Import programF401RE-USBHostC270_example

Simple USBHost WebCam test program

Import programK64F_USBHostC270_example

Simple USBHost C270 example

Import programF401RE-BTstack_example

BTstack for Nucleo F401RE/FRDM-KL46Z example program

Import programUSBHostRSSI_example

Bluetooth device discovery example program.

Import programKL46Z-USBHostGPS_HelloWorld

Simple USBHost GPS Dongle Receiver for FRDM-KL46Z test program

Revision:
2:0cdac6bcc534
Parent:
1:c072d9e580b0
--- a/USBHost.cpp	Tue Jan 21 08:59:28 2014 +0000
+++ b/USBHost.cpp	Thu Jan 23 08:32:54 2014 +0000
@@ -19,39 +19,6 @@
 #define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
 #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
 
-#define BD_OWN_MASK        (1<<7)
-#define BD_DATA01_MASK     (1<<6)
-#define BD_KEEP_MASK       (1<<5)
-#define BD_NINC_MASK       (1<<4)
-#define BD_DTS_MASK        (1<<3)
-#define BD_STALL_MASK      (1<<2)
-
-#define TX    1
-#define RX    0
-
-#define EP0_BDT_IDX(dir, odd) (((2 * dir) + (1 * odd)))
-
-#define SETUP_TOKEN    0x0D
-#define IN_TOKEN       0x09
-#define OUT_TOKEN      0x01
-
-// for each endpt: 8 bytes
-struct BDT {
-    uint8_t   info;       // BD[0:7]
-    uint8_t   dummy;      // RSVD: BD[8:15]
-    uint16_t  byte_count; // BD[16:32]
-    uint32_t  address;    // Addr
-    void setBuffer(uint8_t* buf, int size) {
-        address = (uint32_t)buf;
-        byte_count = size;
-    }
-    uint8_t getStatus() {
-        return (info>>2)&0x0f;
-    }    
-};
-
-__attribute__((__aligned__(512))) BDT bdt[64];
-
 USBHost* USBHost::inst = NULL;
 
 USBHost* USBHost::getHostInst()
@@ -64,89 +31,9 @@
 }
 
 USBHost::USBHost() {
-    inst = this;
-    memset(rx_data01, DATA1, sizeof(rx_data01));
-    memset(tx_data01, DATA1, sizeof(tx_data01));
 }
 
-void USBHost::init() {
-    // Disable IRQ
-    NVIC_DisableIRQ(USB0_IRQn);
-
-    // choose usb src as PLL
-    SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK);
-
-    // enable OTG clock
-    SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
-
-    // USB Module Configuration
-    // Reset USB Module
-    USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
-    while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
-
-    // Clear interrupt flag
-    USB0->ISTAT = 0xff;
-
-    // Set BDT Base Register
-    USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8);
-    USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16);
-    USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24);
-
-    // Set SOF threshold
-    USB0->SOFTHLD = USB_SOFTHLD_CNT(1);
-
-    // pulldown D+ and D-
-    USB0->USBCTRL = USB_USBCTRL_PDE_MASK;
-
-    USB0->USBTRC0 |= 0x40;
-
-    // Host mode
-    USB0->CTL |= USB_CTL_HOSTMODEEN_MASK;
-    // Desable SOF packet generation
-    USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
-
-    NVIC_SetVector(USB0_IRQn, (uint32_t)_usbisr);
-    NVIC_EnableIRQ(USB0_IRQn);
-
-    wait_attach();
-
-    for(int retry = 2; retry > 0; retry--) {
-        // Enable RESET
-        USB0->CTL |= USB_CTL_RESET_MASK;
-        wait_ms(500);
-        USB0->CTL &= ~USB_CTL_RESET_MASK;
-    
-        // Enable SOF
-        USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
-        wait_ms(100);
-
-        // token transfer initialize
-        tx_ptr = ODD;
-        rx_ptr = ODD;
-        USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK;
-
-        if (enumeration()) {
-            break;
-        }
-        USB_DBG("retry=%d", retry);
-        USB_TEST_ASSERT(retry > 1);
-    }
-}
-
-void USBHost::wait_attach() {
-    attach_done = false;
-    USB0->INTEN = USB_INTEN_ATTACHEN_MASK;
-    while(!attach_done);
-    wait_ms(100);
-    USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK);
-    lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true;
-    if (lowSpeed) { // low speed
-        USB0->ENDPOINT[0].ENDPT |= USB_ENDPT_HOSTWOHUB_MASK;
-    }
-    USB_DBG("lowSpeed=%d", lowSpeed);
-}
-
-bool USBHost::enumeration() {
+/* virtual */ bool USBHost::enumeration() {
     uint8_t desc[64];
     MaxPacketSize0 = 8;
     dev_addr = 0;
@@ -161,15 +48,14 @@
     USB_DBG_HEX(desc, result);
     MaxPacketSize0 = desc[7];
 
-    dev_addr = 1;
     SETUP_PACKET setup_set_address = {0x00, SET_ADDRESS, 1, 0, 0};
     result = ControlWrite(&setup_set_address);
     if (result < 0) {
         USB_DBG("result=%d %02x", result, LastStatus);
         return false;
     }
-    USB0->ADDR = (lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(dev_addr);
     wait_ms(100);
+    dev_addr = 1;
 
     result = ControlRead(&setup_get_descriptor, desc, sizeof(desc));
     if (result < 8) {
@@ -234,9 +120,10 @@
 }
 
 int USBHost::ControlRead(SETUP_PACKET* setup, uint8_t* data, int size) {
+    setAddr(dev_addr);
     token_setup(setup, size); // setup stage
-    USB_DBG("setup %02x", LastStatus);
-    if (LastStatus != ACK && lowSpeed == false) {
+    if (LastStatus != ACK) {
+        USB_DBG("setup %02x", LastStatus);
         return -1;
     }
     rx_data01[0] = DATA1;
@@ -244,11 +131,9 @@
     while(read_len < size) {
         int size2 = std::min(size-read_len, MaxPacketSize0);
         int result = token_in(0, data+read_len, size2);
-        USB_DBG("token_in result=%d %02x", result, LastStatus);
+        //USB_DBG("token_in result=%d %02x", result, LastStatus);
         if (result < 0) {
-            if (LastStatus == NAK || LastStatus == Bus_Timeout) {
-                break;
-            }
+            USB_DBG("token_in %d/%d %02x", read_len, size, LastStatus);
             return result;
         }
         read_len += result;
@@ -269,9 +154,13 @@
 }
 
 int USBHost::ControlWrite(SETUP_PACKET* setup, uint8_t* data, int size) {
-    if (token_setup(setup, size) != ACK) { // setup stage
+    setAddr(dev_addr);
+    token_setup(setup, size); // setup stage
+    if (LastStatus != ACK) {
+        USB_DBG("setup %02x", LastStatus);
         return -1;
     }
+
     tx_data01[0] = DATA1;
     int write_len = 0;
     if (data != NULL) {
@@ -289,19 +178,15 @@
 }
 
 int USBHost::InterruptRead(uint8_t* data, int size) {
-    USB0->ISTAT = 0xff;
-    USB0->ENDPOINT[0].ENDPT = (lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) |
-                              USB_ENDPT_EPCTLDIS_MASK|
-                              USB_ENDPT_EPRXEN_MASK|
-                              USB_ENDPT_EPHSHK_MASK;
-    return token_in(ep_int_in & 0x7f, data, size);
+    setAddr(dev_addr);
+    setEndpoint();
+    const int retryLimit = 0;
+    return token_in(ep_int_in & 0x7f, data, size, retryLimit);
 }
 
 int USBHost::BulkRead(uint8_t* data, int size) {
-    token_ready();
-    USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPCTLDIS_MASK|
-                              USB_ENDPT_EPRXEN_MASK|
-                              USB_ENDPT_EPHSHK_MASK;
+    setAddr(dev_addr);
+    setEndpoint();
     const int max_packet_size = 64;
     int read_len = 0;
     while(read_len < size) {
@@ -320,10 +205,8 @@
 }
 
 int USBHost::BulkWrite(const uint8_t* data, int size) {
-    token_ready();
-    USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPCTLDIS_MASK|
-                              USB_ENDPT_EPTXEN_MASK|
-                              USB_ENDPT_EPHSHK_MASK;
+    setAddr(dev_addr);
+    setEndpoint();
     const int max_packet_size = 64;
     int write_len = 0;
     while(write_len < size) {
@@ -341,108 +224,3 @@
     return write_len;
 }
 
-int USBHost::token_setup(SETUP_PACKET* setup, uint16_t wLength) {
-    token_ready();
-    USB0->ENDPOINT[0].ENDPT = (lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) |
-                              USB_ENDPT_EPRXEN_MASK|
-                              USB_ENDPT_EPTXEN_MASK|
-                              USB_ENDPT_EPHSHK_MASK;
-    int idx = EP0_BDT_IDX(TX, tx_ptr);
-    bdt[idx].info = BD_OWN_MASK |
-                    BD_DTS_MASK; // always data0
-    setup->wLength = wLength;
-    bdt[idx].setBuffer((uint8_t*)setup, sizeof(SETUP_PACKET));
-    CTASSERT(sizeof(SETUP_PACKET) == 8);
-    token_done = false;
-    USB0->TOKEN = USB_TOKEN_TOKENPID(SETUP_TOKEN)|USB_TOKEN_TOKENENDPT(0);
-    while(!token_done);
-    LastStatus = bdt[idx].getStatus();
-    return LastStatus;
-}
-
-int USBHost::token_in(uint8_t ep, uint8_t* data, int size) {
-    USB_TEST_ASSERT(ep < sizeof(rx_data01));
-    token_ready();
-    int idx = EP0_BDT_IDX(RX, rx_ptr);
-    bdt[idx].info = BD_OWN_MASK|
-                    BD_DTS_MASK|
-                    ((rx_data01[ep] == DATA1) ? BD_DATA01_MASK : 0);
-    bdt[idx].setBuffer(data, size);
-    token_done = false;
-    USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)|USB_TOKEN_TOKENENDPT(ep);
-    while(!token_done);
-    LastStatus = bdt[idx].getStatus();
-    if (LastStatus == DATA0) {
-        rx_data01[ep] = DATA1;
-    } else if (LastStatus == DATA1) {
-        rx_data01[ep] = DATA0;
-    } else {
-        return -1;
-    }
-    return bdt[idx].byte_count;
-}
-
-int USBHost::token_out(uint8_t ep, const uint8_t* data, int size) {
-    USB_TEST_ASSERT(ep < sizeof(tx_data01));
-    token_ready();
-    int idx = EP0_BDT_IDX(TX, tx_ptr);
-    bdt[idx].info = BD_OWN_MASK|
-                    BD_DTS_MASK|
-                   ((tx_data01[ep] == DATA1) ? BD_DATA01_MASK : 0);
-    bdt[idx].setBuffer((uint8_t*)data, size);
-    token_done = false;
-    USB0->TOKEN = USB_TOKEN_TOKENPID(OUT_TOKEN)|USB_TOKEN_TOKENENDPT(ep);
-    while(!token_done);
-    LastStatus = bdt[idx].getStatus();
-    if (LastStatus == ACK) {
-        tx_data01[ep] = (tx_data01[ep] == DATA0) ? DATA1 : DATA0;
-        return bdt[idx].byte_count;
-    }
-    return -1;
-}
-
-void USBHost::token_ready() {
-    while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) { // TOKEN_BUSY ?
-        wait_ms(1);
-    }
-    USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF
-    while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK));
-    USB0->SOFTHLD = 0; // this is needed as without this you can get errors
-    USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF
-}
-
-void USBHost::_usbisr(void) {
-    if (inst) {
-        inst->UsbIrqhandler();
-    }
-}
-
-void USBHost::UsbIrqhandler() {
-    uint8_t istat = USB0->ISTAT;
-    if (istat & USB_ISTAT_TOKDNE_MASK) {
-        uint8_t stat = USB0->STAT;
-        ODD_EVEN next_ptr = (stat & USB_STAT_ODD_MASK) ? ODD : EVEN;
-        if (stat & USB_STAT_TX_MASK) {
-            tx_ptr = next_ptr;
-        } else {
-            rx_ptr = next_ptr;
-        }
-        token_done = true;
-    }
-    if (istat & USB_ISTAT_ATTACH_MASK) {
-        USB0->INTEN &= ~USB_INTEN_ATTACHEN_MASK;
-        attach_done = true;
-    }
-    USB0->ISTAT = istat; // clear
-}
-
-void debug_hex(uint8_t* buf, int size) {
-    for(int i = 0; i < size; i++) {
-        fprintf(stderr, "%02x ", buf[i]);
-        if (i%16 == 15) {
-            fprintf(stderr, "\r\n");
-        }
-    }
-    fprintf(stderr, "\r\n");
-}
-