Usb read

Dependencies:   FATFileSystem

Fork of F401RE-USBHost by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHALHost_KL46Z.cpp Source File

USBHALHost_KL46Z.cpp

00001 // Simple USBHost for FRDM-KL46Z
00002 #if defined(TARGET_KL46Z)||defined(TARGET_KL25Z)
00003 #include "USBHALHost_KL46Z.h"
00004 
00005 template <bool>struct CtAssert;
00006 template <>struct CtAssert<true> {};
00007 #define CTASSERT(A) CtAssert<A>();
00008 
00009 
00010 #ifdef _USB_DBG
00011 #define USB_DBG(...) do{fprintf(stderr,"[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");} while(0);
00012 #define USB_DBG_HEX(A,B) debug_hex(A,B)
00013 void debug_hex(uint8_t* buf, int size);
00014 #else
00015 #define USB_DBG(...) while(0)
00016 #define USB_DBG_HEX(A,B) while(0)
00017 #endif
00018 
00019 #ifdef _USB_TEST
00020 #define USB_TEST_ASSERT(A) while(!(A)){fprintf(stderr,"\n\n%s@%d %s ASSERT!\n\n",__PRETTY_FUNCTION__,__LINE__,#A);exit(1);};
00021 #define USB_TEST_ASSERT_FALSE(A) USB_TEST_ASSERT(!(A))
00022 #else
00023 #define USB_TEST_ASSERT(A) while(0)
00024 #define USB_TEST_ASSERT_FALSE(A) while(0)
00025 #endif
00026 
00027 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
00028 
00029 #define BD_OWN_MASK        (1<<7)
00030 #define BD_DATA01_MASK     (1<<6)
00031 #define BD_KEEP_MASK       (1<<5)
00032 #define BD_NINC_MASK       (1<<4)
00033 #define BD_DTS_MASK        (1<<3)
00034 #define BD_STALL_MASK      (1<<2)
00035 
00036 #define TX    1
00037 #define RX    0
00038 
00039 #define EP0_BDT_IDX(dir, odd) (((2 * dir) + (1 * odd)))
00040 
00041 #define SETUP_TOKEN    0x0D
00042 #define IN_TOKEN       0x09
00043 #define OUT_TOKEN      0x01
00044 
00045 // for each endpt: 8 bytes
00046 struct BDT {
00047     uint8_t   info;       // BD[0:7]
00048     uint8_t   dummy;      // RSVD: BD[8:15]
00049     uint16_t  byte_count; // BD[16:32]
00050     uint32_t  address;    // Addr
00051     void setBuffer(uint8_t* buf, int size) {
00052         address = (uint32_t)buf;
00053         byte_count = size;
00054     }
00055     uint8_t getStatus() {
00056         return (info>>2)&0x0f;
00057     }    
00058 };
00059 
00060 __attribute__((__aligned__(512))) BDT bdt[64];
00061 
00062 USBHALHost* USBHALHost::instHost;
00063 
00064 USBHALHost::USBHALHost() {
00065     instHost = this;
00066     report.clear();
00067 }
00068 
00069 void USBHALHost::init() {
00070     // Disable IRQ
00071     NVIC_DisableIRQ(USB0_IRQn);
00072 
00073     // choose usb src as PLL
00074     SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK);
00075 
00076     // enable OTG clock
00077     SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
00078 
00079     // USB Module Configuration
00080     // Reset USB Module
00081     USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
00082     while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
00083 
00084     // Clear interrupt flag
00085     USB0->ISTAT = 0xff;
00086 
00087     // Set BDT Base Register
00088     USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8);
00089     USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16);
00090     USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24);
00091 
00092     // Set SOF threshold
00093     USB0->SOFTHLD = USB_SOFTHLD_CNT(1);
00094 
00095     // pulldown D+ and D-
00096     USB0->USBCTRL = USB_USBCTRL_PDE_MASK;
00097 
00098     USB0->USBTRC0 |= 0x40;
00099 
00100     // Host mode
00101     USB0->CTL |= USB_CTL_HOSTMODEEN_MASK;
00102     // Desable SOF packet generation
00103     USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
00104 
00105     NVIC_SetVector(USB0_IRQn, (uint32_t)_usbisr);
00106     NVIC_EnableIRQ(USB0_IRQn);
00107 
00108     bool lowSpeed = wait_attach();
00109 
00110     for(int retry = 2; retry > 0; retry--) {
00111         // Enable RESET
00112         USB0->CTL |= USB_CTL_RESET_MASK;
00113         wait_ms(500);
00114         USB0->CTL &= ~USB_CTL_RESET_MASK;
00115     
00116         // Enable SOF
00117         USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
00118         wait_ms(100);
00119 
00120         // token transfer initialize
00121         token_transfer_init();
00122 
00123         USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK|
00124                        USB_INTEN_ERROREN_MASK;
00125         USB0->ERREN |= USB_ERREN_PIDERREN_MASK|
00126                        USB_ERREN_CRC5EOFEN_MASK|
00127                        USB_ERREN_CRC16EN_MASK|
00128                        USB_ERREN_DFN8EN_MASK|
00129                        USB_ERREN_BTOERREN_MASK|
00130                        USB_ERREN_DMAERREN_MASK|
00131                        USB_ERREN_BTSERREN_MASK;
00132 
00133         if (addDevice(NULL, 0, lowSpeed)) {
00134             break;
00135         }
00136         USB_DBG("retry=%d", retry);
00137         USB_TEST_ASSERT(retry > 1);
00138     }
00139 }
00140 
00141 bool USBHALHost::wait_attach() {
00142     attach_done = false;
00143     USB0->INTEN = USB_INTEN_ATTACHEN_MASK;
00144     Timer t;
00145     t.reset();
00146     t.start();
00147     while(!attach_done) {
00148         if (t.read_ms() > 5*1000) {
00149             t.reset();
00150             USB_INFO("Please attach USB device.");
00151         }
00152     }
00153     wait_ms(100);
00154     USB_TEST_ASSERT_FALSE(USB0->CTL & USB_CTL_SE0_MASK);
00155     root_lowSpeed = (USB0->CTL & USB_CTL_JSTATE_MASK) ? false : true;
00156     return root_lowSpeed;
00157 }
00158 
00159 void USBHALHost::setAddr(int _addr, bool _lowSpeed) {
00160     USB0->ADDR = (_lowSpeed ? USB_ADDR_LSEN_MASK : 0x00) | USB_ADDR_ADDR(_addr);
00161 }
00162 
00163 void USBHALHost::setEndpoint() {
00164     USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00)|
00165                               USB_ENDPT_RETRYDIS_MASK|
00166                               USB_ENDPT_EPCTLDIS_MASK|
00167                               USB_ENDPT_EPRXEN_MASK|
00168                               USB_ENDPT_EPTXEN_MASK|
00169                               USB_ENDPT_EPHSHK_MASK;
00170 }
00171 
00172 void USBHALHost::token_transfer_init() {
00173     tx_ptr = ODD;
00174     rx_ptr = ODD;
00175 }
00176 
00177 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
00178     USBDeviceConnected* dev = ep->getDevice();
00179     for(int retry = 0;; retry++) {
00180         token_ready();
00181         USB0->ENDPOINT[0].ENDPT = (root_lowSpeed ? USB_ENDPT_HOSTWOHUB_MASK : 0x00) |
00182                                   USB_ENDPT_RETRYDIS_MASK|
00183                                   USB_ENDPT_EPRXEN_MASK|
00184                                   USB_ENDPT_EPTXEN_MASK|
00185                                   USB_ENDPT_EPHSHK_MASK;
00186         CTASSERT(sizeof(SETUP_PACKET) == 8);
00187         setup->wLength = wLength;
00188         int idx = EP0_BDT_IDX(TX, tx_ptr);
00189         bdt[idx].setBuffer((uint8_t*)setup, sizeof(SETUP_PACKET));
00190         bdt[idx].info = BD_OWN_MASK |
00191                         BD_DTS_MASK; // always data0
00192         token_done = false;
00193         USB0->TOKEN = USB_TOKEN_TOKENPID(SETUP_TOKEN)|
00194                       USB_TOKEN_TOKENENDPT(ep->getAddress() & 0x7f);
00195         while(!token_done);
00196         LastStatus = bdt[idx].getStatus();
00197         if (LastStatus == ACK) {
00198             if (retry > 0) {
00199                 USB_DBG("retry=%d %02x", retry, prev_LastStatus);
00200             }
00201             break;
00202         } else if (LastStatus == STALL) {
00203             report.stall++;
00204             return STALL;
00205         }
00206         if (retry > 10) {
00207             USB_DBG("retry=%d", retry);
00208             break;
00209         }
00210         prev_LastStatus = LastStatus;
00211         wait_ms(100 * retry);
00212     }
00213     ep->setData01(DATA1); // next toggle
00214     return LastStatus;
00215 }
00216 
00217 int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
00218     for(int retry = 0;; retry++) {
00219         token_ready();
00220         int idx = EP0_BDT_IDX(RX, rx_ptr);
00221         bdt[idx].setBuffer(data, size);
00222         bdt[idx].info = BD_OWN_MASK|
00223                         BD_DTS_MASK|
00224                         (ep->getData01() == DATA1 ? BD_DATA01_MASK : 0);
00225         token_done = false;
00226         USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)|
00227                       USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f);
00228         while(!token_done);
00229         LastStatus = bdt[idx].getStatus();
00230         int len = bdt[idx].byte_count;
00231         if (LastStatus == DATA0 || LastStatus == DATA1) {
00232             USB_TEST_ASSERT(ep->getData01() == LastStatus);
00233             ep->setData01(LastStatus == DATA0 ? DATA1 : DATA0);
00234             if (retry > 0) {
00235                 //USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus);
00236             }
00237             return len;
00238         } else if (LastStatus == STALL) {
00239             report.stall++;
00240             return -1;
00241         } else if (LastStatus == NAK) {
00242             report.nak++;
00243             if (retry >= retryLimit) {
00244                 if (retryLimit > 0) {
00245                     USB_DBG("retry=%d retryLimit=%d", retry, retryLimit);
00246                 }
00247                 return -1;
00248             }
00249             wait_ms(100 * retry);
00250         } else if (LastStatus == Bus_Timeout) {
00251             if (retry >= retryLimit) {
00252                 if (retryLimit > 0) {
00253                     USB_DBG("Bus_Timeout retry=%d retryLimit=%d", retry, retryLimit);
00254                 }                
00255                 return -1;
00256             }
00257             wait_ms(500 + 100 * retry);
00258         } else {
00259             return -1;
00260         }
00261         prev_LastStatus = LastStatus;
00262     }
00263 }
00264 
00265 int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
00266     for(int retry = 0;; retry++) {
00267         token_ready();
00268         int idx = EP0_BDT_IDX(TX, tx_ptr);
00269         bdt[idx].setBuffer((uint8_t*)data, size);
00270         bdt[idx].info = BD_OWN_MASK|
00271                         BD_DTS_MASK|
00272                        (ep->getData01() == DATA1 ? BD_DATA01_MASK : 0);
00273         token_done = false;
00274         USB0->TOKEN = USB_TOKEN_TOKENPID(OUT_TOKEN)|
00275                       USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f);
00276         while(!token_done);
00277         LastStatus = bdt[idx].getStatus();
00278         int len = bdt[idx].byte_count;
00279         //USB_DBG("len=%d %02x", len, LastStatus);
00280         if (LastStatus == ACK) {
00281             ep->toggleData01();
00282             if (retry > 0) {
00283                 USB_DBG("len=%d retry=%d %02x", len, retry, prev_LastStatus);
00284             }
00285             return len;
00286         } else if (LastStatus == STALL) {
00287             report.stall++;
00288             return -1;
00289         } else if (LastStatus == NAK) {
00290             report.nak++;
00291             if (retry > retryLimit) {
00292                 USB_DBG("retry=%d retryLimit=%d", retry, retryLimit);
00293                 return -1;
00294             }
00295             wait_ms(100 * retry);
00296         } else {
00297             return -1;
00298         }
00299         prev_LastStatus = LastStatus;
00300     }
00301 }
00302 
00303 int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
00304     while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK); // TOKEN_BUSY ?
00305     USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF
00306     while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK));
00307     USB0->SOFTHLD = 0; // this is needed as without this you can get errors
00308     USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF
00309 
00310     USB0->ENDPOINT[0].ENDPT = USB_ENDPT_EPCTLDIS_MASK|
00311                               USB_ENDPT_RETRYDIS_MASK|
00312                               USB_ENDPT_EPRXEN_MASK|
00313                               USB_ENDPT_EPTXEN_MASK;
00314     int idx = EP0_BDT_IDX(RX, rx_ptr);
00315     bdt[idx].setBuffer(data, size);
00316     bdt[idx].info = BD_OWN_MASK|
00317                     BD_DTS_MASK; // always DATA0
00318     token_done = false;
00319     USB0->TOKEN = USB_TOKEN_TOKENPID(IN_TOKEN)|
00320                   USB_TOKEN_TOKENENDPT(ep->getAddress()&0x7f);
00321     while(!token_done);
00322     LastStatus = bdt[idx].getStatus();
00323     int len = bdt[idx].byte_count;
00324     if (LastStatus == DATA0) {
00325         return len;
00326     }
00327     return -1;
00328 }
00329 
00330 void USBHALHost::token_ready() {
00331     while(USB0->CTL & USB_CTL_TXSUSPENDTOKENBUSY_MASK) { // TOKEN_BUSY ?
00332         wait_ms(1);
00333     }
00334     USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // Clear SOF
00335     while (!(USB0->ISTAT & USB_ISTAT_SOFTOK_MASK));
00336     USB0->SOFTHLD = 0; // this is needed as without this you can get errors
00337     USB0->ISTAT |= USB_ISTAT_SOFTOK_MASK; // clear SOF
00338 }
00339 
00340 void USBHALHost::_usbisr(void) {
00341     if (instHost) {
00342         instHost->UsbIrqhandler();
00343     }
00344 }
00345 
00346 void USBHALHost::UsbIrqhandler() {
00347     if (USB0->ISTAT & USB_ISTAT_TOKDNE_MASK) {
00348         uint8_t stat = USB0->STAT;
00349         ODD_EVEN next_ptr = (stat & USB_STAT_ODD_MASK) ? ODD : EVEN;
00350         if (stat & USB_STAT_TX_MASK) {
00351             tx_ptr = next_ptr;
00352         } else {
00353             rx_ptr = next_ptr;
00354         }
00355         USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
00356         token_done = true;
00357     }
00358     if (USB0->ISTAT & USB_ISTAT_ATTACH_MASK) {
00359         USB0->INTEN &= ~USB_INTEN_ATTACHEN_MASK;
00360         USB0->ISTAT = USB_ISTAT_ATTACH_MASK;
00361         attach_done = true;
00362     }
00363     if (USB0->ISTAT & USB_ISTAT_ERROR_MASK) {
00364         uint8_t errstat = USB0->ERRSTAT;
00365         if (errstat & USB_ERRSTAT_PIDERR_MASK) {
00366             report.errstat_piderr++;
00367         }
00368         if (errstat & USB_ERRSTAT_CRC5EOF_MASK) {
00369             report.errstat_crc5eof++;
00370         }
00371         if (errstat & USB_ERRSTAT_CRC16_MASK) {
00372             report.errstat_crc16++;
00373         }
00374         if (errstat & USB_ERRSTAT_DFN8_MASK) {
00375             report.errstat_dfn8++;
00376         }
00377         if (errstat & USB_ERRSTAT_BTOERR_MASK) {
00378             report.errstat_btoerr++;
00379         }
00380         if (errstat & USB_ERRSTAT_DMAERR_MASK) {
00381             report.errstat_dmaerr++;
00382         }
00383         if (errstat & USB_ERRSTAT_BTSERR_MASK) {
00384             report.errstat_btoerr++;
00385         }
00386         USB0->ERRSTAT = errstat;
00387         USB0->ISTAT = USB_ISTAT_ERROR_MASK;
00388     }
00389 }
00390 
00391 void Report::clear() {
00392     errstat_piderr = 0;
00393     errstat_crc5eof = 0;
00394     errstat_crc16 = 0;
00395     errstat_dfn8 = 0;
00396     errstat_btoerr = 0;
00397     errstat_dmaerr = 0;
00398     errstat_bsterr = 0;
00399     //
00400     nak = 0;
00401 }
00402 
00403 void Report::print_errstat() {
00404     printf("ERRSTAT PID: %d, CRC5EOF: %d, CRC16: %d, DFN8: %d, BTO: %d, DMA: %d, BST: %d\n",
00405         errstat_piderr, errstat_crc5eof,
00406         errstat_crc16, errstat_dfn8,
00407         errstat_btoerr, errstat_dmaerr, errstat_bsterr);
00408 }
00409 
00410 void debug_hex(uint8_t* buf, int size) {
00411     int n = 0;
00412     for(int i = 0; i < size; i++) {
00413         fprintf(stderr, "%02x ", buf[i]);
00414         if (++n >= 16) {
00415             fprintf(stderr, "\n");
00416             n = 0;
00417         }
00418     }
00419     if (n > 0) {
00420         fprintf(stderr, "\n");
00421     }
00422 }
00423 
00424 #endif
00425 
00426