Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/
Fork of STM32_USBDevice by
USBDevice/USBHAL_STM32L1.cpp
- Committer:
- va009039
- Date:
- 2015-06-16
- Revision:
- 58:68fad4f36f1c
- Parent:
- 57:b6b2296460db
- Child:
- 59:5d5e3685bd60
File content as of revision 58:68fad4f36f1c:
/* 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