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