Zoltan Hudak / USBHost-STM32F4

Dependents:   STM32F407VET6_USBHostMSD STM32F407VET6_USBHostMouse STM32F407VET6_USBHostKeyboard STM32F407VET6_USBHostMSD_1

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHALHost_F401RE.cpp Source File

USBHALHost_F401RE.cpp

00001 #if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE)||defined(TARGET_ARCH_MAX)
00002 #include "USBHALHost.h"
00003 #include <algorithm>
00004 
00005 #ifdef _USB_DBG
00006 extern RawSerial pc;
00007 //RawSerial pc(USBTX,USBRX);
00008 #include "mydebug.h"
00009 #define USB_DBG(...) do{pc.printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);pc.printf(__VA_ARGS__);pc.puts("\n");} while(0);
00010 #define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B)
00011 
00012 #else
00013 #define USB_DBG(...) while(0)
00014 #define USB_DBG_HEX(A,B) while(0)
00015 #endif
00016 
00017 #undef USB_TEST_ASSERT
00018 void usb_test_assert_internal(const char *expr, const char *file, int line);
00019 #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
00020 
00021 #define USB_TRACE1(A) while(0)
00022 
00023 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
00024 
00025 __IO bool attach_done = false;
00026 
00027 void delay_ms(uint32_t t)
00028 {
00029     HAL_Delay(t);
00030 }
00031 
00032 // usbh_conf.c
00033 extern HCD_HandleTypeDef hhcd_USB_OTG_FS;
00034 
00035 void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd)
00036 {  
00037   GPIO_InitTypeDef  GPIO_InitStruct;
00038   
00039   if(hhcd->Instance == USB_OTG_FS)
00040   {
00041     /* 
00042      * Configure USB FS GPIOs
00043      * PA11     ------> USB_OTG_FS_DM
00044      * PA12     ------> USB_OTG_FS_DP 
00045      */
00046     __HAL_RCC_GPIOA_CLK_ENABLE();
00047     
00048     GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
00049     GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
00050     GPIO_InitStruct.Pull = GPIO_NOPULL;
00051     GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
00052     GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
00053     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 
00054     
00055     /* Enable USB FS Clocks */ 
00056     __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
00057     
00058     /* Set USBFS Interrupt to the lowest priority */
00059     HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0);
00060     
00061     /* Enable USBFS Interrupt */
00062     HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
00063   } 
00064   
00065 }
00066 
00067 // stm32f4xx_it.c
00068 extern "C" {
00069 void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
00070 {
00071     USB_TRACE1(hhcd);
00072     attach_done = true;
00073 }
00074 
00075 } // extern "C"
00076 
00077 USBHALHost* USBHALHost::instHost;
00078 
00079 USBHALHost::USBHALHost() {
00080     instHost = this;
00081 }
00082 
00083 void USBHALHost::init() {
00084     hhcd_USB_OTG_FS.Instance = USB_OTG_FS;
00085     hhcd_USB_OTG_FS.Init.Host_channels = 8;
00086     hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL;
00087     hhcd_USB_OTG_FS.Init.dma_enable = DISABLE;
00088     hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED;
00089     hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
00090     hhcd_USB_OTG_FS.Init.low_power_enable = ENABLE;
00091     hhcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
00092     hhcd_USB_OTG_FS.Init.use_external_vbus = DISABLE;
00093 
00094     HAL_HCD_Init(&hhcd_USB_OTG_FS);
00095     HAL_HCD_Start(&hhcd_USB_OTG_FS);
00096 
00097     bool lowSpeed = wait_attach();
00098     delay_ms(200);
00099     HAL_HCD_ResetPort(&hhcd_USB_OTG_FS);
00100     delay_ms(100); // Wait for 100 ms after Reset
00101     addDevice(NULL, 0, lowSpeed);
00102 }
00103 
00104 bool USBHALHost::wait_attach() {
00105     Timer t;
00106     t.reset();
00107     t.start();
00108     while(!attach_done) {
00109         if (t.read_ms() > 5*1000) {
00110             t.reset();
00111             USB_INFO("Please attach USB device.");
00112         }
00113     }
00114     wait_ms(100);
00115     return HAL_HCD_GetCurrentSpeed(&hhcd_USB_OTG_FS) == USB_OTG_SPEED_LOW;
00116 }
00117 
00118 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
00119     const uint8_t ep_addr = 0x00;
00120     HC hc;
00121     USBDeviceConnected* dev = ep->getDevice();
00122     hc.Init(ep_addr, 
00123         dev->getAddress(),
00124         dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
00125         EP_TYPE_CTRL, ep->getSize());
00126 
00127     setup->wLength = wLength;
00128     hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP
00129     while(hc.GetURBState() == URB_IDLE);
00130 
00131     switch(hc.GetURBState()) {
00132         case URB_DONE:
00133             LastStatus = ACK;
00134             break;
00135         default:
00136             LastStatus = 0xff;
00137             break;
00138     }
00139     ep->setData01(DATA1);
00140     return 8;
00141 }
00142 
00143 int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
00144     switch(ep->getType()) {
00145         case CONTROL_ENDPOINT:
00146             return token_ctl_in(ep, data, size, retryLimit);
00147         case INTERRUPT_ENDPOINT:
00148             return token_int_in(ep, data, size);
00149         case BULK_ENDPOINT:
00150             return token_blk_in(ep, data, size, retryLimit);
00151     }
00152     return -1;
00153 }
00154 
00155 int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
00156     const uint8_t ep_addr = 0x80;
00157     HC hc;
00158     USBDeviceConnected* dev = ep->getDevice();
00159     hc.Init(ep_addr, 
00160         dev->getAddress(),
00161         dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
00162         EP_TYPE_CTRL, ep->getSize());
00163 
00164     hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
00165 
00166     hc.SubmitRequest(data, size);
00167     while(hc.GetURBState() == URB_IDLE);
00168 
00169     switch(hc.GetURBState()) {
00170         case URB_DONE:
00171             LastStatus = ACK;
00172             break;
00173         default:
00174             LastStatus = 0xff;
00175             return -1;
00176     }
00177     ep->toggleData01();
00178     return hc.GetXferCount();
00179 }
00180 
00181 int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) {
00182     HC hc;
00183     USBDeviceConnected* dev = ep->getDevice();
00184     hc.Init(
00185         ep->getAddress(),
00186         dev->getAddress(),
00187         dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
00188         EP_TYPE_INTR, ep->getSize());
00189 
00190     hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
00191 
00192     hc.SubmitRequest(data, size);
00193     //while(hc.GetURBState() == URB_IDLE);
00194     wait_ms(2);
00195     switch(hc.GetURBState()) {
00196         case URB_DONE:
00197             switch(hc.GetState()) {
00198                 case HC_XFRC:
00199                     LastStatus = ep->getData01();
00200                     ep->toggleData01();
00201                     return hc.GetXferCount();
00202                 case HC_NAK:
00203                     LastStatus = NAK;
00204                     return -1;
00205             }
00206             break;
00207     }
00208     LastStatus = STALL;
00209     return -1;
00210 }
00211 
00212 int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
00213     HC hc;
00214     USBDeviceConnected* dev = ep->getDevice();
00215     hc.Init(
00216         ep->getAddress(),
00217         dev->getAddress(),
00218         HCD_SPEED_FULL,
00219         EP_TYPE_BULK, ep->getSize());
00220 
00221     hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
00222 
00223     int retry = 0;
00224     do {
00225         hc.SubmitRequest(data, size);
00226         while(hc.GetURBState() == URB_IDLE);
00227 
00228         switch(hc.GetURBState()) {
00229             case URB_DONE:
00230                 switch(hc.GetState()) {
00231                     case HC_XFRC:
00232                         LastStatus = ep->getData01();
00233                         ep->toggleData01();
00234                         return hc.GetXferCount();
00235                     case HC_NAK:
00236                         LastStatus = NAK;
00237                         if (retryLimit > 0) {
00238                             delay_ms(1 + 10 * retry);
00239                         }
00240                         break;
00241                     default:
00242                         break;
00243                 }
00244                 break;
00245             case URB_STALL:
00246                 LastStatus = STALL;
00247                 return -1;
00248             default:
00249                 LastStatus = STALL;
00250                 delay_ms(500 + 100 * retry);
00251                 break;
00252         }
00253     }while(retry++ < retryLimit);
00254     return -1;
00255 }
00256 
00257 int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
00258     switch(ep->getType()) {
00259         case CONTROL_ENDPOINT:
00260             return token_ctl_out(ep, data, size, retryLimit);
00261         case INTERRUPT_ENDPOINT:
00262             return token_int_out(ep, data, size);
00263         case BULK_ENDPOINT:
00264             return token_blk_out(ep, data, size, retryLimit);
00265     }
00266     return -1;
00267 }
00268 
00269 int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
00270     const uint8_t ep_addr = 0x00;
00271     HC hc;
00272     USBDeviceConnected* dev = ep->getDevice();
00273     hc.Init(ep_addr, 
00274         dev->getAddress(),
00275         dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
00276         EP_TYPE_CTRL, ep->getSize());
00277 
00278     hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
00279 
00280     do {
00281         hc.SubmitRequest((uint8_t*)data, size);
00282         while(hc.GetURBState() == URB_IDLE);
00283 
00284         switch(hc.GetURBState()) {
00285             case URB_DONE:
00286                 LastStatus = ACK;
00287                 ep->toggleData01();
00288                 return size;
00289 
00290             default:
00291                 break;
00292         }
00293         delay_ms(1);
00294     }while(retryLimit-- > 0); 
00295     return -1;
00296 }
00297 
00298 int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) {
00299     HC hc;
00300     USBDeviceConnected* dev = ep->getDevice();
00301     hc.Init(
00302         ep->getAddress(),
00303         dev->getAddress(),
00304         dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
00305         EP_TYPE_INTR, ep->getSize());
00306 
00307     hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
00308 
00309     hc.SubmitRequest((uint8_t*)data, size);
00310     while(hc.GetURBState() == URB_IDLE);
00311     if (hc.GetURBState() != URB_DONE) {
00312         return -1;
00313     }
00314     ep->toggleData01();
00315     return size;
00316 }
00317 
00318 int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
00319     HC hc;
00320     USBDeviceConnected* dev = ep->getDevice();
00321     hc.Init(
00322         ep->getAddress(), dev->getAddress(),
00323         HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize());
00324 
00325     hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
00326 
00327     int retry = 0;
00328     do {
00329         hc.SubmitRequest((uint8_t*)data, size);
00330         while(hc.GetURBState() == URB_IDLE);
00331 
00332         switch(hc.GetURBState()) {
00333             case URB_DONE:
00334                 switch(hc.GetState()) {
00335                     case HC_XFRC: // ACK
00336                         LastStatus = ep->getData01();
00337                         ep->toggleData01();
00338                         return size;
00339                     default:
00340                         break;
00341                 }
00342                 break;
00343             case URB_NOTREADY: // HC_NAK
00344                 LastStatus = NAK;
00345                 delay_ms(100 * retry);
00346                 break;
00347             default:
00348                 LastStatus = STALL;
00349                 return -1;
00350         }
00351     } while(retry++ < retryLimit);
00352     return -1;
00353 }
00354 
00355 int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
00356     HC* hc = ep->getHALData<HC*>();
00357     if (hc == NULL) {
00358         hc = new HC;
00359         ep->setHALData<HC*>(hc);
00360         USBDeviceConnected* dev = ep->getDevice();
00361         hc->Init(
00362             ep->getAddress(), dev->getAddress(),
00363             HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize());
00364     }
00365     hc->SubmitRequest(data, size);
00366     while(hc->GetURBState() == URB_IDLE);
00367     return hc->GetXferCount();
00368 }
00369 
00370 int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block) {
00371     if (total == 0) {
00372         return token_in(ep);
00373     }
00374     int retryLimit = block ? 10 : 0;
00375     int read_len = 0;
00376     for(int n = 0; read_len < total; n++) {
00377         int size = std::min((int)total-read_len, ep->getSize());
00378         int result = token_in(ep, data+read_len, size, retryLimit);
00379         if (result < 0) {
00380             if (block) {
00381                 return -1;
00382             }
00383             if (LastStatus == NAK) {
00384                 if (n == 0) {
00385                     return -1;
00386                 }
00387                 break;
00388             }
00389             return result;
00390         }
00391         read_len += result;
00392         if (result < ep->getSize()) {
00393             break;
00394         }
00395     }
00396     return read_len;
00397 }
00398 
00399 int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) {
00400     if (total == 0) {
00401         return token_out(ep);
00402     }
00403     int write_len = 0;
00404     for(int n = 0; write_len < total; n++) {
00405         int size = std::min((int)total-write_len, ep->getSize());
00406         int result = token_out(ep, data+write_len, size);
00407         if (result < 0) {
00408             if (LastStatus == NAK) {
00409                 if (n == 0) {
00410                     return -1;
00411                 }
00412                 break;
00413             }
00414             USB_DBG("token_out result=%d %02x", result, LastStatus);
00415             return result;
00416         }
00417         write_len += result;
00418         if (result < ep->getSize()) {
00419             break;
00420         }
00421     }
00422     return write_len;
00423 }
00424 void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
00425     USB_TRACE1(size);
00426     USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING);
00427     ep->setBuffer(data, size);
00428     ep->setState(USB_TYPE_PROCESSING);
00429 }
00430 
00431 USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) {
00432     USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING);
00433     uint8_t* buf = ep->getBufStart();
00434     int size = ep->getBufSize();
00435     int result = multi_token_in(ep, buf, size, false);
00436     USB_TRACE1(result);
00437     if (result < 0) {
00438         return USB_TYPE_PROCESSING;
00439     }
00440     ep->setLengthTransferred(result);
00441     ep->setState(USB_TYPE_IDLE);
00442     return USB_TYPE_OK;
00443 
00444 }
00445 
00446 void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) {
00447     USB_TEST_ASSERT(toggle == 1);
00448     ep->setData01(toggle == 0 ? DATA0 : DATA1);
00449 }
00450 
00451 uint8_t HC::slot = 0x00;
00452 
00453 HC::HC() {
00454     static const int start = 1;
00455     uint8_t mask = (1<<start);
00456     for(int i = start; i < 8; i++, mask <<= 1) {
00457         if (!(slot & mask)) {
00458             slot |= mask;
00459             _ch = i;
00460             return;
00461         }
00462     }
00463     _ch = 0; // ERROR!!!
00464 }
00465 
00466 HC::HC(int ch) {
00467     _ch = ch;
00468     slot |= (1<<_ch);
00469 }
00470 
00471 HC::~HC() {
00472     slot &= ~(1<<_ch);
00473 }
00474 
00475 HAL_StatusTypeDef HC::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) {
00476     _ep_addr = epnum;
00477     _ep_type = ep_type;
00478     return HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, _ch,
00479                            epnum, dev_address, speed, ep_type, mps);
00480 }
00481 
00482 HAL_StatusTypeDef HC::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup) {
00483     uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT;
00484     if (_ep_type == EP_TYPE_CTRL) {
00485         HCD_HCTypeDef* hc = &hhcd_USB_OTG_FS.hc[_ch];
00486         if (setup) {
00487             hc->data_pid = HC_PID_SETUP;
00488             hc->toggle_out = 0;
00489         } else {
00490             if (direction == DIR_IN) {
00491                 if (hc->toggle_in == 0) {
00492                     hc->data_pid = HC_PID_DATA0;
00493                 } else {
00494                     hc->data_pid = HC_PID_DATA1;
00495                 }
00496             } else { // OUT
00497                 if (hc->toggle_out == 0) {
00498                     hc->data_pid = HC_PID_DATA0;
00499                 } else {
00500                     hc->data_pid = HC_PID_DATA1;
00501                 }
00502             }
00503         }
00504         hc->xfer_buff = pbuff;
00505         hc->xfer_len  = length;
00506         hc->urb_state = URB_IDLE;
00507         hc->xfer_count = 0;
00508         hc->ch_num = _ch;
00509         hc->state = HC_IDLE;
00510   
00511         return USB_HC_StartXfer(hhcd_USB_OTG_FS.Instance, hc, 0);
00512     }
00513     return HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, _ch,
00514                                     direction, _ep_type, 0, pbuff, length, 0);
00515 }
00516 
00517 HCD_URBStateTypeDef HC::GetURBState() {
00518     return HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, _ch);
00519 }
00520 
00521 HCD_HCStateTypeDef HC::GetState() {
00522     return HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, _ch);
00523 }
00524 
00525 uint32_t HC::GetXferCount() {
00526     return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, _ch);
00527 }
00528 
00529 void HC::SetToggle(uint8_t toggle) {
00530     if (_ep_addr & 0x80) { // IN
00531         hhcd_USB_OTG_FS.hc[_ch].toggle_in = toggle;
00532     } else { // OUT
00533         hhcd_USB_OTG_FS.hc[_ch].toggle_out = toggle;
00534     }
00535 }
00536 
00537 #endif
00538 
00539