partly working USB Device lib for STM32F746NG Discovery both Interface are working
Dependents: DISCO-F746NG-USB_Device McLighTT project_Keyboard_to_the_Keyboard MIDIInstrumentPADProject ... more
USBDevice/USBHAL_STM32F7.cpp
- Committer:
- DieterGraef
- Date:
- 2016-07-31
- Revision:
- 0:0a2eaa300982
File content as of revision 0:0a2eaa300982:
/* Copyright (c) 2010-2011 mbed.org, MIT License * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or * substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if defined (TARGET_DISCO_F746NG) #include "USBDevice.h" static PCD_HandleTypeDef hpcd_USB_FS; static PCD_HandleTypeDef hpcd_USB_HS; static volatile int epCompleteFS = 0; static volatile int epCompleteHS = 0; USBHAL * USBHAL::instance; uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { return 0; } void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { GPIO_InitTypeDef GPIO_InitStruct; if(hpcd->Instance == USB_OTG_FS) { /* Configure USB FS GPIOs */ __HAL_RCC_GPIOA_CLK_ENABLE(); /* Configure DM DP Pins */ 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); /* Enable USB FS Clock */ __HAL_RCC_USB_OTG_FS_CLK_ENABLE(); } else if(hpcd->Instance == USB_OTG_HS) { /* Configure USB FS GPIOs */ __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(); } } void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { if(hpcd->Instance == USB_OTG_FS) { /* Disable USB FS Clock */ __HAL_RCC_USB_OTG_FS_CLK_DISABLE(); __HAL_RCC_SYSCFG_CLK_DISABLE(); } else if(hpcd->Instance == USB_OTG_HS) { /* Disable USB HS Clocks */ __HAL_RCC_USB_OTG_HS_CLK_DISABLE(); __HAL_RCC_SYSCFG_CLK_DISABLE(); } } USBHAL::USBHAL(uint16_t HW_Interface) { HW_Interfaces=HW_Interface; if(HW_Interface==Fastspeed_Interface) { hpcd_USB_FS.pData = this; hpcd_USB_FS.Instance = USB_OTG_FS; hpcd_USB_FS.Init.dev_endpoints = 8; hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; hpcd_USB_FS.Init.ep0_mps = 0x40; hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED; hpcd_USB_FS.Init.Sof_enable = DISABLE; hpcd_USB_FS.Init.dma_enable = DISABLE; hpcd_USB_FS.Init.vbus_sensing_enable = DISABLE; hpcd_USB_FS.Init.lpm_enable = DISABLE; hpcd_USB_FS.Init.low_power_enable = DISABLE; //hpcd_USB_FS.Init.battery_charging_enable = DISABLE; NVIC_SetVector(OTG_FS_IRQn, (uint32_t)&_usbisrFS); /* Set USBFS Interrupt priority */ HAL_NVIC_SetPriority(OTG_FS_IRQn, 5, 0); /* Enable USBFS Interrupt */ HAL_NVIC_EnableIRQ(OTG_FS_IRQn); HAL_PCD_Init(&hpcd_USB_FS); HAL_PCDEx_SetRxFiFo(&hpcd_USB_FS, 0x80); HAL_PCD_Start(&hpcd_USB_FS); } else { hpcd_USB_HS.pData = this; hpcd_USB_HS.Instance = USB_OTG_HS; hpcd_USB_HS.Init.dev_endpoints = 8; hpcd_USB_HS.Init.speed = PCD_SPEED_HIGH; hpcd_USB_HS.Init.ep0_mps = 0x40; hpcd_USB_HS.Init.phy_itface = PCD_PHY_ULPI; hpcd_USB_HS.Init.Sof_enable = DISABLE; hpcd_USB_HS.Init.dma_enable = DISABLE; hpcd_USB_HS.Init.vbus_sensing_enable = ENABLE; hpcd_USB_HS.Init.lpm_enable = DISABLE; hpcd_USB_HS.Init.low_power_enable = DISABLE; //hpcd_USB_HS.Init.battery_charging_enable = DISABLE; NVIC_SetVector(OTG_HS_IRQn, (uint32_t)&_usbisrHS); /* Set USBHS Interrupt to the lowest priority */ HAL_NVIC_SetPriority(OTG_HS_IRQn, 5, 0); /* Enable USBHS Interrupt */ HAL_NVIC_EnableIRQ(OTG_HS_IRQn); HAL_PCD_Init(&hpcd_USB_HS); HAL_PCDEx_SetRxFiFo(&hpcd_USB_HS, 0x200); HAL_PCD_Start(&hpcd_USB_HS); } } USBHAL::~USBHAL(void) { if(HW_Interfaces==Fastspeed_Interface) { HAL_PCD_DeInit(&hpcd_USB_FS); } else { HAL_PCD_DeInit(&hpcd_USB_HS); } } void USBHAL::connect(void) { if(HW_Interfaces==Fastspeed_Interface) { HAL_PCD_DevConnect(&hpcd_USB_FS); } else { HAL_PCD_DevConnect(&hpcd_USB_HS); } } void USBHAL::disconnect(void) { if(HW_Interfaces==Fastspeed_Interface) { HAL_PCD_DevDisconnect(&hpcd_USB_FS); } else { HAL_PCD_DevDisconnect(&hpcd_USB_HS); } } void USBHAL::configureDevice(void) { // Not needed } void USBHAL::unconfigureDevice(void) { // Not needed } void USBHAL::setAddress(uint8_t address) { if(HW_Interfaces==Fastspeed_Interface) { HAL_PCD_SetAddress(&hpcd_USB_FS, address); } else { HAL_PCD_SetAddress(&hpcd_USB_HS, address); } } class PacketBufferAreaManager { public: PacketBufferAreaManager(int bufsize_):bufsize(bufsize_) { reset(); } void reset() { head = 0; tail = bufsize; } int allocBuf(int maxPacketSize) { head += 4; tail -= maxPacketSize; if (tail < head) { return 0; } return tail; } private: int head,tail; int bufsize; } PktBufArea(512); bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { PCD_HandleTypeDef *hpcd; if(HW_Interfaces==Fastspeed_Interface) { hpcd = &hpcd_USB_FS; } else { hpcd = &hpcd_USB_HS; } uint8_t ep_type; switch(endpoint) { case EP0OUT: HAL_PCD_EP_Open(hpcd, 0x00, maxPacket, EP_TYPE_CTRL); break; case EP0IN: HAL_PCDEx_SetTxFiFo(hpcd,0,maxPacket); HAL_PCD_EP_Open(hpcd, 0x80, maxPacket, EP_TYPE_CTRL); break; case EPINT_OUT: HAL_PCD_EP_Open(hpcd, 0x01, maxPacket, EP_TYPE_INTR); break; case EPINT_IN: HAL_PCDEx_SetTxFiFo(hpcd,1,maxPacket); HAL_PCD_EP_Open(hpcd, 0x81, maxPacket, EP_TYPE_INTR); break; case EPBULK_OUT: HAL_PCD_EP_Open(hpcd, 0x02, maxPacket, EP_TYPE_BULK); break; case EPBULK_IN: HAL_PCDEx_SetTxFiFo(hpcd,2,maxPacket); HAL_PCD_EP_Open(hpcd, 0x82, maxPacket, EP_TYPE_BULK); break; case EP3OUT: ep_type = (flags & ISOCHRONOUS) ? EP_TYPE_ISOC : EP_TYPE_BULK; HAL_PCD_EP_Open(hpcd, 0x03, maxPacket, ep_type); break; case EP3IN: HAL_PCDEx_SetTxFiFo(hpcd,3,maxPacket); ep_type = (flags & ISOCHRONOUS) ? EP_TYPE_ISOC : EP_TYPE_BULK; HAL_PCD_EP_Open(hpcd, 0x83, maxPacket, ep_type); break; default: MBED_ASSERT(0); return false; } return true; } // read setup packet void USBHAL::EP0setup(uint8_t *buffer) { if(HW_Interfaces==Fastspeed_Interface) { memcpy(buffer, hpcd_USB_FS.Setup, 8); } else { memcpy(buffer, hpcd_USB_HS.Setup, 8); } } void USBHAL::EP0readStage(void) { } void USBHAL::EP0read(void) { endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); } class rxTempBufferManager { uint8_t buf0[MAX_PACKET_SIZE_EP0]; uint8_t buf1[MAX_PACKET_SIZE_EP1]; uint8_t buf2[MAX_PACKET_SIZE_EP2]; uint8_t buf3[MAX_PACKET_SIZE_EP3_ISO]; public: uint8_t* ptr(uint8_t endpoint, int maxPacketSize) { switch(endpoint) { case EP0OUT: MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP0); break; case EP1OUT: MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP1); break; case EP2OUT: MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP2); break; case EP3OUT: MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP3_ISO); break; } return ptr(endpoint); } uint8_t* ptr(uint8_t endpoint) { switch(endpoint) { case EP0OUT: return buf0; case EP1OUT: return buf1; case EP2OUT: return buf2; case EP3OUT: return buf3; } MBED_ASSERT(0); return NULL; } } rxtmp; uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { const uint8_t endpoint = EP0OUT; uint32_t length; if(HW_Interfaces==Fastspeed_Interface) { length = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1); } else { length = HAL_PCD_EP_GetRxCount(&hpcd_USB_HS, endpoint>>1); } memcpy(buffer, rxtmp.ptr(endpoint), length); return length; } void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { endpointWrite(EP0IN, buffer, size); } void USBHAL::EP0getWriteResult(void) { } void USBHAL::EP0stall(void) { // If we stall the out endpoint here then we have problems transferring // and setup requests after the (stalled) get device qualifier requests. // TODO: Find out if this is correct behavior, or whether we are doing // something else wrong stallEndpoint(EP0IN); // stallEndpoint(EP0OUT); } EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { if(HW_Interfaces==Fastspeed_Interface) { epCompleteFS &= ~(1 << endpoint); HAL_PCD_EP_Receive(&hpcd_USB_FS, endpoint>>1, rxtmp.ptr(endpoint, maximumSize), maximumSize); } else { epCompleteHS &= ~(1 << endpoint); HAL_PCD_EP_Receive(&hpcd_USB_HS, endpoint>>1, rxtmp.ptr(endpoint, maximumSize), maximumSize); } return EP_PENDING; } EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { int len; if(HW_Interfaces==Fastspeed_Interface) { if (!(epCompleteFS & (1 << endpoint))) { return EP_PENDING; } len = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1); } else { if (!(epCompleteHS & (1 << endpoint))) { return EP_PENDING; } len = HAL_PCD_EP_GetRxCount(&hpcd_USB_HS, endpoint>>1); } memcpy(buffer, rxtmp.ptr(endpoint), len); *bytesRead = len; return EP_COMPLETED; } EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { if(HW_Interfaces==Fastspeed_Interface) { epCompleteFS &= ~(1 << endpoint); HAL_PCD_EP_Transmit(&hpcd_USB_FS, endpoint>>1, data, size); } else { epCompleteHS &= ~(1 << endpoint); HAL_PCD_EP_Transmit(&hpcd_USB_HS, endpoint>>1, data, size); } return EP_PENDING; } EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { if(HW_Interfaces==Fastspeed_Interface) { if (epCompleteFS & (1 << endpoint)) { epCompleteFS &= ~(1 << endpoint); return EP_COMPLETED; } return EP_PENDING; } else { if (epCompleteHS & (1 << endpoint)) { epCompleteHS &= ~(1 << endpoint); return EP_COMPLETED; } return EP_PENDING; } } void USBHAL::stallEndpoint(uint8_t endpoint) { PCD_HandleTypeDef *hpcd; if(HW_Interfaces==Fastspeed_Interface) { hpcd = &hpcd_USB_FS; } else { hpcd = &hpcd_USB_HS; } switch(endpoint) { case EP0IN: HAL_PCD_EP_SetStall(hpcd, 0x80); break; case EP0OUT: HAL_PCD_EP_SetStall(hpcd, 0x00); break; default: break; } } void USBHAL::unstallEndpoint(uint8_t endpoint) { } bool USBHAL::getEndpointStallState(uint8_t endpoint) { return false; } void USBHAL::remoteWakeup(void) {} void USBHAL::_usbisrFS(void) { HAL_PCD_IRQHandler(&hpcd_USB_FS); } void USBHAL::_usbisrHS(void) { HAL_PCD_IRQHandler(&hpcd_USB_HS); } void USBHAL::usbisr(void) {} void USBHAL::SetupStageCallback() { EP0setupCallback(); } void USBHAL::DataInStageCallback(uint8_t epnum) { if(HW_Interfaces==Fastspeed_Interface) { switch(epnum) { case 0: // EP0IN EP0in(); break; case 1: epCompleteFS |= (1<<EP1IN); if (EP1_IN_callback()) { epCompleteFS &= ~(1<<EP1IN); } break; case 2: epCompleteFS |= (1<<EP2IN); if (EP2_IN_callback()) { epCompleteFS &= ~(1<<EP2IN); } break; case 3: epCompleteFS |= (1<<EP3IN); if (EP3_IN_callback()) { epCompleteFS &= ~(1<<EP3IN); } break; default: MBED_ASSERT(0); break; } } else { switch(epnum) { case 0: // EP0IN EP0in(); break; case 1: epCompleteHS |= (1<<EP1IN); if (EP1_IN_callback()) { epCompleteHS &= ~(1<<EP1IN); } break; case 2: epCompleteHS |= (1<<EP2IN); if (EP2_IN_callback()) { epCompleteHS &= ~(1<<EP2IN); } break; case 3: epCompleteFS |= (1<<EP3IN); if (EP3_IN_callback()) { epCompleteFS &= ~(1<<EP3IN); } break; default: MBED_ASSERT(0); break; } } } void USBHAL::DataOutStageCallback(uint8_t epnum) { if(HW_Interfaces==Fastspeed_Interface) { switch(epnum) { case 0: // EP0OUT if ((hpcd_USB_FS.Setup[0]&0x80) == 0x00) // host to device ? { EP0out(); } break; case 1: epCompleteFS |= (1<<EP1OUT); if (EP1_OUT_callback()) { epCompleteFS &= ~(1<<EP1OUT); } break; case 2: epCompleteFS |= (1<<EP2OUT); if (EP2_OUT_callback()) { epCompleteFS &= ~(1<<EP2OUT); } break; case 3: epCompleteFS |= (1<<EP3OUT); if (EP3_OUT_callback()) { epCompleteFS &= ~(1<<EP3OUT); } break; default: MBED_ASSERT(0); break; } } else { switch(epnum) { case 0: // EP0OUT if ((hpcd_USB_HS.Setup[0]&0x80) == 0x00) // host to device ? { EP0out(); } break; case 1: epCompleteHS |= (1<<EP1OUT); if (EP1_OUT_callback()) { epCompleteHS &= ~(1<<EP1OUT); } break; case 2: epCompleteHS |= (1<<EP2OUT); if (EP2_OUT_callback()) { epCompleteHS &= ~(1<<EP2OUT); } break; case 3: epCompleteHS |= (1<<EP3OUT); if (EP3_OUT_callback()) { epCompleteHS &= ~(1<<EP3OUT); } break; default: MBED_ASSERT(0); break; } } } void USBHAL::ResetCallback() { PktBufArea.reset(); realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); } void USBHAL::SOFCallback() { if(HW_Interfaces==Fastspeed_Interface) { SOF(1); } else { SOF(1); } } void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) { reinterpret_cast<USBHAL*>(hpcd->pData)->SetupStageCallback(); } void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { reinterpret_cast<USBHAL*>(hpcd->pData)->DataInStageCallback(epnum); } void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) { reinterpret_cast<USBHAL*>(hpcd->pData)->DataOutStageCallback(epnum); } void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) { reinterpret_cast<USBHAL*>(hpcd->pData)->ResetCallback(); } void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { reinterpret_cast<USBHAL*>(hpcd->pData)->SOFCallback(); } void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) { if (hpcd->Init.low_power_enable) { SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk)); } } #endif