Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/
Fork of STM32_USBDevice by
Diff: USBDevice/USBHAL_STM32L1.cpp
- Revision:
- 58:68fad4f36f1c
- Parent:
- 57:b6b2296460db
- Child:
- 59:5d5e3685bd60
--- a/USBDevice/USBHAL_STM32L1.cpp Fri Jun 12 09:17:50 2015 +0000 +++ b/USBDevice/USBHAL_STM32L1.cpp Tue Jun 16 06:20:17 2015 +0900 @@ -1,414 +1,424 @@ -/* Copyright (c) 2010-2015 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_STM32L1) -#include "USBDevice.h" - -static PCD_HandleTypeDef hpcd_USB_FS; -static volatile int epComplete = 0; - -USBHAL * USBHAL::instance; -uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {return 0;} - -extern "C" void USB_LP_IRQHandler(void) { - HAL_PCD_IRQHandler(&hpcd_USB_FS); -} - -USBHAL::USBHAL(void) { - hpcd_USB_FS.pData = this; - hpcd_USB_FS.Instance = USB; - hpcd_USB_FS.Init.dev_endpoints = 8; - hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; - hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8; - hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED; - hpcd_USB_FS.Init.Sof_enable = DISABLE; - hpcd_USB_FS.Init.low_power_enable = DISABLE; - hpcd_USB_FS.Init.battery_charging_enable = DISABLE; - HAL_PCD_Init(&hpcd_USB_FS); - HAL_PCD_Start(&hpcd_USB_FS); -} - -void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) { - __USB_CLK_ENABLE(); - HAL_NVIC_SetPriority(USB_LP_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(USB_LP_IRQn); -} - -USBHAL::~USBHAL(void) {} - -void USBHAL::connect(void) { - MBED_ASSERT(hpcd_USB_FS.Instance == USB); -} - -void USBHAL::disconnect(void) { -} - -void USBHAL::configureDevice(void) { - // Not needed -} -void USBHAL::unconfigureDevice(void) { - // Not needed -} - -void USBHAL::setAddress(uint8_t address) { - HAL_PCD_SetAddress(&hpcd_USB_FS, address); -} - -class PacketBufferAreaManager { -public: - PacketBufferAreaManager() { - reset(); - } - void reset() { - head = 0; - tail = 512; - } - int allocBuf(int maxPacketSize) { - head += 4; - tail -= maxPacketSize; - if (tail < head) { - return 0; - } - return tail; - } -private: - int head,tail; -} PktBufArea; - -bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { - int pmaadress = PktBufArea.allocBuf(maxPacket); - MBED_ASSERT(pmaadress != 0); - if (pmaadress == 0) { - return false; - } - PCD_HandleTypeDef *hpcd = &hpcd_USB_FS; - switch(endpoint) { - case EP0IN: - HAL_PCDEx_PMAConfig(hpcd, 0x80, PCD_SNG_BUF, pmaadress); - HAL_PCD_EP_Open(hpcd, 0x80, maxPacket, PCD_EP_TYPE_CTRL); - break; - case EP0OUT: - HAL_PCDEx_PMAConfig(hpcd, 0x00, PCD_SNG_BUF, pmaadress); - HAL_PCD_EP_Open(hpcd, 0x00, maxPacket, PCD_EP_TYPE_CTRL); - break; - case EPINT_IN: - HAL_PCDEx_PMAConfig(hpcd, 0x81, PCD_SNG_BUF, pmaadress); - HAL_PCD_EP_Open(hpcd, 0x81, maxPacket, PCD_EP_TYPE_INTR); - break; - case EPINT_OUT: - HAL_PCDEx_PMAConfig(hpcd, 0x01, PCD_SNG_BUF, pmaadress); - HAL_PCD_EP_Open(hpcd, 0x01, maxPacket, PCD_EP_TYPE_INTR); - break; - case EPBULK_IN: - HAL_PCDEx_PMAConfig(hpcd, 0x82, PCD_SNG_BUF, pmaadress); - HAL_PCD_EP_Open(hpcd, 0x82, maxPacket, PCD_EP_TYPE_BULK); - break; - case EPBULK_OUT: - HAL_PCDEx_PMAConfig(hpcd, 0x02, PCD_SNG_BUF, pmaadress); - HAL_PCD_EP_Open(hpcd, 0x02, maxPacket, PCD_EP_TYPE_BULK); - break; - case EPISO_IN: - MBED_ASSERT(flags == ISOCHRONOUS); - HAL_PCDEx_PMAConfig(hpcd, 0x83, PCD_SNG_BUF, pmaadress); - HAL_PCD_EP_Open(hpcd, 0x83, maxPacket, PCD_EP_TYPE_ISOC); - break; - case EPISO_OUT: - MBED_ASSERT(flags == ISOCHRONOUS); - HAL_PCDEx_PMAConfig(hpcd, 0x03, PCD_SNG_BUF, pmaadress); - HAL_PCD_EP_Open(hpcd, 0x03, maxPacket, PCD_EP_TYPE_ISOC); - break; - default: - MBED_ASSERT(0); - return false; - } - return true; -} - -// read setup packet -void USBHAL::EP0setup(uint8_t *buffer) { - memcpy(buffer, hpcd_USB_FS.Setup, 8); -} - -void USBHAL::EP0readStage(void) { -} - -void USBHAL::EP0read(void) { - endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); -} - -static uint8_t* rxTempBuffer(uint8_t endpoint) { - switch(endpoint) { - case EP0OUT: - static uint8_t buf0[MAX_PACKET_SIZE_EP0]; - return buf0; - case EP1OUT: - static uint8_t buf1[MAX_PACKET_SIZE_EP1]; - return buf1; - case EP2OUT: - static uint8_t buf2[MAX_PACKET_SIZE_EP2]; - return buf2; - case EP3OUT: - static uint8_t buf3[MAX_PACKET_SIZE_EP3_ISO]; - return buf3; - } - MBED_ASSERT(0); - return NULL; -} - -uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { - const uint8_t endpoint = EP0OUT; - uint32_t length = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1); - memcpy(buffer, rxTempBuffer(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) { - HAL_PCD_EP_Receive(&hpcd_USB_FS, endpoint>>1, rxTempBuffer(endpoint), maximumSize); - epComplete &= ~(1 << endpoint); - return EP_PENDING; -} - -EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { - if (!(epComplete & (1 << endpoint))) { - return EP_PENDING; - } - int len = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1); - MBED_ASSERT(len <= 64); - memcpy(buffer, rxTempBuffer(endpoint), len); - *bytesRead = len; - return EP_COMPLETED; -} - -EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { - HAL_PCD_EP_Transmit(&hpcd_USB_FS, endpoint>>1, data, size); - epComplete &= ~(1 << endpoint); - return EP_PENDING; -} - -EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { - if (epComplete & (1 << endpoint)) { - epComplete &= ~(1 << endpoint); - return EP_COMPLETED; - } - return EP_PENDING; -} - -void USBHAL::stallEndpoint(uint8_t endpoint) { - PCD_HandleTypeDef *hpcd = &hpcd_USB_FS; - 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::_usbisr(void) {} -void USBHAL::usbisr(void) {} - -void USBHAL::SetupStageCallback() { - EP0setupCallback(); -} - -void USBHAL::DataInStageCallback(uint8_t epnum) { - switch(epnum) { - case 0: // EP0IN - EP0in(); - break; - case 1: - epComplete |= (1<<EP1IN); - if (EP1_IN_callback()) { - epComplete &= ~(1<<EP1IN); - } - break; - case 2: - epComplete |= (1<<EP2IN); - if (EP2_IN_callback()) { - epComplete &= ~(1<<EP2IN); - } - break; - case 3: - epComplete |= (1<<EP3IN); - if (EP3_IN_callback()) { - epComplete &= ~(1<<EP3IN); - } - break; - default: - MBED_ASSERT(0); - break; - } -} - -void USBHAL::DataOutStageCallback(uint8_t epnum) { - switch(epnum) { - case 0: // EP0OUT - EP0out(); - break; - case 1: - epComplete |= (1<<EP1OUT); - if (EP1_OUT_callback()) { - epComplete &= ~(1<<EP1OUT); - } - break; - case 2: - epComplete |= (1<<EP2OUT); - if (EP2_OUT_callback()) { - epComplete &= ~(1<<EP2OUT); - } - break; - case 3: - epComplete |= (1<<EP3OUT); - if (EP3_OUT_callback()) { - epComplete &= ~(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() { - SOF(hpcd_USB_FS.Instance->FNR & 0x7fff); -} - -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)); - } -} - -void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) { - if (state == 1) { - __HAL_SYSCFG_USBPULLUP_ENABLE(); - } else { - __HAL_SYSCFG_USBPULLUP_DISABLE(); - } -} - - -void L152RE_SystemClock_Config(void) { - RCC_OscInitTypeDef RCC_OscInitStruct; - RCC_ClkInitTypeDef RCC_ClkInitStruct; - - __PWR_CLK_ENABLE(); - - __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); - - RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; - RCC_OscInitStruct.HSIState = RCC_HSI_ON; - RCC_OscInitStruct.HSICalibrationValue = 16; - RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; - RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; - RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6; - RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3; - HAL_RCC_OscConfig(&RCC_OscInitStruct); - - RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; - RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; - RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; - RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; - RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; - HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); - - __SYSCFG_CLK_ENABLE(); -} - -uint32_t L152RE_getUSBclock() { - RCC_OscInitTypeDef cfg; - HAL_RCC_GetOscConfig(&cfg); - MBED_ASSERT(cfg.PLL.PLLState == RCC_PLL_ON); - uint32_t src = (cfg.PLL.PLLSource == RCC_PLLSOURCE_HSI) ? HSI_VALUE : HSE_VALUE; - MBED_ASSERT(src == 16000000 || src == 8000000); - switch(cfg.PLL.PLLMUL) { - case RCC_PLL_MUL3: src *= 3; break; - case RCC_PLL_MUL4: src *= 4; break; - case RCC_PLL_MUL6: src *= 6; break; - case RCC_PLL_MUL8: src *= 8; break; - case RCC_PLL_MUL12: src *= 12; break; - case RCC_PLL_MUL16: src *= 16; break; - case RCC_PLL_MUL24: src *= 24; break; - case RCC_PLL_MUL32: src *= 32; break; - case RCC_PLL_MUL48: src *= 48; break; - } - return src / 2; -} - -void L152RE_USBclock_setup() { - if (L152RE_getUSBclock() != 48000000) { - HAL_RCC_DeInit(); - L152RE_SystemClock_Config(); - } -} - -#endif - +/* Copyright (c) 2010-2015 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_STM32L1) +#include "USBDevice.h" + +static PCD_HandleTypeDef hpcd_USB_FS; +static volatile int epComplete = 0; + +USBHAL * USBHAL::instance; +uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {return 0;} + +extern "C" void USB_LP_IRQHandler(void) { + HAL_PCD_IRQHandler(&hpcd_USB_FS); +} + +USBHAL::USBHAL(void) { + hpcd_USB_FS.pData = this; + hpcd_USB_FS.Instance = USB; + hpcd_USB_FS.Init.dev_endpoints = 8; + hpcd_USB_FS.Init.speed = PCD_SPEED_FULL; + hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8; + hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED; + hpcd_USB_FS.Init.Sof_enable = DISABLE; + hpcd_USB_FS.Init.low_power_enable = DISABLE; + hpcd_USB_FS.Init.battery_charging_enable = DISABLE; + HAL_PCD_Init(&hpcd_USB_FS); +} + +void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) { + __USB_CLK_ENABLE(); + HAL_NVIC_SetPriority(USB_LP_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(USB_LP_IRQn); +} + +void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) { + MBED_ASSERT(hpcd->Instance == USB); + __USB_CLK_DISABLE(); // Peripheral clock disable + HAL_NVIC_DisableIRQ(USB_LP_IRQn); // Peripheral interrupt Deinit +} + +USBHAL::~USBHAL(void) { + HAL_PCD_DeInit(&hpcd_USB_FS); +} + +void USBHAL::connect(void) { + MBED_ASSERT(hpcd_USB_FS.Instance == USB); + HAL_PCD_DevConnect(&hpcd_USB_FS); +} + +void USBHAL::disconnect(void) { + HAL_PCD_DevDisconnect(&hpcd_USB_FS); +} + +void USBHAL::configureDevice(void) { + // Not needed +} +void USBHAL::unconfigureDevice(void) { + // Not needed +} + +void USBHAL::setAddress(uint8_t address) { + HAL_PCD_SetAddress(&hpcd_USB_FS, address); +} + +class PacketBufferAreaManager { +public: + PacketBufferAreaManager() { + reset(); + } + void reset() { + head = 0; + tail = 512; + } + int allocBuf(int maxPacketSize) { + head += 4; + tail -= maxPacketSize; + if (tail < head) { + return 0; + } + return tail; + } +private: + int head,tail; +} PktBufArea; + +bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { + int pmaadress = PktBufArea.allocBuf(maxPacket); + MBED_ASSERT(pmaadress != 0); + if (pmaadress == 0) { + return false; + } + PCD_HandleTypeDef *hpcd = &hpcd_USB_FS; + uint8_t ep_type; + switch(endpoint) { + case EP0OUT: + HAL_PCDEx_PMAConfig(hpcd, 0x00, PCD_SNG_BUF, pmaadress); + HAL_PCD_EP_Open(hpcd, 0x00, maxPacket, PCD_EP_TYPE_CTRL); + break; + case EP0IN: + HAL_PCDEx_PMAConfig(hpcd, 0x80, PCD_SNG_BUF, pmaadress); + HAL_PCD_EP_Open(hpcd, 0x80, maxPacket, PCD_EP_TYPE_CTRL); + break; + case EPINT_OUT: + HAL_PCDEx_PMAConfig(hpcd, 0x01, PCD_SNG_BUF, pmaadress); + HAL_PCD_EP_Open(hpcd, 0x01, maxPacket, PCD_EP_TYPE_INTR); + break; + case EPINT_IN: + HAL_PCDEx_PMAConfig(hpcd, 0x81, PCD_SNG_BUF, pmaadress); + HAL_PCD_EP_Open(hpcd, 0x81, maxPacket, PCD_EP_TYPE_INTR); + break; + case EPBULK_OUT: + HAL_PCDEx_PMAConfig(hpcd, 0x02, PCD_SNG_BUF, pmaadress); + HAL_PCD_EP_Open(hpcd, 0x02, maxPacket, PCD_EP_TYPE_BULK); + break; + case EPBULK_IN: + HAL_PCDEx_PMAConfig(hpcd, 0x82, PCD_SNG_BUF, pmaadress); + HAL_PCD_EP_Open(hpcd, 0x82, maxPacket, PCD_EP_TYPE_BULK); + break; + case EP3OUT: + HAL_PCDEx_PMAConfig(hpcd, 0x03, PCD_SNG_BUF, pmaadress); + ep_type = (flags & ISOCHRONOUS) ? PCD_EP_TYPE_ISOC : PCD_EP_TYPE_BULK; + HAL_PCD_EP_Open(hpcd, 0x03, maxPacket, ep_type); + break; + case EP3IN: + HAL_PCDEx_PMAConfig(hpcd, 0x83, PCD_SNG_BUF, pmaadress); + ep_type = (flags & ISOCHRONOUS) ? PCD_EP_TYPE_ISOC : PCD_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) { + memcpy(buffer, hpcd_USB_FS.Setup, 8); +} + +void USBHAL::EP0readStage(void) { +} + +void USBHAL::EP0read(void) { + endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0); +} + +static uint8_t* rxTempBuffer(uint8_t endpoint) { + switch(endpoint) { + case EP0OUT: + static uint8_t buf0[MAX_PACKET_SIZE_EP0]; + return buf0; + case EP1OUT: + static uint8_t buf1[MAX_PACKET_SIZE_EP1]; + return buf1; + case EP2OUT: + static uint8_t buf2[MAX_PACKET_SIZE_EP2]; + return buf2; + case EP3OUT: + static uint8_t buf3[MAX_PACKET_SIZE_EP3_ISO]; + return buf3; + } + MBED_ASSERT(0); + return NULL; +} + +uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { + const uint8_t endpoint = EP0OUT; + uint32_t length = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1); + memcpy(buffer, rxTempBuffer(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) { + HAL_PCD_EP_Receive(&hpcd_USB_FS, endpoint>>1, rxTempBuffer(endpoint), maximumSize); + epComplete &= ~(1 << endpoint); + return EP_PENDING; +} + +EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { + if (!(epComplete & (1 << endpoint))) { + return EP_PENDING; + } + int len = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1); + MBED_ASSERT(len <= 64); + memcpy(buffer, rxTempBuffer(endpoint), len); + *bytesRead = len; + return EP_COMPLETED; +} + +EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { + HAL_PCD_EP_Transmit(&hpcd_USB_FS, endpoint>>1, data, size); + epComplete &= ~(1 << endpoint); + return EP_PENDING; +} + +EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { + if (epComplete & (1 << endpoint)) { + epComplete &= ~(1 << endpoint); + return EP_COMPLETED; + } + return EP_PENDING; +} + +void USBHAL::stallEndpoint(uint8_t endpoint) { + PCD_HandleTypeDef *hpcd = &hpcd_USB_FS; + 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::_usbisr(void) {} +void USBHAL::usbisr(void) {} + +void USBHAL::SetupStageCallback() { + EP0setupCallback(); +} + +void USBHAL::DataInStageCallback(uint8_t epnum) { + switch(epnum) { + case 0: // EP0IN + EP0in(); + break; + case 1: + epComplete |= (1<<EP1IN); + if (EP1_IN_callback()) { + epComplete &= ~(1<<EP1IN); + } + break; + case 2: + epComplete |= (1<<EP2IN); + if (EP2_IN_callback()) { + epComplete &= ~(1<<EP2IN); + } + break; + case 3: + epComplete |= (1<<EP3IN); + if (EP3_IN_callback()) { + epComplete &= ~(1<<EP3IN); + } + break; + default: + MBED_ASSERT(0); + break; + } +} + +void USBHAL::DataOutStageCallback(uint8_t epnum) { + switch(epnum) { + case 0: // EP0OUT + EP0out(); + break; + case 1: + epComplete |= (1<<EP1OUT); + if (EP1_OUT_callback()) { + epComplete &= ~(1<<EP1OUT); + } + break; + case 2: + epComplete |= (1<<EP2OUT); + if (EP2_OUT_callback()) { + epComplete &= ~(1<<EP2OUT); + } + break; + case 3: + epComplete |= (1<<EP3OUT); + if (EP3_OUT_callback()) { + epComplete &= ~(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() { + SOF(hpcd_USB_FS.Instance->FNR & 0x7fff); +} + +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)); + } +} + +void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) { + if (state == 1) { + __HAL_SYSCFG_USBPULLUP_ENABLE(); + } else { + __HAL_SYSCFG_USBPULLUP_DISABLE(); + } +} + + +void L152RE_SystemClock_Config(void) { + RCC_OscInitTypeDef RCC_OscInitStruct; + RCC_ClkInitTypeDef RCC_ClkInitStruct; + + __PWR_CLK_ENABLE(); + + __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); + + RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; + RCC_OscInitStruct.HSIState = RCC_HSI_ON; + RCC_OscInitStruct.HSICalibrationValue = 16; + RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; + RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; + RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6; + RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3; + HAL_RCC_OscConfig(&RCC_OscInitStruct); + + RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK; + RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; + RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; + RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; + RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; + HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1); + + __SYSCFG_CLK_ENABLE(); +} + +uint32_t L152RE_getUSBclock() { + RCC_OscInitTypeDef cfg; + HAL_RCC_GetOscConfig(&cfg); + MBED_ASSERT(cfg.PLL.PLLState == RCC_PLL_ON); + uint32_t src = (cfg.PLL.PLLSource == RCC_PLLSOURCE_HSI) ? HSI_VALUE : HSE_VALUE; + MBED_ASSERT(src == 16000000 || src == 8000000); + switch(cfg.PLL.PLLMUL) { + case RCC_PLL_MUL3: src *= 3; break; + case RCC_PLL_MUL4: src *= 4; break; + case RCC_PLL_MUL6: src *= 6; break; + case RCC_PLL_MUL8: src *= 8; break; + case RCC_PLL_MUL12: src *= 12; break; + case RCC_PLL_MUL16: src *= 16; break; + case RCC_PLL_MUL24: src *= 24; break; + case RCC_PLL_MUL32: src *= 32; break; + case RCC_PLL_MUL48: src *= 48; break; + } + return src / 2; +} + +void L152RE_USBclock_setup() { + if (L152RE_getUSBclock() != 48000000) { + HAL_RCC_DeInit(); + L152RE_SystemClock_Config(); + } +} + +#endif +