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
Diff: USBHost/TARGET_STM32F7/USBHALHost_F746NG.cpp
- Revision:
- 24:5396b6a93262
- Child:
- 25:7d6d9fc471bf
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/USBHost/TARGET_STM32F7/USBHALHost_F746NG.cpp Mon Jun 13 17:21:07 2016 +0000 @@ -0,0 +1,1345 @@ +#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 + +