STM32L443xx HAL User Manual
stm32l4xx_hal_pcd_ex.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_pcd_ex.c
00004   * @author  MCD Application Team
00005   * @brief   PCD Extended HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the USB Peripheral Controller:
00008   *           + Extended features functions
00009   *
00010   ******************************************************************************
00011   * @attention
00012   *
00013   * Copyright (c) 2017 STMicroelectronics.
00014   * All rights reserved.
00015   *
00016   * This software is licensed under terms that can be found in the LICENSE file
00017   * in the root directory of this software component.
00018   * If no LICENSE file comes with this software, it is provided AS-IS.
00019   *
00020   ******************************************************************************
00021   */
00022 
00023 /* Includes ------------------------------------------------------------------*/
00024 #include "stm32l4xx_hal.h"
00025 
00026 /** @addtogroup STM32L4xx_HAL_Driver
00027   * @{
00028   */
00029 
00030 /** @defgroup PCDEx PCDEx
00031   * @brief PCD Extended HAL module driver
00032   * @{
00033   */
00034 
00035 #ifdef HAL_PCD_MODULE_ENABLED
00036 
00037 #if defined (USB) || defined (USB_OTG_FS)
00038 /* Private types -------------------------------------------------------------*/
00039 /* Private variables ---------------------------------------------------------*/
00040 /* Private constants ---------------------------------------------------------*/
00041 /* Private macros ------------------------------------------------------------*/
00042 /* Private functions ---------------------------------------------------------*/
00043 /* Exported functions --------------------------------------------------------*/
00044 
00045 /** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions
00046   * @{
00047   */
00048 
00049 /** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions
00050   * @brief    PCDEx control functions
00051   *
00052 @verbatim
00053  ===============================================================================
00054                  ##### Extended features functions #####
00055  ===============================================================================
00056     [..]  This section provides functions allowing to:
00057       (+) Update FIFO configuration
00058 
00059 @endverbatim
00060   * @{
00061   */
00062 #if defined (USB_OTG_FS)
00063 /**
00064   * @brief  Set Tx FIFO
00065   * @param  hpcd PCD handle
00066   * @param  fifo The number of Tx fifo
00067   * @param  size Fifo size
00068   * @retval HAL status
00069   */
00070 HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size)
00071 {
00072   uint8_t i;
00073   uint32_t Tx_Offset;
00074 
00075   /*  TXn min size = 16 words. (n  : Transmit FIFO index)
00076       When a TxFIFO is not used, the Configuration should be as follows:
00077           case 1 :  n > m    and Txn is not used    (n,m  : Transmit FIFO indexes)
00078          --> Txm can use the space allocated for Txn.
00079          case2  :  n < m    and Txn is not used    (n,m  : Transmit FIFO indexes)
00080          --> Txn should be configured with the minimum space of 16 words
00081      The FIFO is used optimally when used TxFIFOs are allocated in the top
00082          of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
00083      When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */
00084 
00085   Tx_Offset = hpcd->Instance->GRXFSIZ;
00086 
00087   if (fifo == 0U)
00088   {
00089     hpcd->Instance->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset;
00090   }
00091   else
00092   {
00093     Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16;
00094     for (i = 0U; i < (fifo - 1U); i++)
00095     {
00096       Tx_Offset += (hpcd->Instance->DIEPTXF[i] >> 16);
00097     }
00098 
00099     /* Multiply Tx_Size by 2 to get higher performance */
00100     hpcd->Instance->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset;
00101   }
00102 
00103   return HAL_OK;
00104 }
00105 
00106 /**
00107   * @brief  Set Rx FIFO
00108   * @param  hpcd PCD handle
00109   * @param  size Size of Rx fifo
00110   * @retval HAL status
00111   */
00112 HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size)
00113 {
00114   hpcd->Instance->GRXFSIZ = size;
00115 
00116   return HAL_OK;
00117 }
00118 
00119 /**
00120   * @brief  Activate LPM feature.
00121   * @param  hpcd PCD handle
00122   * @retval HAL status
00123   */
00124 HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd)
00125 {
00126   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
00127 
00128   hpcd->lpm_active = 1U;
00129   hpcd->LPM_State = LPM_L0;
00130   USBx->GINTMSK |= USB_OTG_GINTMSK_LPMINTM;
00131   USBx->GLPMCFG |= (USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
00132 
00133   return HAL_OK;
00134 }
00135 
00136 /**
00137   * @brief  Deactivate LPM feature.
00138   * @param  hpcd PCD handle
00139   * @retval HAL status
00140   */
00141 HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd)
00142 {
00143   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
00144 
00145   hpcd->lpm_active = 0U;
00146   USBx->GINTMSK &= ~USB_OTG_GINTMSK_LPMINTM;
00147   USBx->GLPMCFG &= ~(USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
00148 
00149   return HAL_OK;
00150 }
00151 
00152 
00153 /**
00154   * @brief  Handle BatteryCharging Process.
00155   * @param  hpcd PCD handle
00156   * @retval HAL status
00157   */
00158 void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd)
00159 {
00160   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
00161   uint32_t tickstart = HAL_GetTick();
00162 
00163   /* Enable DCD : Data Contact Detect */
00164   USBx->GCCFG |= USB_OTG_GCCFG_DCDEN;
00165 
00166   /* Wait Detect flag or a timeout is happen */
00167   while ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == 0U)
00168   {
00169     /* Check for the Timeout */
00170     if ((HAL_GetTick() - tickstart) > 1000U)
00171     {
00172 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00173       hpcd->BCDCallback(hpcd, PCD_BCD_ERROR);
00174 #else
00175       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR);
00176 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00177 
00178       return;
00179     }
00180   }
00181 
00182   /* Right response got */
00183   HAL_Delay(200U);
00184 
00185   /* Check Detect flag*/
00186   if ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == USB_OTG_GCCFG_DCDET)
00187   {
00188 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00189     hpcd->BCDCallback(hpcd, PCD_BCD_CONTACT_DETECTION);
00190 #else
00191     HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION);
00192 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00193   }
00194 
00195   /*Primary detection: checks if connected to Standard Downstream Port
00196   (without charging capability) */
00197   USBx->GCCFG &= ~ USB_OTG_GCCFG_DCDEN;
00198   HAL_Delay(50U);
00199   USBx->GCCFG |=  USB_OTG_GCCFG_PDEN;
00200   HAL_Delay(50U);
00201 
00202   if ((USBx->GCCFG & USB_OTG_GCCFG_PDET) == 0U)
00203   {
00204     /* Case of Standard Downstream Port */
00205 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00206     hpcd->BCDCallback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
00207 #else
00208     HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
00209 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00210   }
00211   else
00212   {
00213     /* start secondary detection to check connection to Charging Downstream
00214     Port or Dedicated Charging Port */
00215     USBx->GCCFG &= ~ USB_OTG_GCCFG_PDEN;
00216     HAL_Delay(50U);
00217     USBx->GCCFG |=  USB_OTG_GCCFG_SDEN;
00218     HAL_Delay(50U);
00219 
00220     if ((USBx->GCCFG & USB_OTG_GCCFG_SDET) == USB_OTG_GCCFG_SDET)
00221     {
00222       /* case Dedicated Charging Port  */
00223 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00224       hpcd->BCDCallback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
00225 #else
00226       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
00227 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00228     }
00229     else
00230     {
00231       /* case Charging Downstream Port  */
00232 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00233       hpcd->BCDCallback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
00234 #else
00235       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
00236 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00237     }
00238   }
00239 
00240   /* Battery Charging capability discovery finished */
00241   (void)HAL_PCDEx_DeActivateBCD(hpcd);
00242 
00243 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00244   hpcd->BCDCallback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
00245 #else
00246   HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
00247 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00248 }
00249 
00250 /**
00251   * @brief  Activate BatteryCharging feature.
00252   * @param  hpcd PCD handle
00253   * @retval HAL status
00254   */
00255 HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd)
00256 {
00257   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
00258 
00259   USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
00260   USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
00261 
00262   /* Power Down USB transceiver  */
00263   USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
00264 
00265   /* Enable Battery charging */
00266   USBx->GCCFG |= USB_OTG_GCCFG_BCDEN;
00267 
00268   hpcd->battery_charging_active = 1U;
00269 
00270   return HAL_OK;
00271 }
00272 
00273 /**
00274   * @brief  Deactivate BatteryCharging feature.
00275   * @param  hpcd PCD handle
00276   * @retval HAL status
00277   */
00278 HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd)
00279 {
00280   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
00281 
00282   USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
00283   USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
00284 
00285   /* Disable Battery charging */
00286   USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
00287 
00288   hpcd->battery_charging_active = 0U;
00289 
00290   return HAL_OK;
00291 }
00292 
00293 #endif /* defined (USB_OTG_FS) */
00294 #if defined (USB)
00295 /**
00296   * @brief  Configure PMA for EP
00297   * @param  hpcd  Device instance
00298   * @param  ep_addr endpoint address
00299   * @param  ep_kind endpoint Kind
00300   *                  USB_SNG_BUF: Single Buffer used
00301   *                  USB_DBL_BUF: Double Buffer used
00302   * @param  pmaadress: EP address in The PMA: In case of single buffer endpoint
00303   *                   this parameter is 16-bit value providing the address
00304   *                   in PMA allocated to endpoint.
00305   *                   In case of double buffer endpoint this parameter
00306   *                   is a 32-bit value providing the endpoint buffer 0 address
00307   *                   in the LSB part of 32-bit value and endpoint buffer 1 address
00308   *                   in the MSB part of 32-bit value.
00309   * @retval HAL status
00310   */
00311 
00312 HAL_StatusTypeDef  HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, uint16_t ep_addr,
00313                                        uint16_t ep_kind, uint32_t pmaadress)
00314 {
00315   PCD_EPTypeDef *ep;
00316 
00317   /* initialize ep structure*/
00318   if ((0x80U & ep_addr) == 0x80U)
00319   {
00320     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
00321   }
00322   else
00323   {
00324     ep = &hpcd->OUT_ep[ep_addr];
00325   }
00326 
00327   /* Here we check if the endpoint is single or double Buffer*/
00328   if (ep_kind == PCD_SNG_BUF)
00329   {
00330     /* Single Buffer */
00331     ep->doublebuffer = 0U;
00332     /* Configure the PMA */
00333     ep->pmaadress = (uint16_t)pmaadress;
00334   }
00335 #if (USE_USB_DOUBLE_BUFFER == 1U)
00336   else /* USB_DBL_BUF */
00337   {
00338     /* Double Buffer Endpoint */
00339     ep->doublebuffer = 1U;
00340     /* Configure the PMA */
00341     ep->pmaaddr0 = (uint16_t)(pmaadress & 0xFFFFU);
00342     ep->pmaaddr1 = (uint16_t)((pmaadress & 0xFFFF0000U) >> 16);
00343   }
00344 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
00345 
00346   return HAL_OK;
00347 }
00348 
00349 /**
00350   * @brief  Activate BatteryCharging feature.
00351   * @param  hpcd PCD handle
00352   * @retval HAL status
00353   */
00354 HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd)
00355 {
00356   USB_TypeDef *USBx = hpcd->Instance;
00357   hpcd->battery_charging_active = 1U;
00358 
00359   /* Enable BCD feature */
00360   USBx->BCDR |= USB_BCDR_BCDEN;
00361 
00362   /* Enable DCD : Data Contact Detect */
00363   USBx->BCDR &= ~(USB_BCDR_PDEN);
00364   USBx->BCDR &= ~(USB_BCDR_SDEN);
00365   USBx->BCDR |= USB_BCDR_DCDEN;
00366 
00367   return HAL_OK;
00368 }
00369 
00370 /**
00371   * @brief  Deactivate BatteryCharging feature.
00372   * @param  hpcd PCD handle
00373   * @retval HAL status
00374   */
00375 HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd)
00376 {
00377   USB_TypeDef *USBx = hpcd->Instance;
00378   hpcd->battery_charging_active = 0U;
00379 
00380   /* Disable BCD feature */
00381   USBx->BCDR &= ~(USB_BCDR_BCDEN);
00382 
00383   return HAL_OK;
00384 }
00385 
00386 /**
00387   * @brief  Handle BatteryCharging Process.
00388   * @param  hpcd PCD handle
00389   * @retval HAL status
00390   */
00391 void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd)
00392 {
00393   USB_TypeDef *USBx = hpcd->Instance;
00394   uint32_t tickstart = HAL_GetTick();
00395 
00396   /* Wait Detect flag or a timeout is happen */
00397   while ((USBx->BCDR & USB_BCDR_DCDET) == 0U)
00398   {
00399     /* Check for the Timeout */
00400     if ((HAL_GetTick() - tickstart) > 1000U)
00401     {
00402 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00403       hpcd->BCDCallback(hpcd, PCD_BCD_ERROR);
00404 #else
00405       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR);
00406 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00407 
00408       return;
00409     }
00410   }
00411 
00412   HAL_Delay(200U);
00413 
00414   /* Data Pin Contact ? Check Detect flag */
00415   if ((USBx->BCDR & USB_BCDR_DCDET) == USB_BCDR_DCDET)
00416   {
00417 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00418     hpcd->BCDCallback(hpcd, PCD_BCD_CONTACT_DETECTION);
00419 #else
00420     HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION);
00421 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00422   }
00423   /* Primary detection: checks if connected to Standard Downstream Port
00424   (without charging capability) */
00425   USBx->BCDR &= ~(USB_BCDR_DCDEN);
00426   HAL_Delay(50U);
00427   USBx->BCDR |= (USB_BCDR_PDEN);
00428   HAL_Delay(50U);
00429 
00430   /* If Charger detect ? */
00431   if ((USBx->BCDR & USB_BCDR_PDET) == USB_BCDR_PDET)
00432   {
00433     /* Start secondary detection to check connection to Charging Downstream
00434     Port or Dedicated Charging Port */
00435     USBx->BCDR &= ~(USB_BCDR_PDEN);
00436     HAL_Delay(50U);
00437     USBx->BCDR |= (USB_BCDR_SDEN);
00438     HAL_Delay(50U);
00439 
00440     /* If CDP ? */
00441     if ((USBx->BCDR & USB_BCDR_SDET) == USB_BCDR_SDET)
00442     {
00443       /* Dedicated Downstream Port DCP */
00444 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00445       hpcd->BCDCallback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
00446 #else
00447       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
00448 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00449     }
00450     else
00451     {
00452       /* Charging Downstream Port CDP */
00453 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00454       hpcd->BCDCallback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
00455 #else
00456       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
00457 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00458     }
00459   }
00460   else /* NO */
00461   {
00462     /* Standard Downstream Port */
00463 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00464     hpcd->BCDCallback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
00465 #else
00466     HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
00467 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00468   }
00469 
00470   /* Battery Charging capability discovery finished Start Enumeration */
00471   (void)HAL_PCDEx_DeActivateBCD(hpcd);
00472 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
00473   hpcd->BCDCallback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
00474 #else
00475   HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
00476 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
00477 }
00478 
00479 
00480 /**
00481   * @brief  Activate LPM feature.
00482   * @param  hpcd PCD handle
00483   * @retval HAL status
00484   */
00485 HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd)
00486 {
00487 
00488   USB_TypeDef *USBx = hpcd->Instance;
00489   hpcd->lpm_active = 1U;
00490   hpcd->LPM_State = LPM_L0;
00491 
00492   USBx->LPMCSR |= USB_LPMCSR_LMPEN;
00493   USBx->LPMCSR |= USB_LPMCSR_LPMACK;
00494 
00495   return HAL_OK;
00496 }
00497 
00498 /**
00499   * @brief  Deactivate LPM feature.
00500   * @param  hpcd PCD handle
00501   * @retval HAL status
00502   */
00503 HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd)
00504 {
00505   USB_TypeDef *USBx = hpcd->Instance;
00506 
00507   hpcd->lpm_active = 0U;
00508 
00509   USBx->LPMCSR &= ~(USB_LPMCSR_LMPEN);
00510   USBx->LPMCSR &= ~(USB_LPMCSR_LPMACK);
00511 
00512   return HAL_OK;
00513 }
00514 
00515 #endif /* defined (USB) */
00516 
00517 /**
00518   * @brief  Send LPM message to user layer callback.
00519   * @param  hpcd PCD handle
00520   * @param  msg LPM message
00521   * @retval HAL status
00522   */
00523 __weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
00524 {
00525   /* Prevent unused argument(s) compilation warning */
00526   UNUSED(hpcd);
00527   UNUSED(msg);
00528 
00529   /* NOTE : This function should not be modified, when the callback is needed,
00530             the HAL_PCDEx_LPM_Callback could be implemented in the user file
00531    */
00532 }
00533 
00534 /**
00535   * @brief  Send BatteryCharging message to user layer callback.
00536   * @param  hpcd PCD handle
00537   * @param  msg LPM message
00538   * @retval HAL status
00539   */
00540 __weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg)
00541 {
00542   /* Prevent unused argument(s) compilation warning */
00543   UNUSED(hpcd);
00544   UNUSED(msg);
00545 
00546   /* NOTE : This function should not be modified, when the callback is needed,
00547             the HAL_PCDEx_BCD_Callback could be implemented in the user file
00548    */
00549 }
00550 
00551 /**
00552   * @}
00553   */
00554 
00555 /**
00556   * @}
00557   */
00558 #endif /* defined (USB) || defined (USB_OTG_FS) */
00559 #endif /* HAL_PCD_MODULE_ENABLED */
00560 
00561 /**
00562   * @}
00563   */
00564 
00565 /**
00566   * @}
00567   */