TUKS MCU Introductory course / TUKS-COURSE-THERMOMETER

Fork of TUKS-COURSE-TIMER by TUKS MCU Introductory course

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers stm32l4xx_hal_pcd.c Source File

stm32l4xx_hal_pcd.c

Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_pcd.c
00004   * @author  MCD Application Team
00005   * @version V1.5.1
00006   * @date    31-May-2016
00007   * @brief   PCD HAL module driver.
00008   *          This file provides firmware functions to manage the following 
00009   *          functionalities of the USB Peripheral Controller:
00010   *           + Initialization and de-initialization functions
00011   *           + IO operation functions
00012   *           + Peripheral Control functions 
00013   *           + Peripheral State functions
00014   *         
00015   @verbatim
00016   ==============================================================================
00017                     ##### How to use this driver #####
00018   ==============================================================================
00019     [..]
00020       The PCD HAL driver can be used as follows:
00021 
00022      (#) Declare a PCD_HandleTypeDef handle structure, for example:
00023          PCD_HandleTypeDef  hpcd;
00024         
00025      (#) Fill parameters of Init structure in HCD handle
00026   
00027      (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...) 
00028 
00029      (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
00030          (##) Enable the PCD/USB Low Level interface clock using 
00031               (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
00032          (##) Initialize the related GPIO clocks
00033          (##) Configure PCD pin-out
00034          (##) Configure PCD NVIC interrupt
00035     
00036      (#)Associate the Upper USB device stack to the HAL PCD Driver:
00037          (##) hpcd.pData = pdev;
00038 
00039      (#)Enable PCD transmission and reception:
00040          (##) HAL_PCD_Start();
00041 
00042   @endverbatim
00043   ******************************************************************************
00044   * @attention
00045   *
00046   * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
00047   *
00048   * Redistribution and use in source and binary forms, with or without modification,
00049   * are permitted provided that the following conditions are met:
00050   *   1. Redistributions of source code must retain the above copyright notice,
00051   *      this list of conditions and the following disclaimer.
00052   *   2. Redistributions in binary form must reproduce the above copyright notice,
00053   *      this list of conditions and the following disclaimer in the documentation
00054   *      and/or other materials provided with the distribution.
00055   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00056   *      may be used to endorse or promote products derived from this software
00057   *      without specific prior written permission.
00058   *
00059   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00060   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00061   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00062   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00063   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00064   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00065   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00066   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00067   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00068   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00069   *
00070   ******************************************************************************
00071   */ 
00072 
00073 /* Includes ------------------------------------------------------------------*/
00074 #include "stm32l4xx_hal.h"
00075 
00076 /** @addtogroup STM32L4xx_HAL_Driver
00077   * @{
00078   */
00079 
00080 /** @defgroup PCD PCD
00081   * @brief PCD HAL module driver
00082   * @{
00083   */
00084 
00085 #ifdef HAL_PCD_MODULE_ENABLED
00086     
00087 #if defined(STM32L475xx) || defined(STM32L476xx) || \
00088     defined(STM32L485xx) || defined(STM32L486xx) || \
00089     defined(STM32L432xx) || defined(STM32L433xx) || \
00090     defined(STM32L442xx) || defined(STM32L443xx)
00091       
00092 /* Private types -------------------------------------------------------------*/
00093 /* Private variables ---------------------------------------------------------*/
00094 /* Private constants ---------------------------------------------------------*/
00095 /* Private macros ------------------------------------------------------------*/
00096 /** @defgroup PCD_Private_Macros PCD Private Macros
00097   * @{
00098   */
00099 #define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
00100 #define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
00101 /**
00102   * @}
00103   */
00104 
00105 /* Private functions prototypes ----------------------------------------------*/
00106 /** @defgroup PCD_Private_Functions PCD Private Functions
00107   * @{
00108   */
00109 #if defined (USB_OTG_FS)
00110 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
00111 #endif /* USB_OTG_FS */
00112 #if defined (USB)
00113 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
00114 #endif /* USB */
00115 /**
00116   * @}
00117   */
00118 
00119 /* Exported functions --------------------------------------------------------*/
00120 /** @defgroup PCD_Exported_Functions PCD Exported Functions
00121   * @{
00122   */
00123 
00124 /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions 
00125  *  @brief    Initialization and Configuration functions 
00126  *
00127 @verbatim
00128  ===============================================================================
00129             ##### Initialization and de-initialization functions #####
00130  ===============================================================================
00131     [..]  This section provides functions allowing to:
00132      
00133 @endverbatim
00134   * @{
00135   */
00136 
00137 /**
00138   * @brief  Initializes the PCD according to the specified
00139   *         parameters in the PCD_InitTypeDef and initialize the associated handle.
00140   * @param  hpcd: PCD handle
00141   * @retval HAL status
00142   */
00143 HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
00144 {
00145   uint32_t index = 0;
00146   
00147   /* Check the PCD handle allocation */
00148   if(hpcd == NULL)
00149   {
00150     return HAL_ERROR;
00151   }
00152   
00153   /* Check the parameters */
00154   assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
00155   
00156   if(hpcd->State == HAL_PCD_STATE_RESET)
00157   {
00158     /* Allocate lock resource and initialize it */
00159     hpcd->Lock = HAL_UNLOCKED;
00160     for (index = 0; index < hpcd->Init.dev_endpoints ; index++)
00161     hpcd->EPLock[index].Lock = HAL_UNLOCKED;
00162     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
00163     HAL_PCD_MspInit(hpcd);
00164   }
00165 
00166   hpcd->State = HAL_PCD_STATE_BUSY;
00167 
00168   /* Disable the Interrupts */
00169   __HAL_PCD_DISABLE(hpcd);
00170 
00171   /*Init the Core (common init.) */
00172   USB_CoreInit(hpcd->Instance, hpcd->Init);
00173 
00174   /* Force Device Mode*/
00175   USB_SetCurrentMode(hpcd->Instance , USB_DEVICE_MODE);
00176 
00177   /* Init endpoints structures */
00178   for (index = 0; index < hpcd->Init.dev_endpoints ; index++)
00179   {
00180     /* Init ep structure */
00181     hpcd->IN_ep[index].is_in = 1;
00182     hpcd->IN_ep[index].num = index;
00183     hpcd->IN_ep[index].tx_fifo_num = index;
00184     /* Control until ep is activated */
00185     hpcd->IN_ep[index].type = EP_TYPE_CTRL;
00186     hpcd->IN_ep[index].maxpacket =  0;
00187     hpcd->IN_ep[index].xfer_buff = 0;
00188     hpcd->IN_ep[index].xfer_len = 0;
00189   }
00190   
00191   for (index = 0; index < 15 ; index++)
00192   {
00193     hpcd->OUT_ep[index].is_in = 0;
00194     hpcd->OUT_ep[index].num = index;
00195     hpcd->IN_ep[index].tx_fifo_num = index;
00196     /* Control until ep is activated */
00197     hpcd->OUT_ep[index].type = EP_TYPE_CTRL;
00198     hpcd->OUT_ep[index].maxpacket = 0;
00199     hpcd->OUT_ep[index].xfer_buff = 0;
00200     hpcd->OUT_ep[index].xfer_len = 0;
00201   }
00202   /* Init Device */
00203   USB_DevInit(hpcd->Instance, hpcd->Init);
00204 
00205   hpcd->USB_Address = 0;
00206   
00207   hpcd->State= HAL_PCD_STATE_READY;
00208   
00209    /* Activate LPM */
00210   if (hpcd->Init.lpm_enable ==1)
00211   {
00212     HAL_PCDEx_ActivateLPM(hpcd);
00213   }  
00214   /* Activate Battery charging */
00215   if (hpcd->Init.battery_charging_enable ==1)
00216   {
00217     HAL_PCDEx_ActivateBCD(hpcd);
00218   }
00219   USB_DevDisconnect (hpcd->Instance);  
00220   return HAL_OK;
00221 }
00222 
00223 /**
00224   * @brief  DeInitializes the PCD peripheral.
00225   * @param  hpcd: PCD handle
00226   * @retval HAL status
00227   */
00228 HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
00229 {
00230   /* Check the PCD handle allocation */
00231   if(hpcd == NULL)
00232   {
00233     return HAL_ERROR;
00234   }
00235 
00236   hpcd->State = HAL_PCD_STATE_BUSY;
00237   
00238   /* Stop Device */
00239   HAL_PCD_Stop(hpcd);
00240     
00241   /* DeInit the low level hardware */
00242   HAL_PCD_MspDeInit(hpcd);
00243   
00244   hpcd->State = HAL_PCD_STATE_RESET; 
00245   
00246   return HAL_OK;
00247 }
00248 
00249 /**
00250   * @brief  Initializes the PCD MSP.
00251   * @param  hpcd: PCD handle
00252   * @retval None
00253   */
00254 __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
00255 {
00256   /* Prevent unused argument(s) compilation warning */
00257   UNUSED(hpcd);
00258 
00259   /* NOTE : This function should not be modified, when the callback is needed,
00260             the HAL_PCD_MspInit could be implemented in the user file
00261    */
00262 }
00263 
00264 /**
00265   * @brief  DeInitializes PCD MSP.
00266   * @param  hpcd: PCD handle
00267   * @retval None
00268   */
00269 __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
00270 {
00271   /* Prevent unused argument(s) compilation warning */
00272   UNUSED(hpcd);
00273 
00274   /* NOTE : This function should not be modified, when the callback is needed,
00275             the HAL_PCD_MspDeInit could be implemented in the user file
00276    */
00277 }
00278 
00279 /**
00280   * @}
00281   */
00282 
00283 /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions 
00284  *  @brief   Data transfers functions 
00285  *
00286 @verbatim   
00287  ===============================================================================
00288                       ##### IO operation functions #####
00289  ===============================================================================  
00290     [..]
00291     This subsection provides a set of functions allowing to manage the PCD data 
00292     transfers.
00293 
00294 @endverbatim
00295   * @{
00296   */
00297   
00298 /**
00299   * @brief  Start The USB OTG Device.
00300   * @param  hpcd: PCD handle
00301   * @retval HAL status
00302   */
00303 HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
00304 { 
00305   __HAL_LOCK(hpcd); 
00306   USB_DevConnect (hpcd->Instance);
00307   __HAL_PCD_ENABLE(hpcd);
00308   __HAL_UNLOCK(hpcd); 
00309   return HAL_OK;
00310 }
00311 
00312 /**
00313   * @brief  Stop The USB OTG Device.
00314   * @param  hpcd: PCD handle
00315   * @retval HAL status
00316   */
00317 HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
00318 { 
00319   __HAL_LOCK(hpcd); 
00320   __HAL_PCD_DISABLE(hpcd);
00321   USB_StopDevice(hpcd->Instance);
00322   USB_DevDisconnect (hpcd->Instance);
00323   __HAL_UNLOCK(hpcd); 
00324   return HAL_OK;
00325 }
00326 #if defined (USB_OTG_FS)
00327 /**
00328   * @brief  Handles PCD interrupt request.
00329   * @param  hpcd: PCD handle
00330   * @retval HAL status
00331   */
00332 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
00333 {
00334   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
00335   uint32_t index = 0, ep_intr = 0, epint = 0, epnum = 0;
00336   uint32_t fifoemptymsk = 0, temp = 0;
00337   USB_OTG_EPTypeDef *ep = NULL;
00338   uint32_t hclk = 80000000;
00339   
00340   /* ensure that we are in device mode */
00341   if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
00342   {
00343     /* avoid spurious interrupt */
00344     if(__HAL_PCD_IS_INVALID_INTERRUPT(hpcd)) 
00345     {
00346       return;
00347     }
00348     
00349     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
00350     {
00351       /* incorrect mode, acknowledge the interrupt */
00352       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
00353     }
00354     
00355     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
00356     {
00357       epnum = 0;
00358       
00359       /* Read in the device interrupt bits */
00360       ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
00361       
00362       while ( ep_intr )
00363       {
00364         if (ep_intr & 0x1)
00365         {
00366           epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, epnum);
00367           
00368           if(( epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
00369           {
00370             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
00371             
00372             if ((( (USBx_OUTEP(0)->DOEPINT & 0x8000) == 0)) )
00373             {
00374               
00375               if(hpcd->Init.dma_enable == 1)
00376               {
00377                 hpcd->OUT_ep[epnum].xfer_count = hpcd->OUT_ep[epnum].maxpacket- (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ); 
00378                 hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket;            
00379               }
00380               
00381               HAL_PCD_DataOutStageCallback(hpcd, epnum);
00382               
00383               if(hpcd->Init.dma_enable == 1)
00384               {
00385                 if((epnum == 0) && (hpcd->OUT_ep[epnum].xfer_len == 0))
00386                 {
00387                   /* this is ZLP, so prepare EP0 for next setup */
00388                   USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup);
00389                 }              
00390               }
00391             }
00392             /* Clear the SetPktRcvd flag*/ 
00393             USBx_OUTEP(0)->DOEPINT |= 0x8020;
00394           }
00395           
00396           if(( epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
00397           {
00398             /* Inform the upper layer that a setup packet is available */
00399             HAL_PCD_SetupStageCallback(hpcd);
00400             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
00401           }
00402           
00403           if(( epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
00404           {
00405             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
00406           }
00407         }
00408         epnum++;
00409         ep_intr >>= 1;
00410       }
00411     }
00412     
00413     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
00414     {
00415       /* Read in the device interrupt bits */
00416       ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
00417       
00418       epnum = 0;
00419       
00420       while ( ep_intr )
00421       {
00422         if (ep_intr & 0x1) /* In ITR */
00423         {
00424           epint = USB_ReadDevInEPInterrupt(hpcd->Instance, epnum);
00425           
00426           if(( epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
00427           {
00428             fifoemptymsk = 0x1 << epnum;
00429             atomic_clr_u32(&USBx_DEVICE->DIEPEMPMSK,  fifoemptymsk);
00430             
00431             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
00432             
00433             if (hpcd->Init.dma_enable == 1)
00434             {
00435               hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket; 
00436             }
00437             
00438             HAL_PCD_DataInStageCallback(hpcd, epnum);
00439             
00440             if (hpcd->Init.dma_enable == 1)
00441             {
00442               /* this is ZLP, so prepare EP0 for next setup */
00443               if((epnum == 0) && (hpcd->IN_ep[epnum].xfer_len == 0))
00444               {
00445                 /* prepare to rx more setup packets */
00446                 USB_EP0_OutStart(hpcd->Instance, 1, (uint8_t *)hpcd->Setup);
00447               }
00448             }           
00449           }
00450           if(( epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
00451           {
00452             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
00453           }
00454           if(( epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
00455           {
00456             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
00457           }
00458           if(( epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
00459           {
00460             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
00461           }
00462           if(( epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
00463           {
00464             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
00465           }       
00466           if(( epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
00467           {
00468             PCD_WriteEmptyTxFifo(hpcd , epnum);
00469           }
00470         }
00471         epnum++;
00472         ep_intr >>= 1;
00473       }
00474     }
00475     
00476     /* Handle Resume Interrupt */
00477     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
00478     {    
00479       /* Clear the Remote Wake-up Signaling */
00480       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
00481       
00482       if(hpcd->LPM_State == LPM_L1)
00483       {
00484         hpcd->LPM_State = LPM_L0;
00485         HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
00486       }
00487       else
00488       {
00489         HAL_PCD_ResumeCallback(hpcd);
00490       }
00491       
00492       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
00493     }
00494     
00495     /* Handle Suspend Interrupt */
00496     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
00497     {
00498       if((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
00499       {
00500         
00501         HAL_PCD_SuspendCallback(hpcd);
00502       }
00503       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
00504     }
00505     
00506     /* Handle LPM Interrupt */ 
00507     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
00508     {
00509       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);      
00510       if( hpcd->LPM_State == LPM_L0)
00511       {   
00512         hpcd->LPM_State = LPM_L1;
00513         hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >>2 ;  
00514         HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
00515       }
00516       else
00517       {
00518         HAL_PCD_SuspendCallback(hpcd);
00519       }
00520     }
00521     
00522     /* Handle Reset Interrupt */
00523     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
00524     {
00525       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG; 
00526       USB_FlushTxFifo(hpcd->Instance ,  0 );
00527       
00528       for (index = 0; index < hpcd->Init.dev_endpoints ; index++)
00529       {
00530         USBx_INEP(index)->DIEPINT = 0xFF;
00531         USBx_OUTEP(index)->DOEPINT = 0xFF;
00532       }
00533       USBx_DEVICE->DAINT = 0xFFFFFFFF;
00534       USBx_DEVICE->DAINTMSK |= 0x10001;
00535       
00536       if(hpcd->Init.use_dedicated_ep1)
00537       {
00538         USBx_DEVICE->DOUTEP1MSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM); 
00539         USBx_DEVICE->DINEP1MSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);  
00540       }
00541       else
00542       {
00543         USBx_DEVICE->DOEPMSK |= (USB_OTG_DOEPMSK_STUPM | USB_OTG_DOEPMSK_XFRCM | USB_OTG_DOEPMSK_EPDM);
00544         USBx_DEVICE->DIEPMSK |= (USB_OTG_DIEPMSK_TOM | USB_OTG_DIEPMSK_XFRCM | USB_OTG_DIEPMSK_EPDM);
00545       }
00546       
00547       /* Set Default Address to 0 */
00548       USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
00549       
00550       /* setup EP0 to receive SETUP packets */
00551       USB_EP0_OutStart(hpcd->Instance, hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
00552       
00553       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
00554     }
00555     
00556     /* Handle Enumeration done Interrupt */
00557     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
00558     {
00559       USB_ActivateSetup(hpcd->Instance);
00560       hpcd->Instance->GUSBCFG &= ~USB_OTG_GUSBCFG_TRDT;
00561       
00562       hpcd->Init.speed            = USB_OTG_SPEED_FULL;
00563       hpcd->Init.ep0_mps          = USB_OTG_FS_MAX_PACKET_SIZE ; 
00564       
00565         /* The USBTRD is configured according to the tables below, depending on AHB frequency 
00566         used by application. In the low AHB frequency range it is used to stretch enough the USB response 
00567         time to IN tokens, the USB turnaround time, so to compensate for the longer AHB read access 
00568         latency to the Data FIFO */
00569 
00570       /* Get hclk frequency value */
00571       hclk = HAL_RCC_GetHCLKFreq();
00572     
00573       if((hclk >= 14200000)&&(hclk < 15000000))
00574       {
00575         /* hclk Clock Range between 14.2-15 MHz */
00576         hpcd->Instance->GUSBCFG |= (uint32_t)((0xF << 10) & USB_OTG_GUSBCFG_TRDT);
00577       }
00578       
00579       else if((hclk >= 15000000)&&(hclk < 16000000))
00580       {
00581         /* hclk Clock Range between 15-16 MHz */
00582         hpcd->Instance->GUSBCFG |= (uint32_t)((0xE << 10) & USB_OTG_GUSBCFG_TRDT);
00583       }
00584       
00585       else if((hclk >= 16000000)&&(hclk < 17200000))
00586       {
00587         /* hclk Clock Range between 16-17.2 MHz */
00588         hpcd->Instance->GUSBCFG |= (uint32_t)((0xD << 10) & USB_OTG_GUSBCFG_TRDT);
00589       }
00590       
00591       else if((hclk >= 17200000)&&(hclk < 18500000))
00592       {
00593         /* hclk Clock Range between 17.2-18.5 MHz */
00594         hpcd->Instance->GUSBCFG |= (uint32_t)((0xC << 10) & USB_OTG_GUSBCFG_TRDT);
00595       }
00596       
00597       else if((hclk >= 18500000)&&(hclk < 20000000))
00598       {
00599         /* hclk Clock Range between 18.5-20 MHz */
00600         hpcd->Instance->GUSBCFG |= (uint32_t)((0xB << 10) & USB_OTG_GUSBCFG_TRDT);
00601       }
00602       
00603       else if((hclk >= 20000000)&&(hclk < 21800000))
00604       {
00605         /* hclk Clock Range between 20-21.8 MHz */
00606         hpcd->Instance->GUSBCFG |= (uint32_t)((0xA << 10) & USB_OTG_GUSBCFG_TRDT);
00607       }
00608       
00609       else if((hclk >= 21800000)&&(hclk < 24000000))
00610       {
00611         /* hclk Clock Range between 21.8-24 MHz */
00612         hpcd->Instance->GUSBCFG |= (uint32_t)((0x9 << 10) & USB_OTG_GUSBCFG_TRDT);
00613       }
00614       
00615       else if((hclk >= 24000000)&&(hclk < 27700000))
00616       {
00617         /* hclk Clock Range between 24-27.7 MHz */
00618         hpcd->Instance->GUSBCFG |= (uint32_t)((0x8 << 10) & USB_OTG_GUSBCFG_TRDT);
00619       }
00620       
00621       else if((hclk >= 27700000)&&(hclk < 32000000))
00622       {
00623         /* hclk Clock Range between 27.7-32 MHz */
00624         hpcd->Instance->GUSBCFG |= (uint32_t)((0x7 << 10) & USB_OTG_GUSBCFG_TRDT);
00625       }
00626       
00627       else /* if(hclk >= 32000000) */
00628       {
00629         /* hclk Clock Range between 32-80 MHz */
00630         hpcd->Instance->GUSBCFG |= (uint32_t)((0x6 << 10) & USB_OTG_GUSBCFG_TRDT);
00631       }  
00632       
00633       HAL_PCD_ResetCallback(hpcd);
00634       
00635       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
00636     }
00637     
00638     /* Handle RxQLevel Interrupt */
00639     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
00640     {
00641       USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
00642       
00643       temp = USBx->GRXSTSP;
00644       
00645       ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
00646       
00647       if(((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
00648       {
00649         if((temp & USB_OTG_GRXSTSP_BCNT) != 0)
00650         {
00651           USB_ReadPacket(USBx, ep->xfer_buff, (temp & USB_OTG_GRXSTSP_BCNT) >> 4);
00652           ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
00653           ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
00654         }
00655       }
00656       else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_SETUP_UPDT)
00657       {
00658         USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8);
00659         ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
00660       }
00661       USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
00662     }
00663     
00664     /* Handle SOF Interrupt */
00665     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
00666     {
00667       HAL_PCD_SOFCallback(hpcd);
00668       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
00669     }
00670     
00671     /* Handle Incomplete ISO IN Interrupt */
00672     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
00673     {
00674       HAL_PCD_ISOINIncompleteCallback(hpcd, epnum);
00675       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
00676     } 
00677     
00678     /* Handle Incomplete ISO OUT Interrupt */
00679     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
00680     {
00681       HAL_PCD_ISOOUTIncompleteCallback(hpcd, epnum);
00682       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
00683     } 
00684     
00685     /* Handle Connection event Interrupt */
00686     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
00687     {
00688       HAL_PCD_ConnectCallback(hpcd);
00689       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
00690     } 
00691     
00692     /* Handle Disconnection event Interrupt */
00693     if(__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
00694     {
00695       temp = hpcd->Instance->GOTGINT;
00696       
00697       if((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
00698       {
00699         HAL_PCD_DisconnectCallback(hpcd);
00700       }
00701       hpcd->Instance->GOTGINT |= temp;
00702     }
00703   }
00704 }
00705 
00706 #endif /* USB_OTG_FS */
00707 
00708 #if defined (USB)
00709 /**
00710   * @brief  This function handles PCD interrupt request.
00711   * @param  hpcd: PCD handle
00712   * @retval HAL status
00713   */
00714 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
00715 {
00716   uint32_t wInterrupt_Mask = 0;
00717   
00718   if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_CTR))
00719   {
00720     /* servicing of the endpoint correct transfer interrupt */
00721     /* clear of the CTR flag into the sub */
00722     PCD_EP_ISR_Handler(hpcd);
00723   }
00724 
00725   if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_RESET))
00726   {
00727     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
00728     HAL_PCD_ResetCallback(hpcd);
00729     HAL_PCD_SetAddress(hpcd, 0);
00730   }
00731 
00732   if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_PMAOVR))
00733   {
00734     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);    
00735   }
00736 
00737   if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ERR))
00738   {
00739     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR); 
00740   }
00741 
00742   if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP))
00743   {
00744     
00745     hpcd->Instance->CNTR &= ~(USB_CNTR_LPMODE);
00746 
00747     /*set wInterrupt_Mask global variable*/
00748     wInterrupt_Mask = USB_CNTR_CTRM  | USB_CNTR_WKUPM | USB_CNTR_SUSPM | USB_CNTR_ERRM \
00749       | USB_CNTR_SOFM | USB_CNTR_ESOFM | USB_CNTR_RESETM;
00750     
00751     /*Set interrupt mask*/
00752     hpcd->Instance->CNTR = wInterrupt_Mask;
00753 
00754     /* enable L1REQ interrupt */ 
00755     if (hpcd->Init.lpm_enable ==1)
00756     {
00757       wInterrupt_Mask |= USB_CNTR_L1REQM;
00758       
00759       /* Enable LPM support and enable ACK answer to LPM request*/
00760       USB_TypeDef *USBx = hpcd->Instance;
00761       hpcd->lpm_active = ENABLE;
00762       hpcd->LPM_State = LPM_L0;
00763       
00764       USBx->LPMCSR |= (USB_LPMCSR_LMPEN);
00765       USBx->LPMCSR |= (USB_LPMCSR_LPMACK);
00766     } 
00767     
00768     if(hpcd->LPM_State == LPM_L1)
00769     {
00770       hpcd->LPM_State = LPM_L0;
00771       HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
00772     }
00773     
00774     HAL_PCD_ResumeCallback(hpcd);
00775     
00776     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);     
00777   }
00778 
00779   if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SUSP))
00780   {    
00781     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
00782     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);  
00783     
00784     /* Force low-power mode in the macrocell */
00785     hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
00786     hpcd->Instance->CNTR |= USB_CNTR_LPMODE;
00787 
00788     if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_WKUP) == 0)
00789     {
00790       HAL_PCD_SuspendCallback(hpcd);
00791     }
00792   }
00793 
00794   /* Handle LPM Interrupt */ 
00795   if(__HAL_PCD_GET_FLAG(hpcd, USB_ISTR_L1REQ))
00796   {
00797     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ);      
00798     if( hpcd->LPM_State == LPM_L0)
00799     {   
00800       /* Force suspend and low-power mode before going to L1 state*/
00801       hpcd->Instance->CNTR |= USB_CNTR_LPMODE;
00802       hpcd->Instance->CNTR |= USB_CNTR_FSUSP;
00803       
00804       hpcd->LPM_State = LPM_L1;
00805       hpcd->BESL = (hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >>2 ;  
00806       HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
00807     }
00808     else
00809     {
00810       HAL_PCD_SuspendCallback(hpcd);
00811     }
00812   }
00813 
00814   if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_SOF))
00815   {
00816     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF); 
00817     HAL_PCD_SOFCallback(hpcd);
00818   }
00819 
00820   if (__HAL_PCD_GET_FLAG (hpcd, USB_ISTR_ESOF))
00821   {
00822     /* clear ESOF flag in ISTR */
00823     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF); 
00824   }
00825 }
00826 #endif /* USB */
00827 
00828 /**
00829   * @brief  Data OUT stage callback.
00830   * @param  hpcd: PCD handle
00831   * @param  epnum: endpoint number
00832   * @retval None
00833   */
00834 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
00835 {
00836   /* Prevent unused argument(s) compilation warning */
00837   UNUSED(hpcd);
00838   UNUSED(epnum);
00839 
00840   /* NOTE : This function should not be modified, when the callback is needed,
00841             the HAL_PCD_DataOutStageCallback could be implemented in the user file
00842    */ 
00843 }
00844 
00845 /**
00846   * @brief  Data IN stage callback.
00847   * @param  hpcd: PCD handle
00848   * @param  epnum: endpoint number
00849   * @retval None
00850   */
00851 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
00852 {
00853   /* Prevent unused argument(s) compilation warning */
00854   UNUSED(hpcd);
00855   UNUSED(epnum);
00856 
00857   /* NOTE : This function should not be modified, when the callback is needed,
00858             the HAL_PCD_DataInStageCallback could be implemented in the user file
00859    */ 
00860 }
00861 /**
00862   * @brief  Setup stage callback.
00863   * @param  hpcd: PCD handle
00864   * @retval None
00865   */
00866 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
00867 {
00868   /* Prevent unused argument(s) compilation warning */
00869   UNUSED(hpcd);
00870 
00871   /* NOTE : This function should not be modified, when the callback is needed,
00872             the HAL_PCD_SetupStageCallback could be implemented in the user file
00873    */ 
00874 }
00875 
00876 /**
00877   * @brief  USB Start Of Frame callback.
00878   * @param  hpcd: PCD handle
00879   * @retval None
00880   */
00881 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
00882 {
00883   /* Prevent unused argument(s) compilation warning */
00884   UNUSED(hpcd);
00885 
00886   /* NOTE : This function should not be modified, when the callback is needed,
00887             the HAL_PCD_SOFCallback could be implemented in the user file
00888    */ 
00889 }
00890 
00891 /**
00892   * @brief  USB Reset callback.
00893   * @param  hpcd: PCD handle
00894   * @retval None
00895   */
00896 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
00897 {
00898   /* Prevent unused argument(s) compilation warning */
00899   UNUSED(hpcd);
00900 
00901   /* NOTE : This function should not be modified, when the callback is needed,
00902             the HAL_PCD_ResetCallback could be implemented in the user file
00903    */ 
00904 }
00905 
00906 /**
00907   * @brief  Suspend event callback.
00908   * @param  hpcd: PCD handle
00909   * @retval None
00910   */
00911 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
00912 {
00913   /* Prevent unused argument(s) compilation warning */
00914   UNUSED(hpcd);
00915 
00916   /* NOTE : This function should not be modified, when the callback is needed,
00917             the HAL_PCD_SuspendCallback could be implemented in the user file
00918    */ 
00919 }
00920 
00921 /**
00922   * @brief  Resume event callback.
00923   * @param  hpcd: PCD handle
00924   * @retval None
00925   */
00926 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
00927 {
00928   /* Prevent unused argument(s) compilation warning */
00929   UNUSED(hpcd);
00930 
00931   /* NOTE : This function should not be modified, when the callback is needed,
00932             the HAL_PCD_ResumeCallback could be implemented in the user file
00933    */ 
00934 }
00935 
00936 /**
00937   * @brief  Incomplete ISO OUT callback.
00938   * @param  hpcd: PCD handle
00939   * @param  epnum: endpoint number
00940   * @retval None
00941   */
00942 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
00943 {
00944   /* Prevent unused argument(s) compilation warning */
00945   UNUSED(hpcd);
00946   UNUSED(epnum);
00947 
00948   /* NOTE : This function should not be modified, when the callback is needed,
00949             the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
00950    */ 
00951 }
00952 
00953 /**
00954   * @brief  Incomplete ISO IN callback.
00955   * @param  hpcd: PCD handle
00956   * @param  epnum: endpoint number
00957   * @retval None
00958   */
00959 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
00960 {
00961   /* Prevent unused argument(s) compilation warning */
00962   UNUSED(hpcd);
00963   UNUSED(epnum);
00964 
00965   /* NOTE : This function should not be modified, when the callback is needed,
00966             the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
00967    */ 
00968 }
00969 
00970 /**
00971   * @brief  Connection event callback.
00972   * @param  hpcd: PCD handle
00973   * @retval None
00974   */
00975 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
00976 {
00977   /* Prevent unused argument(s) compilation warning */
00978   UNUSED(hpcd);
00979 
00980   /* NOTE : This function should not be modified, when the callback is needed,
00981             the HAL_PCD_ConnectCallback could be implemented in the user file
00982    */ 
00983 }
00984 
00985 /**
00986   * @brief  Disconnection event callback.
00987   * @param  hpcd: PCD handle
00988   * @retval None
00989   */
00990 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
00991 {
00992   /* Prevent unused argument(s) compilation warning */
00993   UNUSED(hpcd);
00994 
00995   /* NOTE : This function should not be modified, when the callback is needed,
00996             the HAL_PCD_DisconnectCallback could be implemented in the user file
00997    */ 
00998 }
00999 
01000 /**
01001   * @}
01002   */
01003   
01004 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions 
01005  *  @brief   management functions 
01006  *
01007 @verbatim   
01008  ===============================================================================
01009                       ##### Peripheral Control functions #####
01010  ===============================================================================  
01011     [..]
01012     This subsection provides a set of functions allowing to control the PCD data 
01013     transfers.
01014 
01015 @endverbatim
01016   * @{
01017   */
01018 
01019 /**
01020   * @brief  Connect the USB device.
01021   * @param  hpcd: PCD handle
01022   * @retval HAL status
01023   */
01024 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
01025 {
01026   __HAL_LOCK(hpcd); 
01027   USB_DevConnect(hpcd->Instance);
01028   __HAL_UNLOCK(hpcd); 
01029   return HAL_OK;
01030 }
01031 
01032 /**
01033   * @brief  Disconnect the USB device.
01034   * @param  hpcd: PCD handle
01035   * @retval HAL status
01036   */
01037 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
01038 {
01039   __HAL_LOCK(hpcd); 
01040   USB_DevDisconnect(hpcd->Instance);
01041   __HAL_UNLOCK(hpcd); 
01042   return HAL_OK;
01043 }
01044 
01045 /**
01046   * @brief  Set the USB Device address.
01047   * @param  hpcd: PCD handle
01048   * @param  address: new device address
01049   * @retval HAL status
01050   */
01051 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
01052 {
01053   __HAL_LOCK(hpcd); 
01054   hpcd->USB_Address = address;
01055   USB_SetDevAddress(hpcd->Instance, address);
01056   __HAL_UNLOCK(hpcd);   
01057   return HAL_OK;
01058 }
01059 /**
01060   * @brief  Open and configure an endpoint.
01061   * @param  hpcd: PCD handle
01062   * @param  ep_addr: endpoint address
01063   * @param  ep_mps: endpoint max packet size
01064   * @param  ep_type: endpoint type   
01065   * @retval HAL status
01066   */
01067 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint16_t ep_mps, uint8_t ep_type)
01068 {
01069   HAL_StatusTypeDef  ret = HAL_OK;
01070   PCD_EPTypeDef *ep = NULL;
01071   
01072   if ((ep_addr & 0x80) == 0x80)
01073   {
01074     ep = &hpcd->IN_ep[ep_addr & 0x7F];
01075   }
01076   else
01077   {
01078     ep = &hpcd->OUT_ep[ep_addr & 0x7F];
01079   }
01080   ep->num   = ep_addr & 0x7F;
01081   
01082   ep->is_in = (0x80 & ep_addr) != 0;
01083   ep->maxpacket = ep_mps;
01084   ep->type = ep_type;
01085     
01086   __HAL_LOCK(hpcd);
01087   USB_ActivateEndpoint(hpcd->Instance , ep);
01088   __HAL_UNLOCK(hpcd);
01089   return ret;
01090 
01091 }
01092 
01093 
01094 /**
01095   * @brief  Deactivate an endpoint.
01096   * @param  hpcd: PCD handle
01097   * @param  ep_addr: endpoint address
01098   * @retval HAL status
01099   */
01100 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01101 {  
01102   PCD_EPTypeDef *ep = NULL;
01103   
01104   if ((ep_addr & 0x80) == 0x80)
01105   {
01106     ep = &hpcd->IN_ep[ep_addr & 0x7F];
01107   }
01108   else
01109   {
01110     ep = &hpcd->OUT_ep[ep_addr & 0x7F];
01111   }
01112   ep->num   = ep_addr & 0x7F;
01113   
01114   ep->is_in = (0x80 & ep_addr) != 0;
01115   
01116   __HAL_LOCK(hpcd); 
01117   USB_DeactivateEndpoint(hpcd->Instance , ep);
01118   __HAL_UNLOCK(hpcd);   
01119   return HAL_OK;
01120 }
01121 
01122 
01123 /**
01124   * @brief  Receive an amount of data.
01125   * @param  hpcd: PCD handle
01126   * @param  ep_addr: endpoint address
01127   * @param  pBuf: pointer to the reception buffer   
01128   * @param  len: amount of data to be received
01129   * @retval HAL status
01130   */
01131 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
01132 {
01133   PCD_EPTypeDef *ep = NULL;
01134   
01135   ep = &hpcd->OUT_ep[ep_addr & 0x7F];
01136   
01137   /*setup and start the Xfer */
01138   ep->xfer_buff = pBuf;  
01139   ep->xfer_len = len;
01140   ep->xfer_count = 0;
01141   ep->is_in = 0;
01142   ep->num = ep_addr & 0x7F;
01143   
01144   __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01145   
01146   if ((ep_addr & 0x7F) == 0 )
01147   {
01148     USB_EP0StartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable);
01149   }
01150   else
01151   {
01152     USB_EPStartXfer(hpcd->Instance, ep, hpcd->Init.dma_enable);
01153   }
01154   __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01155   
01156   return HAL_OK;
01157 }
01158 
01159 /**
01160   * @brief  Get Received Data Size.
01161   * @param  hpcd: PCD handle
01162   * @param  ep_addr: endpoint address
01163   * @retval Data Size
01164   */
01165 uint16_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01166 {
01167   return hpcd->OUT_ep[ep_addr & 0x7F].xfer_count;
01168 }
01169 /**
01170   * @brief  Send an amount of data.
01171   * @param  hpcd: PCD handle
01172   * @param  ep_addr: endpoint address
01173   * @param  pBuf: pointer to the transmission buffer   
01174   * @param  len: amount of data to be sent
01175   * @retval HAL status
01176   */
01177 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
01178 {
01179   PCD_EPTypeDef *ep = NULL;
01180   
01181   ep = &hpcd->IN_ep[ep_addr & 0x7F];
01182   
01183   /*setup and start the Xfer */
01184   ep->xfer_buff = pBuf;  
01185   ep->xfer_len = len;
01186   ep->xfer_count = 0;
01187   ep->is_in = 1;
01188   ep->num = ep_addr & 0x7F;
01189   
01190   __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01191   
01192   if ((ep_addr & 0x7F) == 0 )
01193   {
01194     USB_EP0StartXfer(hpcd->Instance,ep,  hpcd->Init.dma_enable);
01195   }
01196   else
01197   {
01198     USB_EPStartXfer(hpcd->Instance, ep,  hpcd->Init.dma_enable);
01199   }
01200   
01201   __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01202   
01203   return HAL_OK;
01204 }
01205 
01206 /**
01207   * @brief  Set a STALL condition over an endpoint.
01208   * @param  hpcd: PCD handle
01209   * @param  ep_addr: endpoint address
01210   * @retval HAL status
01211   */
01212 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01213 {
01214   PCD_EPTypeDef *ep = NULL;
01215   
01216   if ((0x80 & ep_addr) == 0x80)
01217   {
01218     ep = &hpcd->IN_ep[ep_addr & 0x7F];
01219   }
01220   else
01221   {
01222     ep = &hpcd->OUT_ep[ep_addr];
01223   }
01224   
01225   ep->is_stall = 1;
01226   ep->num   = ep_addr & 0x7F;
01227   ep->is_in = ((ep_addr & 0x80) == 0x80);
01228   
01229   __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01230   USB_EPSetStall(hpcd->Instance , ep);
01231   if((ep_addr & 0x7F) == 0)
01232   {
01233     USB_EP0_OutStart(hpcd->Instance,  hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
01234   }
01235   __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01236   
01237   return HAL_OK;
01238 }
01239 
01240 /**
01241   * @brief  Clear a STALL condition over in an endpoint.
01242   * @param  hpcd: PCD handle
01243   * @param  ep_addr: endpoint address
01244   * @retval HAL status
01245   */
01246 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01247 {
01248   PCD_EPTypeDef *ep = NULL;
01249   
01250   if ((0x80 & ep_addr) == 0x80)
01251   {
01252     ep = &hpcd->IN_ep[ep_addr & 0x7F];
01253   }
01254   else
01255   {
01256     ep = &hpcd->OUT_ep[ep_addr];
01257   }
01258   
01259   ep->is_stall = 0;
01260   ep->num   = ep_addr & 0x7F;
01261   ep->is_in = ((ep_addr & 0x80) == 0x80);
01262   
01263   __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01264   USB_EPClearStall(hpcd->Instance , ep);
01265   __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01266     
01267   return HAL_OK;
01268 }
01269 
01270 /**
01271   * @brief  Flush an endpoint.
01272   * @param  hpcd: PCD handle
01273   * @param  ep_addr: endpoint address
01274   * @retval HAL status
01275   */
01276 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
01277 {
01278   __HAL_LOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01279   if ((ep_addr & 0x80) == 0x80)
01280   {
01281     USB_FlushTxFifo(hpcd->Instance, ep_addr & 0x7F);
01282   }
01283   else
01284   {
01285     USB_FlushRxFifo(hpcd->Instance);
01286   }
01287   
01288   __HAL_UNLOCK(&hpcd->EPLock[ep_addr & 0x7F]);
01289     
01290   return HAL_OK;
01291 }
01292 
01293 /**
01294   * @brief  Activate remote wakeup signalling.
01295   * @param  hpcd: PCD handle
01296   * @retval HAL status
01297   */
01298 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
01299 {
01300   return(USB_ActivateRemoteWakeup(hpcd->Instance)); 
01301 }
01302 
01303 /**
01304   * @brief  De-activate remote wakeup signalling.
01305   * @param  hpcd: PCD handle
01306   * @retval HAL status
01307   */
01308 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
01309 {
01310   return(USB_DeActivateRemoteWakeup(hpcd->Instance));
01311 }
01312 /**
01313   * @}
01314   */
01315   
01316 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions 
01317  *  @brief   Peripheral State functions 
01318  *
01319 @verbatim   
01320  ===============================================================================
01321                       ##### Peripheral State functions #####
01322  ===============================================================================  
01323     [..]
01324     This subsection permits to get in run-time the status of the peripheral 
01325     and the data flow.
01326 
01327 @endverbatim
01328   * @{
01329   */
01330 
01331 /**
01332   * @brief  Return the PCD handle state.
01333   * @param  hpcd: PCD handle
01334   * @retval HAL state
01335   */
01336 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
01337 {
01338   return hpcd->State;
01339 }
01340 /**
01341   * @}
01342   */
01343 
01344 /**
01345   * @}
01346   */
01347 
01348 /* Private functions ---------------------------------------------------------*/
01349 /** @addtogroup PCD_Private_Functions
01350   * @{
01351   */
01352 #if defined (USB_OTG_FS)
01353 /**
01354   * @brief  Check FIFO for the next packet to be loaded.
01355   * @param  hpcd: PCD handle
01356   * @param  epnum: endpoint number
01357   * @retval HAL status
01358   */
01359 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
01360 {
01361   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;  
01362   USB_OTG_EPTypeDef *ep = NULL;
01363   int32_t len = 0;
01364   uint32_t len32b = 0;
01365   uint32_t fifoemptymsk = 0;
01366 
01367   ep = &hpcd->IN_ep[epnum];
01368   len = ep->xfer_len - ep->xfer_count;
01369   
01370   if (len > ep->maxpacket)
01371   {
01372     len = ep->maxpacket;
01373   }
01374   
01375   
01376   len32b = (len + 3) / 4;
01377  
01378   while  ( (USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) > len32b &&
01379           ep->xfer_count < ep->xfer_len &&
01380             ep->xfer_len != 0)
01381   {
01382     /* Write the FIFO */
01383     len = ep->xfer_len - ep->xfer_count;
01384     
01385     if (len > ep->maxpacket)
01386     {
01387       len = ep->maxpacket;
01388     }
01389     len32b = (len + 3) / 4;
01390     
01391     USB_WritePacket(USBx, ep->xfer_buff, epnum, len, hpcd->Init.dma_enable); 
01392     
01393     ep->xfer_buff  += len;
01394     ep->xfer_count += len;
01395   }
01396   
01397   if(len <= 0)
01398   {
01399     fifoemptymsk = 0x1 << epnum;
01400     atomic_clr_u32(&USBx_DEVICE->DIEPEMPMSK, fifoemptymsk);
01401     
01402   }
01403   
01404   return HAL_OK;  
01405 }
01406 #endif /* USB_OTG_FS */
01407 
01408 #if defined (USB)
01409 /**
01410   * @brief  This function handles PCD Endpoint interrupt request.
01411   * @param  hpcd: PCD handle
01412   * @retval HAL status
01413   */
01414 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
01415 {
01416   PCD_EPTypeDef *ep = NULL;
01417   uint16_t count = 0;
01418   uint8_t epindex = 0;
01419   __IO uint16_t wIstr = 0;  
01420   __IO uint16_t wEPVal = 0;
01421   
01422   /* stay in loop while pending interrupts */
01423   while (((wIstr = hpcd->Instance->ISTR) & USB_ISTR_CTR) != 0)
01424   {
01425     /* extract highest priority endpoint number */
01426     epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
01427     
01428     if (epindex == 0)
01429     {
01430       /* Decode and service control endpoint interrupt */
01431       
01432       /* DIR bit = origin of the interrupt */   
01433       if ((wIstr & USB_ISTR_DIR) == 0)
01434       {
01435         /* DIR = 0 */
01436         
01437         /* DIR = 0      => IN  int */
01438         /* DIR = 0 implies that (EP_CTR_TX = 1) always  */
01439         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
01440         ep = &hpcd->IN_ep[0];
01441         
01442         ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
01443         ep->xfer_buff += ep->xfer_count;
01444  
01445         /* TX COMPLETE */
01446         HAL_PCD_DataInStageCallback(hpcd, 0);
01447         
01448         
01449         if((hpcd->USB_Address > 0)&& ( ep->xfer_len == 0))
01450         {
01451           hpcd->Instance->DADDR = (hpcd->USB_Address | USB_DADDR_EF);
01452           hpcd->USB_Address = 0;
01453         }
01454         
01455       }
01456       else
01457       {
01458         /* DIR = 1 */
01459         
01460         /* DIR = 1 & CTR_RX       => SETUP or OUT int */
01461         /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
01462         ep = &hpcd->OUT_ep[0];
01463         wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
01464         
01465         if ((wEPVal & USB_EP_SETUP) != 0)
01466         {
01467           /* Get SETUP Packet*/
01468           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
01469           USB_ReadPMA(hpcd->Instance, (uint8_t*)hpcd->Setup ,ep->pmaadress , ep->xfer_count);       
01470           /* SETUP bit kept frozen while CTR_RX = 1*/ 
01471           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0); 
01472           
01473           /* Process SETUP Packet*/
01474           HAL_PCD_SetupStageCallback(hpcd);
01475         }
01476         
01477         else if ((wEPVal & USB_EP_CTR_RX) != 0)
01478         {
01479           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
01480           /* Get Control Data OUT Packet*/
01481           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
01482           
01483           if (ep->xfer_count != 0)
01484           {
01485             USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
01486             ep->xfer_buff+=ep->xfer_count;
01487           }
01488           
01489           /* Process Control Data OUT Packet*/
01490            HAL_PCD_DataOutStageCallback(hpcd, 0);
01491           
01492           PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
01493           PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
01494         }
01495       }
01496     }
01497     else
01498     {
01499       /* Decode and service non control endpoints interrupt  */
01500       
01501       /* process related endpoint register */
01502       wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
01503       if ((wEPVal & USB_EP_CTR_RX) != 0)
01504       {  
01505         /* clear int flag */
01506         PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
01507         ep = &hpcd->OUT_ep[epindex];
01508         
01509         /* OUT double Buffering*/
01510         if (ep->doublebuffer == 0)
01511         {
01512           count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
01513           if (count != 0)
01514           {
01515             USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
01516           }
01517         }
01518         else
01519         {
01520           if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX)
01521           {
01522             /*read from endpoint BUF0Addr buffer*/
01523             count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
01524             if (count != 0)
01525             {
01526               USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
01527             }
01528           }
01529           else
01530           {
01531             /*read from endpoint BUF1Addr buffer*/
01532             count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
01533             if (count != 0)
01534             {
01535               USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
01536             }
01537           }
01538           PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_OUT);  
01539         }
01540         /*multi-packet on the NON control OUT endpoint*/
01541         ep->xfer_count+=count;
01542         ep->xfer_buff+=count;
01543        
01544         if ((ep->xfer_len == 0) || (count < ep->maxpacket))
01545         {
01546           /* RX COMPLETE */
01547           HAL_PCD_DataOutStageCallback(hpcd, ep->num);
01548         }
01549         else
01550         {
01551           HAL_PCD_EP_Receive(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
01552         }
01553         
01554       } /* if((wEPVal & EP_CTR_RX) */
01555       
01556       if ((wEPVal & USB_EP_CTR_TX) != 0)
01557       {
01558         ep = &hpcd->IN_ep[epindex];
01559         
01560         /* clear int flag */
01561         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
01562         
01563         /* IN double Buffering*/
01564         if (ep->doublebuffer == 0)
01565         {
01566           ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
01567           if (ep->xfer_count != 0)
01568           {
01569             USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, ep->xfer_count);
01570           }
01571         }
01572         else
01573         {
01574           if (PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_TX)
01575           {
01576             /*read from endpoint BUF0Addr buffer*/
01577             ep->xfer_count = PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
01578             if (ep->xfer_count != 0)
01579             {
01580               USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, ep->xfer_count);
01581             }
01582           }
01583           else
01584           {
01585             /*read from endpoint BUF1Addr buffer*/
01586             ep->xfer_count = PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
01587             if (ep->xfer_count != 0)
01588             {
01589               USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, ep->xfer_count);
01590             }
01591           }
01592           PCD_FreeUserBuffer(hpcd->Instance, ep->num, PCD_EP_DBUF_IN);  
01593         }
01594         /*multi-packet on the NON control IN endpoint*/
01595         ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
01596         ep->xfer_buff+=ep->xfer_count;
01597        
01598         /* Zero Length Packet? */
01599         if (ep->xfer_len == 0)
01600         {
01601           /* TX COMPLETE */
01602           HAL_PCD_DataInStageCallback(hpcd, ep->num);
01603         }
01604         else
01605         {
01606           HAL_PCD_EP_Transmit(hpcd, ep->num, ep->xfer_buff, ep->xfer_len);
01607         }
01608       } 
01609     }
01610   }
01611   return HAL_OK;
01612 }
01613 #endif /* USB */
01614 
01615 /**
01616   * @}
01617   */
01618 
01619 /**
01620   * @}
01621   */
01622   
01623 #endif /* STM32L475xx || STM32L476xx || */
01624        /* STM32L485xx || STM32L486xx || */
01625        /* STM32L432xx || STM32L433xx || */
01626        /* STM32L442xx || STM32L443xx    */
01627 
01628 #endif /* HAL_PCD_MODULE_ENABLED */
01629 
01630 
01631 /**
01632   * @}
01633   */
01634 
01635 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/