Fork of https://developer.mbed.org/users/bscott/code/STM32_USBDevice/

Fork of STM32_USBDevice by Bradley Scott

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHAL_STM32L1.cpp Source File

USBHAL_STM32L1.cpp

00001 /* Copyright (c) 2010-2015 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 #if defined(TARGET_STM32L1)||defined(TARGET_STM32F3)||defined(TARGET_STM32F1)||defined(TARGET_STM32F0)
00020 #include "pinmap.h"
00021 #include "USBDevice.h"
00022 
00023 #if defined(TARGET_STM32F1)
00024 #define USB_LP_IRQn USB_LP_CAN1_RX0_IRQn
00025 const uint8_t PCD_EP_TYPE_CTRL = EP_TYPE_CTRL;
00026 const uint8_t PCD_EP_TYPE_INTR = EP_TYPE_INTR;
00027 const uint8_t PCD_EP_TYPE_BULK = EP_TYPE_BULK;
00028 const uint8_t PCD_EP_TYPE_ISOC = EP_TYPE_ISOC;
00029 
00030 #elif defined(TARGET_STM32L1)
00031 void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) {
00032     __SYSCFG_CLK_ENABLE(); // for SYSCFG_PMC_USB_PU
00033     if (state == 1) {
00034         __HAL_SYSCFG_USBPULLUP_ENABLE();
00035     } else {
00036         __HAL_SYSCFG_USBPULLUP_DISABLE();
00037     } 
00038 }
00039 
00040 #elif defined(TARGET_STM32L0)||defined(TARGET_STM32F0)
00041 #define USB_LP_IRQn USB_IRQn
00042 void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) {
00043     if (state == 1) {
00044         SET_BIT(USB->BCDR, USB_BCDR_DPPU); // DP Pull-up
00045     } else {
00046         CLEAR_BIT(USB->BCDR, USB_BCDR_DPPU);
00047     } 
00048 }
00049 
00050 #elif defined(TARGET_STM32F3)
00051 // use remapped USB interrupts, so that CAN peripheral can also be used if needed
00052 //#define USB_LP_IRQn USB_LP_CAN_RX0_IRQn
00053 #endif
00054 
00055 static PCD_HandleTypeDef hpcd_USB_FS;
00056 static volatile int epComplete = 0;
00057 
00058 USBHAL * USBHAL::instance;
00059 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {return 0;}
00060 
00061 USBHAL::USBHAL(void) : PktBufArea(512) {
00062     #if defined(TARGET_STM32F3)
00063         // Configure USB pins
00064         pin_function(PA_11, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB));
00065         pin_function(PA_12, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF14_USB));
00066     #endif
00067     hpcd_USB_FS.pData = this;
00068     hpcd_USB_FS.Instance = USB;
00069     hpcd_USB_FS.Init.dev_endpoints = 8;
00070     hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
00071     hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8;
00072     hpcd_USB_FS.Init.phy_itface = PCD_PHY_EMBEDDED;
00073     hpcd_USB_FS.Init.Sof_enable = DISABLE;
00074     hpcd_USB_FS.Init.low_power_enable = DISABLE;
00075     hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
00076 #if defined(TARGET_STM32F3)
00077     __HAL_RCC_SYSCFG_CLK_ENABLE();
00078     __HAL_REMAPINTERRUPT_USB_ENABLE();
00079 #endif
00080     NVIC_SetVector(USB_LP_IRQn, (uint32_t)&_usbisr);
00081     HAL_PCD_Init(&hpcd_USB_FS);
00082     HAL_PCD_Start(&hpcd_USB_FS);
00083 }
00084 
00085 void HAL_PCD_MspInit(PCD_HandleTypeDef* hpcd) {
00086     __USB_CLK_ENABLE();
00087     HAL_NVIC_SetPriority(USB_LP_IRQn, 0, 0);
00088 }
00089 
00090 void HAL_PCD_MspDeInit(PCD_HandleTypeDef* hpcd) {
00091     HAL_NVIC_DisableIRQ(USB_LP_IRQn); // Peripheral interrupt Deinit
00092     __USB_CLK_DISABLE(); // Peripheral clock disable
00093 }
00094 
00095 USBHAL::~USBHAL(void) {
00096     HAL_PCD_DeInit(&hpcd_USB_FS);
00097 }
00098 
00099 void USBHAL::connect(void) {
00100     HAL_NVIC_EnableIRQ(USB_LP_IRQn);
00101     HAL_PCD_DevConnect(&hpcd_USB_FS);
00102 }
00103 
00104 void USBHAL::disconnect(void) {
00105     HAL_PCD_DevDisconnect(&hpcd_USB_FS);
00106     HAL_NVIC_DisableIRQ(USB_LP_IRQn);
00107 }
00108 
00109 void USBHAL::configureDevice(void) {
00110     // Not needed
00111 }
00112 void USBHAL::unconfigureDevice(void) {
00113     // Not needed
00114 }
00115 
00116 void USBHAL::setAddress(uint8_t address) {
00117     HAL_PCD_SetAddress(&hpcd_USB_FS, address);
00118 }
00119 
00120 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
00121     int pmaadress = PktBufArea.allocBuf(maxPacket);
00122     MBED_ASSERT(pmaadress != 0);
00123     if (pmaadress == 0) {
00124         return false;
00125     }
00126     PCD_HandleTypeDef *hpcd = &hpcd_USB_FS;
00127     uint8_t ep_type;
00128     switch(endpoint) {
00129         case EP0OUT:
00130             HAL_PCDEx_PMAConfig(hpcd, 0x00, PCD_SNG_BUF, pmaadress);
00131             HAL_PCD_EP_Open(hpcd, 0x00, maxPacket, PCD_EP_TYPE_CTRL);
00132             break;
00133         case EP0IN:
00134             HAL_PCDEx_PMAConfig(hpcd, 0x80, PCD_SNG_BUF, pmaadress);
00135             HAL_PCD_EP_Open(hpcd, 0x80, maxPacket, PCD_EP_TYPE_CTRL);
00136             break;
00137         case EPINT_OUT:
00138             HAL_PCDEx_PMAConfig(hpcd, 0x01, PCD_SNG_BUF, pmaadress);
00139             HAL_PCD_EP_Open(hpcd, 0x01, maxPacket, PCD_EP_TYPE_INTR);
00140             break;
00141         case EPINT_IN:
00142             HAL_PCDEx_PMAConfig(hpcd, 0x81, PCD_SNG_BUF, pmaadress);
00143             HAL_PCD_EP_Open(hpcd, 0x81, maxPacket, PCD_EP_TYPE_INTR);
00144             break;
00145         case EPBULK_OUT:
00146             HAL_PCDEx_PMAConfig(hpcd, 0x02, PCD_SNG_BUF, pmaadress);
00147             HAL_PCD_EP_Open(hpcd, 0x02, maxPacket, PCD_EP_TYPE_BULK);
00148             break;
00149         case EPBULK_IN:
00150             HAL_PCDEx_PMAConfig(hpcd, 0x82, PCD_SNG_BUF, pmaadress);
00151             HAL_PCD_EP_Open(hpcd, 0x82, maxPacket, PCD_EP_TYPE_BULK);
00152             break;
00153         case EP3OUT:
00154             HAL_PCDEx_PMAConfig(hpcd, 0x03, PCD_SNG_BUF, pmaadress);
00155             ep_type = (flags & ISOCHRONOUS) ? PCD_EP_TYPE_ISOC : PCD_EP_TYPE_BULK;
00156             HAL_PCD_EP_Open(hpcd, 0x03, maxPacket, ep_type);
00157             break;
00158         case EP3IN:
00159             HAL_PCDEx_PMAConfig(hpcd, 0x83, PCD_SNG_BUF, pmaadress);
00160             ep_type = (flags & ISOCHRONOUS) ? PCD_EP_TYPE_ISOC : PCD_EP_TYPE_BULK;
00161             HAL_PCD_EP_Open(hpcd, 0x83, maxPacket, ep_type);
00162             break;
00163         default:
00164             MBED_ASSERT(0);
00165             return false;
00166     }
00167     return true;
00168 }
00169 
00170 // read setup packet
00171 void USBHAL::EP0setup(uint8_t *buffer) {
00172     memcpy(buffer, hpcd_USB_FS.Setup, 8);
00173 }
00174 
00175 void USBHAL::EP0readStage(void) {
00176 }
00177 
00178 void USBHAL::EP0read(void) {
00179     endpointRead(EP0OUT, MAX_PACKET_SIZE_EP0);
00180 }
00181 
00182 class rxTempBufferManager {
00183     uint8_t buf0[MAX_PACKET_SIZE_EP0];
00184     uint8_t buf1[MAX_PACKET_SIZE_EP1];
00185     uint8_t buf2[MAX_PACKET_SIZE_EP2];
00186     uint8_t buf3[MAX_PACKET_SIZE_EP3_ISO];
00187 public:
00188     uint8_t* ptr(uint8_t endpoint, int maxPacketSize) {
00189         switch(endpoint) {
00190             case EP0OUT:
00191                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP0);
00192                 break;
00193             case EP1OUT:
00194                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP1);
00195                 break;
00196             case EP2OUT:
00197                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP2);
00198                 break;
00199             case EP3OUT:
00200                 MBED_ASSERT(maxPacketSize <= MAX_PACKET_SIZE_EP3_ISO);
00201                 break;
00202         }
00203         return ptr(endpoint);
00204     }
00205     uint8_t* ptr(uint8_t endpoint) {
00206         switch(endpoint) {
00207             case EP0OUT: return buf0;
00208             case EP1OUT: return buf1;
00209             case EP2OUT: return buf2;
00210             case EP3OUT: return buf3;
00211         }
00212         MBED_ASSERT(0);
00213         return NULL;
00214     }
00215 } rxtmp;
00216 
00217 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
00218     const uint8_t endpoint = EP0OUT;
00219     uint32_t length = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1);
00220     memcpy(buffer, rxtmp.ptr(endpoint), length);
00221     return length;
00222 }
00223 
00224 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
00225     endpointWrite(EP0IN, buffer, size);
00226 }
00227 
00228 void USBHAL::EP0getWriteResult(void) {
00229 }
00230 
00231 void USBHAL::EP0stall(void) {
00232     // If we stall the out endpoint here then we have problems transferring
00233     // and setup requests after the (stalled) get device qualifier requests.
00234     // TODO: Find out if this is correct behavior, or whether we are doing
00235     // something else wrong
00236     stallEndpoint(EP0IN);
00237 //    stallEndpoint(EP0OUT);
00238 }
00239 
00240 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
00241     core_util_critical_section_enter();
00242     HAL_PCD_EP_Receive(&hpcd_USB_FS, endpoint>>1, rxtmp.ptr(endpoint, maximumSize), maximumSize);
00243     epComplete &= ~(1 << endpoint);
00244     core_util_critical_section_exit();
00245     return EP_PENDING;
00246 }
00247 
00248 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
00249     if (!(epComplete & (1 << endpoint))) {
00250         return EP_PENDING;
00251     }
00252     int len = HAL_PCD_EP_GetRxCount(&hpcd_USB_FS, endpoint>>1);
00253     memcpy(buffer, rxtmp.ptr(endpoint), len);
00254     *bytesRead = len;
00255     return EP_COMPLETED;
00256 }
00257 
00258 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, const uint8_t *data, uint32_t size) {
00259     core_util_critical_section_enter();
00260     HAL_PCD_EP_Transmit(&hpcd_USB_FS, endpoint>>1, const_cast<uint8_t*>(data), size);
00261     epComplete &= ~(1 << endpoint);
00262     core_util_critical_section_exit();
00263     return EP_PENDING;
00264 }
00265 
00266 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
00267     if (epComplete & (1 << endpoint)) {
00268         core_util_critical_section_enter();
00269         epComplete &= ~(1 << endpoint);
00270         core_util_critical_section_exit();
00271         return EP_COMPLETED;
00272     }
00273     return EP_PENDING;
00274 }
00275 
00276 void USBHAL::stallEndpoint(uint8_t endpoint) {
00277     PCD_HandleTypeDef *hpcd = &hpcd_USB_FS;
00278     switch(endpoint) {
00279         case EP0IN:
00280             HAL_PCD_EP_SetStall(hpcd, 0x80);
00281             break;
00282         case EP0OUT:
00283             HAL_PCD_EP_SetStall(hpcd, 0x00);
00284             break;
00285         default:
00286             break;
00287     }
00288 }
00289 
00290 void USBHAL::unstallEndpoint(uint8_t endpoint) {
00291 }
00292 
00293 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
00294     return false;
00295 }
00296 
00297 void USBHAL::remoteWakeup(void) {}
00298 
00299 void USBHAL::_usbisr(void) {
00300     HAL_PCD_IRQHandler(&hpcd_USB_FS);
00301 }
00302 
00303 void USBHAL::usbisr(void) {}
00304 
00305 void USBHAL::SetupStageCallback() {
00306     EP0setupCallback();
00307 }
00308 
00309 void USBHAL::DataInStageCallback(uint8_t epnum) {
00310     switch(epnum) {
00311         case 0: // EP0IN
00312             EP0in();
00313             break;
00314         case 1: 
00315             epComplete |= (1<<EP1IN);
00316             if (EP1_IN_callback()) {
00317                 epComplete &= ~(1<<EP1IN);
00318             }
00319             break;
00320         case 2:
00321             epComplete |= (1<<EP2IN);
00322             if (EP2_IN_callback()) {
00323                 epComplete &= ~(1<<EP2IN);
00324             }
00325             break;
00326         case 3: 
00327             epComplete |= (1<<EP3IN);
00328             if (EP3_IN_callback()) {
00329                 epComplete &= ~(1<<EP3IN);
00330             }
00331             break;
00332         default:
00333             MBED_ASSERT(0);
00334             break;
00335     }
00336 }
00337 
00338 void USBHAL::DataOutStageCallback(uint8_t epnum) {
00339     switch(epnum) {
00340         case 0: // EP0OUT
00341             if ((hpcd_USB_FS.Setup[0]&0x80) == 0x00) { // host to device ?
00342                 EP0out();
00343             }
00344             break;
00345         case 1:
00346             epComplete |= (1<<EP1OUT);
00347             if (EP1_OUT_callback()) {
00348                 epComplete &= ~(1<<EP1OUT);
00349             }
00350             break;
00351         case 2:
00352             epComplete |= (1<<EP2OUT);
00353             if (EP2_OUT_callback()) {
00354                 epComplete &= ~(1<<EP2OUT);
00355             }
00356             break;
00357         case 3:
00358             epComplete |= (1<<EP3OUT);
00359             if (EP3_OUT_callback()) {
00360                 epComplete &= ~(1<<EP3OUT);
00361             }
00362             break;
00363         default:
00364             MBED_ASSERT(0);
00365             break;
00366     }
00367 }
00368 
00369 void USBHAL::ResetCallback() {
00370     PktBufArea.reset();
00371     realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
00372     realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
00373 }
00374 
00375 void USBHAL::SOFCallback() {
00376     SOF(hpcd_USB_FS.Instance->FNR & USB_FNR_FN);
00377 }
00378 
00379 void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd) {
00380     reinterpret_cast<USBHAL*>(hpcd->pData)->SetupStageCallback();
00381 }
00382 
00383 void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
00384     reinterpret_cast<USBHAL*>(hpcd->pData)->DataInStageCallback(epnum);
00385 }
00386 
00387 void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) {
00388     reinterpret_cast<USBHAL*>(hpcd->pData)->DataOutStageCallback(epnum);
00389 }
00390 
00391 void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd) {
00392     reinterpret_cast<USBHAL*>(hpcd->pData)->ResetCallback();
00393 }
00394 
00395 void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
00396     reinterpret_cast<USBHAL*>(hpcd->pData)->SOFCallback();
00397 }
00398 
00399 void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd) {
00400     if (hpcd->Init.low_power_enable) {
00401         SCB->SCR |= (uint32_t)((uint32_t)(SCB_SCR_SLEEPDEEP_Msk | SCB_SCR_SLEEPONEXIT_Msk));
00402     }
00403 }
00404 
00405 #endif