Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: F401RE-USBHostMIDI_RecieveExample
Fork of F401RE-USBHost by
Diff: USBHost.cpp
- 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");
-}
-
