Simple USBHost library for STM32F746NG Discovery board. Only either the Fastspeed or the Highspeed port can be used( not both together)
Dependents: DISCO-F746NG_USB_Host
Fork of KL46Z-USBHost by
USBHost/TARGET_STM32F7/USBHALHost_F746NG.cpp
- Committer:
- DieterGraef
- Date:
- 2016-06-13
- Revision:
- 24:5396b6a93262
- Child:
- 25:7d6d9fc471bf
File content as of revision 24:5396b6a93262:
#if defined(TARGET_DISCO_F746NG) #include "mbed.h" #include "stm32f7xx_hal.h" #include "USBHALHost.h" #include <algorithm> #include "USB_Helper.h" #ifdef _USB_DBG //extern RawSerial pc; //RawSerial pc(USBTX,USBRX); #include "mydebug.h" #define USB_DBG(...) do{printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);printf(__VA_ARGS__);printf("\n");} while(0); #define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B) #else #define USB_DBG(...) while(0) #define USB_DBG_HEX(A,B) while(0) #endif #undef USB_TEST_ASSERT void usb_test_assert_internal(const char *expr, const char *file, int line); #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);} #define USB_TRACE1(A) while(0) #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0); __IO bool attach_done = false; void delay_ms(uint32_t t) { wait_ms(t); } // usbh_conf.c //__attribute__((section(".dmatransfer"))); void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd) { GPIO_InitTypeDef GPIO_InitStruct; if(hhcd->Instance==USB_OTG_FS) { /* Configure USB FS GPIOs */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE(); GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12); GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* Configure POWER_SWITCH IO pin */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); /* Enable USB FS Clocks */ __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); } if(hhcd->Instance==USB_OTG_HS) { /* Peripheral clock enable */ __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); /* CLK */ GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* D0 */ GPIO_InitStruct.Pin = GPIO_PIN_3; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* D1 D2 D3 D4 D5 D6 D7 */ GPIO_InitStruct.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12 | GPIO_PIN_13; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* STP */ GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); /* NXT */ GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOH, &GPIO_InitStruct); /* DIR */ GPIO_InitStruct.Pin = GPIO_PIN_2; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Alternate = GPIO_AF10_OTG_HS; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); /* Enable USB HS Clocks */ __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); } } // stm32f4xx_it.c extern "C" { void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd) { //USB_TRACE1(hhcd); attach_done = true; } } // extern "C" USBHALHost* USBHALHost::instHost; USBHALHost::USBHALHost(int InterfaceNumber) { IF_N=InterfaceNumber; hhcd=&hhcd_USB; instHost = this; } void USBHALHost::init() { if(IF_N==USB_FastSpeed) { hhcd_USB.Instance = USB_OTG_FS; hhcd_USB.Init.Host_channels = 11; hhcd_USB.Init.dma_enable = 0; hhcd_USB.Init.low_power_enable = 0; hhcd_USB.Init.phy_itface = HCD_PHY_EMBEDDED; hhcd_USB.Init.Sof_enable = 1; hhcd_USB.Init.speed = HCD_SPEED_FULL; hhcd_USB.Init.vbus_sensing_enable = 0; hhcd_USB.Init.lpm_enable = 0; HAL_HCD_Init(&hhcd_USB); /* Peripheral interrupt init*/ /* Sets the priority grouping field */ NVIC_SetVector(OTG_FS_IRQn, (uint32_t)&_usbisr); HAL_NVIC_SetPriority(OTG_FS_IRQn, 6, 0); HAL_NVIC_EnableIRQ(OTG_FS_IRQn); HAL_HCD_Start(&hhcd_USB); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_5, GPIO_PIN_RESET); bool lowSpeed = wait_attach(); delay_ms(200); HAL_HCD_ResetPort(&hhcd_USB); delay_ms(100); // Wait for 100 ms after Reset addDevice(NULL, 0, lowSpeed); } if(IF_N==USB_HighSpeed) { hhcd_USB.Instance = USB_OTG_HS; hhcd_USB.Init.Host_channels = 8; hhcd_USB.Init.dma_enable = 1; hhcd_USB.Init.low_power_enable = 0; hhcd_USB.Init.phy_itface = HCD_PHY_ULPI; hhcd_USB.Init.Sof_enable = 1; hhcd_USB.Init.speed = HCD_SPEED_HIGH; hhcd_USB.Init.vbus_sensing_enable = 0; hhcd_USB.Init.use_external_vbus = 1; hhcd_USB.Init.lpm_enable = 0; HAL_HCD_Init(&hhcd_USB); NVIC_SetVector(OTG_HS_IRQn, (uint32_t)&_usbisr); HAL_NVIC_SetPriority(OTG_HS_IRQn, 6, 0); HAL_NVIC_EnableIRQ(OTG_HS_IRQn); HAL_HCD_Start(&hhcd_USB); bool lowSpeed = wait_attach(); delay_ms(200); HAL_HCD_ResetPort(&hhcd_USB); delay_ms(100); // Wait for 100 ms after Reset addDevice(NULL, 0, lowSpeed); } } bool USBHALHost::wait_attach() { Timer t; t.reset(); t.start(); while(!attach_done) { if (t.read_ms() > 5*1000) { t.reset(); USB_INFO("Please attach USB device."); } } wait_ms(100); return HAL_HCD_GetCurrentSpeed(&hhcd_USB) == USB_OTG_SPEED_LOW; } int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) { const uint8_t ep_addr = 0x00; HC hc(&hhcd_USB); HCD_URBStateTypeDef st; USBDeviceConnected* dev = ep->getDevice(); if(IF_N==USB_FastSpeed) { hc.Init(IF_N, ep_addr, dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, EP_TYPE_CTRL, ep->getSize()); } else { hc.Init(IF_N,ep_addr, dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH , EP_TYPE_CTRL, ep->getSize()); } setup->wLength = wLength; st=hc.GetURBState(); hc.SubmitRequest(IF_N,(uint8_t*)setup, 8, true); // PID_SETUP while(hc.GetURBState() == URB_IDLE); switch(hc.GetURBState()) { case URB_DONE: LastStatus = ACK; break; default: LastStatus = 0xff; break; } ep->setData01(DATA1); return 8; } int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); switch(ep->getType()) { case CONTROL_ENDPOINT: return token_ctl_in(ep, data, size, retryLimit); case INTERRUPT_ENDPOINT: return token_int_in(ep, data, size); case BULK_ENDPOINT: return token_blk_in(ep, data, size, retryLimit); } return -1; } int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { const uint8_t ep_addr = 0x80; HC hc(&hhcd_USB); HCD_URBStateTypeDef st; USBDeviceConnected* dev = ep->getDevice(); if(IF_N==USB_FastSpeed) { hc.Init(IF_N,ep_addr, dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, EP_TYPE_CTRL, ep->getSize()); } else { hc.Init(IF_N,ep_addr, dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH , EP_TYPE_CTRL, ep->getSize()); } hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); st=hc.GetURBState(); SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); wait_ms(1); hc.SubmitRequest(IF_N,data, size); while(hc.GetURBState() == URB_IDLE); CPU_CACHE_Flush((uint32_t *)data,size); st=hc.GetURBState(); switch(hc.GetURBState()) { case URB_DONE: LastStatus = ACK; break; default: LastStatus = 0xff; return -1; } ep->toggleData01(); return hc.GetXferCount(); } int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) { HC hc(&hhcd_USB); HCD_URBStateTypeDef st; USBDeviceConnected* dev = ep->getDevice(); if(IF_N==USB_FastSpeed) { hc.Init(IF_N,ep->getAddress(), dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, EP_TYPE_INTR, ep->getSize()); } else { hc.Init(IF_N,ep->getAddress(), dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH , EP_TYPE_INTR, ep->getSize()); } hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); st=hc.GetURBState(); SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); hc.SubmitRequest(IF_N,data, size); while(hc.GetURBState() == URB_IDLE); CPU_CACHE_Flush((uint32_t *)data,size); switch(hc.GetURBState()) { case URB_DONE: switch(hc.GetState()) { case HC_XFRC: LastStatus = ep->getData01(); ep->toggleData01(); return hc.GetXferCount(); case HC_NAK: LastStatus = NAK; return -1; } break; } LastStatus = STALL; return -1; } int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) { HC hc(&hhcd_USB); HCD_URBStateTypeDef st; USBDeviceConnected* dev = ep->getDevice(); if(IF_N==USB_FastSpeed) { hc.Init(IF_N, ep->getAddress(), dev->getAddress(), HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize()); } else { hc.Init(IF_N, ep->getAddress(), dev->getAddress(), HCD_SPEED_HIGH, EP_TYPE_BULK, ep->getSize()); } hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); int retry = 0; do { st=hc.GetURBState(); SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); hc.SubmitRequest(IF_N,data, size); while(hc.GetURBState() == URB_IDLE); CPU_CACHE_Flush((uint32_t *)data,size); st=hc.GetURBState(); switch(st) { case URB_DONE: switch(hc.GetState()) { case HC_XFRC: LastStatus = ep->getData01(); ep->toggleData01(); return hc.GetXferCount(); case HC_NAK: LastStatus = NAK; if (retryLimit > 0) { delay_ms(1 + 10 * retry); } break; default: break; } break; case URB_STALL: LastStatus = STALL; return -1; default: LastStatus = STALL; delay_ms(500 + 100 * retry); break; } } while(retry++ < retryLimit); return -1; } int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { CPU_CACHE_Flush((uint32_t *)data,size); SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); switch(ep->getType()) { case CONTROL_ENDPOINT: return token_ctl_out(ep, data, size, retryLimit); case INTERRUPT_ENDPOINT: return token_int_out(ep, data, size); case BULK_ENDPOINT: return token_blk_out(ep, data, size, retryLimit); } return -1; } int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { const uint8_t ep_addr = 0x00; HC hc(&hhcd_USB); HCD_URBStateTypeDef st; USBDeviceConnected* dev = ep->getDevice(); if(IF_N==USB_FastSpeed) { hc.Init(IF_N,ep_addr, dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, EP_TYPE_CTRL, ep->getSize()); } else { hc.Init(IF_N,ep_addr, dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH , EP_TYPE_CTRL, ep->getSize()); } hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); do { st=hc.GetURBState(); CPU_CACHE_Flush((uint32_t *)data,size); wait_ms(1); hc.SubmitRequest(IF_N,(uint8_t*)data, size); while(hc.GetURBState() == URB_IDLE); SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); switch(hc.GetURBState()) { case URB_DONE: LastStatus = ACK; ep->toggleData01(); return size; default: break; } delay_ms(1); } while(retryLimit-- > 0); return -1; } int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) { HC hc(&hhcd_USB); HCD_URBStateTypeDef st; USBDeviceConnected* dev = ep->getDevice(); if(IF_N==USB_FastSpeed) { hc.Init(IF_N, ep->getAddress(), dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL, EP_TYPE_INTR, ep->getSize()); } else { hc.Init(IF_N, ep->getAddress(), dev->getAddress(), dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_HIGH , EP_TYPE_INTR, ep->getSize()); } hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); st=hc.GetURBState(); CPU_CACHE_Flush((uint32_t *)data,size); hc.SubmitRequest(IF_N,(uint8_t*)data, size); while(hc.GetURBState() == URB_IDLE); SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); if (hc.GetURBState() != URB_DONE) { return -1; } ep->toggleData01(); return size; } int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) { HC hc(&hhcd_USB); HCD_URBStateTypeDef st; USBDeviceConnected* dev = ep->getDevice(); if(IF_N==USB_FastSpeed) { hc.Init(IF_N, ep->getAddress(), dev->getAddress(), HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize()); } else { hc.Init(IF_N, ep->getAddress(), dev->getAddress(), HCD_SPEED_HIGH, EP_TYPE_BULK, ep->getSize()); } hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1); int retry = 0; do { st=hc.GetURBState(); CPU_CACHE_Flush((uint32_t *)data,size); hc.SubmitRequest(IF_N,(uint8_t*)data, size); while(hc.GetURBState() == URB_IDLE); SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); switch(hc.GetURBState()) { case URB_DONE: switch(hc.GetState()) { case HC_XFRC: // ACK LastStatus = ep->getData01(); ep->toggleData01(); return size; default: break; } break; case URB_NOTREADY: // HC_NAK LastStatus = NAK; delay_ms(100 * retry); break; default: LastStatus = STALL; return -1; } } while(retry++ < retryLimit); return -1; } int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) { HCD_URBStateTypeDef st; HC* hc = ep->getHALData<HC*>(); if (hc == NULL) { hc = new HC(&hhcd_USB); ep->setHALData<HC*>(hc); USBDeviceConnected* dev = ep->getDevice(); if(IF_N==USB_FastSpeed) { hc->Init(IF_N, ep->getAddress(), dev->getAddress(), HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize()); } else { hc->Init(IF_N, ep->getAddress(), dev->getAddress(), HCD_SPEED_HIGH, EP_TYPE_ISOC, ep->getSize()); } } st=hc->GetURBState(); SCB_InvalidateDCache_by_Addr((uint32_t *)data,size); hc->SubmitRequest(IF_N,data, size); while(hc->GetURBState() == URB_IDLE); CPU_CACHE_Flush((uint32_t *)data,size); return hc->GetXferCount(); } int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block) { if (total == 0) { return token_in(ep); } int retryLimit = block ? 10 : 0; int read_len = 0; for(int n = 0; read_len < total; n++) { int size = std::min((int)total-read_len, ep->getSize()); int result = token_in(ep, data+read_len, size, retryLimit); if (result < 0) { if (block) { return -1; } if (LastStatus == NAK) { if (n == 0) { return -1; } break; } return result; } read_len += result; if (result < ep->getSize()) { break; } } return read_len; } int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) { if (total == 0) { return token_out(ep); } int write_len = 0; for(int n = 0; write_len < total; n++) { int size = std::min((int)total-write_len, ep->getSize()); int result = token_out(ep, data+write_len, size); if (result < 0) { if (LastStatus == NAK) { if (n == 0) { return -1; } break; } USB_DBG("token_out result=%d %02x", result, LastStatus); return result; } write_len += result; if (result < ep->getSize()) { break; } } return write_len; } void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) { //USB_TRACE1(size); //USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING); ep->setBuffer(data, size); ep->setState(USB_TYPE_PROCESSING); } USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) { //USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING); uint8_t* buf = ep->getBufStart(); int size = ep->getBufSize(); int result = multi_token_in(ep, buf, size, false); //USB_TRACE1(result); if (result < 0) { return USB_TYPE_PROCESSING; } ep->setLengthTransferred(result); ep->setState(USB_TYPE_IDLE); return USB_TYPE_OK; } void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) { //USB_TEST_ASSERT(toggle == 1); ep->setData01(toggle == 0 ? DATA0 : DATA1); } int USBHALHost::epint_setup(USBEndpoint* ep) { return 1; } void USBHALHost::_usbisr(void) { instHost->usbisr(); } void USBHALHost::usbisr(void) { USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; uint32_t i = 0 , interrupt = 0; /* ensure that we are in device mode */ if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST) { /* avoid spurious interrupt */ if(__HAL_HCD_IS_INVALID_INTERRUPT(hhcd)) { return; } if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT)) { /* incorrect mode, acknowledge the interrupt */ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT); } if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR)) { /* incorrect mode, acknowledge the interrupt */ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR); } if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE)) { /* incorrect mode, acknowledge the interrupt */ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE); } if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS)) { /* incorrect mode, acknowledge the interrupt */ __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS); } /* Handle Host Disconnect Interrupts */ if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT)) { /* Cleanup HPRT */ USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); /* Handle Host Port Interrupts */ HAL_HCD_Disconnect_Callback(hhcd); USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ ); __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT); } /* Handle Host Port Interrupts */ if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT)) { // USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; __IO uint32_t hprt0, hprt0_dup; /* Handle Host Port Interrupts */ hprt0 = USBx_HPRT0; hprt0_dup = USBx_HPRT0; hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); /* Check wether Port Connect Detected */ if((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET) { if((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS) { USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); HAL_HCD_Connect_Callback(hhcd); } hprt0_dup |= USB_OTG_HPRT_PCDET; } /* Check whether Port Enable Changed */ if((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG) { hprt0_dup |= USB_OTG_HPRT_PENCHNG; if((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA) { if(hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY) { if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17)) { USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_6_MHZ ); } else { USB_InitFSLSPClkSel(hhcd->Instance ,HCFG_48_MHZ ); } } else { if(hhcd->Init.speed == HCD_SPEED_FULL) { USBx_HOST->HFIR = (uint32_t)60000; } } HAL_HCD_Connect_Callback(hhcd); if(hhcd->Init.speed == HCD_SPEED_HIGH) { USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); } } else { /* Cleanup HPRT */ USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET |\ USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG ); USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT); } } /* Check For an overcurrent */ if((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG) { hprt0_dup |= USB_OTG_HPRT_POCCHNG; } /* Clear Port Interrupts */ USBx_HPRT0 = hprt0_dup; } // /* Handle Host SOF Interrupts */ if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF)) { HAL_HCD_SOF_Callback(hhcd); __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF); } /* Handle Host channel Interrupts */ if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT)) { interrupt = USB_HC_ReadInterrupt(hhcd->Instance); for (i = 0; i < hhcd->Init.Host_channels ; i++) { if (interrupt & (1 << i)) { if ((USBx_HC(i)->HCCHAR) & USB_OTG_HCCHAR_EPDIR) { // USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; uint8_t chnum = i; if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR) { __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR); __HAL_HCD_UNMASK_HALT_HC_INT(chnum); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK) { __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); hhcd->hc[chnum].state = HC_STALL; __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL); USB_HC_Halt(hhcd->Instance, chnum); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); hhcd->hc[chnum].state = HC_DATATGLERR; __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR); } if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC) { if (hhcd->Init.dma_enable) { hhcd->hc[chnum].xfer_count = hhcd->hc[chnum].xfer_len - \ (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ); } hhcd->hc[chnum].state = HC_XFRC; __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC); if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL)|| (hhcd->hc[chnum].ep_type == EP_TYPE_BULK)) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); } else if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR) { USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM; __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); } else if(hhcd->hc[chnum].ep_type == EP_TYPE_ISOC) { USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM; hhcd->hc[chnum].urb_state = URB_DONE; HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); } hhcd->hc[chnum].toggle_in ^= 1; } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH) { __HAL_HCD_MASK_HALT_HC_INT(chnum); if(hhcd->hc[chnum].state == HC_XFRC) { hhcd->hc[chnum].urb_state = URB_DONE; } else if (hhcd->hc[chnum].state == HC_NAK) { hhcd->hc[chnum].urb_state = URB_DONE; } else if (hhcd->hc[chnum].state == HC_STALL) { hhcd->hc[chnum].urb_state = URB_STALL; } else if (hhcd->hc[chnum].state == HC_XACTERR) { hhcd->hc[chnum].urb_state = URB_NOTREADY; } else if (hhcd->hc[chnum].state == HC_DATATGLERR) { hhcd->hc[chnum].urb_state = URB_ERROR; } __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH); HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); hhcd->hc[chnum].state = HC_XACTERR; USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK) { if(hhcd->hc[chnum].ep_type == EP_TYPE_INTR) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); } else if (hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) { /* re-activate the channel */ USBx_HC(chnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS; USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA; } else if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); } hhcd->hc[chnum].state = HC_NAK; __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); } // } else { // uint8_t chnum=i; USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_AHBERR) { __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR); __HAL_HCD_UNMASK_HALT_HC_INT(chnum); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_ACK) { __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK); if( hhcd->hc[chnum].do_ping == 1) { hhcd->hc[chnum].state = HC_NYET; __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); hhcd->hc[chnum].urb_state = URB_NOTREADY; } } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NYET) { hhcd->hc[chnum].state = HC_NYET; __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_FRMOR) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_XFRC) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC); hhcd->hc[chnum].state = HC_XFRC; } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_STALL) { __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL); __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); hhcd->hc[chnum].state = HC_STALL; } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_NAK) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); hhcd->hc[chnum].state = HC_NAK; __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_TXERR) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); hhcd->hc[chnum].state = HC_XACTERR; __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR); } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_DTERR) { __HAL_HCD_UNMASK_HALT_HC_INT(chnum); USB_HC_Halt(hhcd->Instance, chnum); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK); __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR); hhcd->hc[chnum].state = HC_DATATGLERR; } else if ((USBx_HC(chnum)->HCINT) & USB_OTG_HCINT_CHH) { __HAL_HCD_MASK_HALT_HC_INT(chnum); if(hhcd->hc[chnum].state == HC_XFRC) { hhcd->hc[chnum].urb_state = URB_DONE; if (hhcd->hc[chnum].ep_type == EP_TYPE_BULK) { hhcd->hc[chnum].toggle_out ^= 1; } } else if (hhcd->hc[chnum].state == HC_NAK) { hhcd->hc[chnum].urb_state = URB_NOTREADY; } else if (hhcd->hc[chnum].state == HC_NYET) { hhcd->hc[chnum].urb_state = URB_NOTREADY; hhcd->hc[chnum].do_ping = 0; } else if (hhcd->hc[chnum].state == HC_STALL) { hhcd->hc[chnum].urb_state = URB_STALL; } else if(hhcd->hc[chnum].state == HC_XACTERR) { hhcd->hc[chnum].urb_state = URB_NOTREADY; } else if (hhcd->hc[chnum].state == HC_DATATGLERR) { hhcd->hc[chnum].urb_state = URB_ERROR; } __HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH); HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state); } // } } } __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT); } /* Handle Rx Queue Level Interrupts */ if(__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) { USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL); // USB_OTG_GlobalTypeDef *USBx = hhcd->Instance; uint8_t channelnum =0; uint32_t pktsts; uint32_t pktcnt; uint32_t temp = 0; temp = hhcd->Instance->GRXSTSP ; channelnum = temp & USB_OTG_GRXSTSP_EPNUM; pktsts = (temp & USB_OTG_GRXSTSP_PKTSTS) >> 17; pktcnt = (temp & USB_OTG_GRXSTSP_BCNT) >> 4; switch (pktsts) { case GRXSTS_PKTSTS_IN: /* Read the data into the host buffer. */ if ((pktcnt > 0) && (hhcd->hc[channelnum].xfer_buff != (void *)0)) { USB_ReadPacket(hhcd->Instance, hhcd->hc[channelnum].xfer_buff, pktcnt); /*manage multiple Xfer */ hhcd->hc[channelnum].xfer_buff += pktcnt; hhcd->hc[channelnum].xfer_count += pktcnt; if((USBx_HC(channelnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0) { /* re-activate the channel when more packets are expected */ USBx_HC(channelnum)->HCCHAR &= ~USB_OTG_HCCHAR_CHDIS; USBx_HC(channelnum)->HCCHAR |= USB_OTG_HCCHAR_CHENA; hhcd->hc[channelnum].toggle_in ^= 1; } } break; case GRXSTS_PKTSTS_DATA_TOGGLE_ERR: break; case GRXSTS_PKTSTS_IN_XFER_COMP: case GRXSTS_PKTSTS_CH_HALTED: default: break; } // USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL); } } } uint8_t HC::slot = 0x00; HC::HC(HCD_HandleTypeDef* hhcd_USB) { static const int start = 1; uint8_t mask = (1<<start); hc_USB=hhcd_USB; for(int i = start; i < 8; i++, mask <<= 1) { if (!(slot & mask)) { slot |= mask; _ch = i; return; } } _ch = 0; // ERROR!!! } HC::HC(HCD_HandleTypeDef* hhcd_USB,int ch) { hc_USB=hhcd_USB; _ch = ch; slot |= (1<<_ch); } HC::~HC() { slot &= ~(1<<_ch); } HAL_StatusTypeDef HC::Init(int IF_N, uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) { _ep_addr = epnum; _ep_type = ep_type; if(IF_N!=USB_FastSpeed) { while(HAL_HCD_GetState(hc_USB)!=HAL_HCD_STATE_READY); } return HAL_HCD_HC_Init(hc_USB, _ch, epnum, dev_address, speed, ep_type, mps); } HAL_StatusTypeDef HC::SubmitRequest(int IF_N,uint8_t* pbuff, uint16_t length, bool setup) { uint32_t tick; tick=HAL_GetTick(); while(HAL_GetTick()==tick); if(IF_N!=USB_FastSpeed) { while((hc_USB->Instance->GRXSTSR&0x1E0000)==0x40000); while(((hc_USB->Instance->HNPTXSTS& 0xFFFF)*((hc_USB->Instance->HNPTXSTS& 0x000F0000)>>16))<length); } uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT; if (_ep_type == EP_TYPE_CTRL) { HCD_HCTypeDef* hc = &hc_USB->hc[_ch]; if (setup) { hc->data_pid = HC_PID_SETUP; hc->toggle_out = 0; } else { if (direction == DIR_IN) { if (hc->toggle_in == 0) { hc->data_pid = HC_PID_DATA0; } else { hc->data_pid = HC_PID_DATA1; } } else // OUT { if (hc->toggle_out == 0) { hc->data_pid = HC_PID_DATA0; } else { hc->data_pid = HC_PID_DATA1; } } } hc->xfer_buff = pbuff; hc->xfer_len = length; hc->urb_state = URB_IDLE; hc->xfer_count = 0; hc->ch_num = _ch; hc->state = HC_IDLE; if(IF_N==USB_FastSpeed) { return USB_HC_StartXfer(hc_USB->Instance, hc, 0); } else { return USB_HC_StartXfer(hc_USB->Instance, hc, 1); } } return HAL_HCD_HC_SubmitRequest(hc_USB, _ch, direction, _ep_type, 0, pbuff, length, 0); } HCD_URBStateTypeDef HC::GetURBState() { return HAL_HCD_HC_GetURBState(hc_USB, _ch); } HCD_HCStateTypeDef HC::GetState() { return HAL_HCD_HC_GetState(hc_USB, _ch); } uint32_t HC::GetXferCount() { return HAL_HCD_HC_GetXferCount(hc_USB, _ch); } void HC::SetToggle(uint8_t toggle) { if (_ep_addr & 0x80) // IN { hc_USB->hc[_ch].toggle_in = toggle; } else // OUT { hc_USB->hc[_ch].toggle_out = toggle; } } #endif