1 /**
2   ******************************************************************************
3   * @file    stm32g4xx_hal_pcd_ex.c
4   * @author  MCD Application Team
5   * @brief   PCD Extended HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the USB Peripheral Controller:
8   *           + Extended features functions
9   *
10   ******************************************************************************
11   * @attention
12   *
13   * Copyright (c) 2019 STMicroelectronics.
14   * All rights reserved.
15   *
16   * This software is licensed under terms that can be found in the LICENSE file
17   * in the root directory of this software component.
18   * If no LICENSE file comes with this software, it is provided AS-IS.
19   *
20   ******************************************************************************
21   */
22 
23 /* Includes ------------------------------------------------------------------*/
24 #include "stm32g4xx_hal.h"
25 
26 /** @addtogroup STM32G4xx_HAL_Driver
27   * @{
28   */
29 
30 /** @defgroup PCDEx PCDEx
31   * @brief PCD Extended HAL module driver
32   * @{
33   */
34 
35 #ifdef HAL_PCD_MODULE_ENABLED
36 
37 #if defined (USB)
38 /* Private types -------------------------------------------------------------*/
39 /* Private variables ---------------------------------------------------------*/
40 /* Private constants ---------------------------------------------------------*/
41 /* Private macros ------------------------------------------------------------*/
42 /* Private functions ---------------------------------------------------------*/
43 /* Exported functions --------------------------------------------------------*/
44 
45 /** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions
46   * @{
47   */
48 
49 /** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions
50   * @brief    PCDEx control functions
51   *
52 @verbatim
53  ===============================================================================
54                  ##### Extended features functions #####
55  ===============================================================================
56     [..]  This section provides functions allowing to:
57       (+) Update FIFO configuration
58 
59 @endverbatim
60   * @{
61   */
62 
63 /**
64   * @brief  Configure PMA for EP
65   * @param  hpcd  Device instance
66   * @param  ep_addr endpoint address
67   * @param  ep_kind endpoint Kind
68   *                  USB_SNG_BUF: Single Buffer used
69   *                  USB_DBL_BUF: Double Buffer used
70   * @param  pmaadress: EP address in The PMA: In case of single buffer endpoint
71   *                   this parameter is 16-bit value providing the address
72   *                   in PMA allocated to endpoint.
73   *                   In case of double buffer endpoint this parameter
74   *                   is a 32-bit value providing the endpoint buffer 0 address
75   *                   in the LSB part of 32-bit value and endpoint buffer 1 address
76   *                   in the MSB part of 32-bit value.
77   * @retval HAL status
78   */
79 
HAL_PCDEx_PMAConfig(PCD_HandleTypeDef * hpcd,uint16_t ep_addr,uint16_t ep_kind,uint32_t pmaadress)80 HAL_StatusTypeDef  HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, uint16_t ep_addr,
81                                        uint16_t ep_kind, uint32_t pmaadress)
82 {
83   PCD_EPTypeDef *ep;
84 
85   /* initialize ep structure*/
86   if ((0x80U & ep_addr) == 0x80U)
87   {
88     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
89   }
90   else
91   {
92     ep = &hpcd->OUT_ep[ep_addr];
93   }
94 
95   /* Here we check if the endpoint is single or double Buffer*/
96   if (ep_kind == PCD_SNG_BUF)
97   {
98     /* Single Buffer */
99     ep->doublebuffer = 0U;
100     /* Configure the PMA */
101     ep->pmaadress = (uint16_t)pmaadress;
102   }
103 #if (USE_USB_DOUBLE_BUFFER == 1U)
104   else /* USB_DBL_BUF */
105   {
106     /* Double Buffer Endpoint */
107     ep->doublebuffer = 1U;
108     /* Configure the PMA */
109     ep->pmaaddr0 = (uint16_t)(pmaadress & 0xFFFFU);
110     ep->pmaaddr1 = (uint16_t)((pmaadress & 0xFFFF0000U) >> 16);
111   }
112 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
113 
114   return HAL_OK;
115 }
116 
117 /**
118   * @brief  Activate BatteryCharging feature.
119   * @param  hpcd PCD handle
120   * @retval HAL status
121   */
HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef * hpcd)122 HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd)
123 {
124   USB_TypeDef *USBx = hpcd->Instance;
125   hpcd->battery_charging_active = 1U;
126 
127   /* Enable BCD feature */
128   USBx->BCDR |= USB_BCDR_BCDEN;
129 
130   /* Enable DCD : Data Contact Detect */
131   USBx->BCDR &= ~(USB_BCDR_PDEN);
132   USBx->BCDR &= ~(USB_BCDR_SDEN);
133   USBx->BCDR |= USB_BCDR_DCDEN;
134 
135   return HAL_OK;
136 }
137 
138 /**
139   * @brief  Deactivate BatteryCharging feature.
140   * @param  hpcd PCD handle
141   * @retval HAL status
142   */
HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef * hpcd)143 HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd)
144 {
145   USB_TypeDef *USBx = hpcd->Instance;
146   hpcd->battery_charging_active = 0U;
147 
148   /* Disable BCD feature */
149   USBx->BCDR &= ~(USB_BCDR_BCDEN);
150 
151   return HAL_OK;
152 }
153 
154 /**
155   * @brief  Handle BatteryCharging Process.
156   * @param  hpcd PCD handle
157   * @retval HAL status
158   */
HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef * hpcd)159 void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd)
160 {
161   USB_TypeDef *USBx = hpcd->Instance;
162   uint32_t tickstart = HAL_GetTick();
163 
164   /* Wait Detect flag or a timeout is happen */
165   while ((USBx->BCDR & USB_BCDR_DCDET) == 0U)
166   {
167     /* Check for the Timeout */
168     if ((HAL_GetTick() - tickstart) > 1000U)
169     {
170 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
171       hpcd->BCDCallback(hpcd, PCD_BCD_ERROR);
172 #else
173       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR);
174 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
175 
176       return;
177     }
178   }
179 
180   HAL_Delay(200U);
181 
182   /* Data Pin Contact ? Check Detect flag */
183   if ((USBx->BCDR & USB_BCDR_DCDET) == USB_BCDR_DCDET)
184   {
185 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
186     hpcd->BCDCallback(hpcd, PCD_BCD_CONTACT_DETECTION);
187 #else
188     HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION);
189 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
190   }
191   /* Primary detection: checks if connected to Standard Downstream Port
192   (without charging capability) */
193   USBx->BCDR &= ~(USB_BCDR_DCDEN);
194   HAL_Delay(50U);
195   USBx->BCDR |= (USB_BCDR_PDEN);
196   HAL_Delay(50U);
197 
198   /* If Charger detect ? */
199   if ((USBx->BCDR & USB_BCDR_PDET) == USB_BCDR_PDET)
200   {
201     /* Start secondary detection to check connection to Charging Downstream
202     Port or Dedicated Charging Port */
203     USBx->BCDR &= ~(USB_BCDR_PDEN);
204     HAL_Delay(50U);
205     USBx->BCDR |= (USB_BCDR_SDEN);
206     HAL_Delay(50U);
207 
208     /* If CDP ? */
209     if ((USBx->BCDR & USB_BCDR_SDET) == USB_BCDR_SDET)
210     {
211       /* Dedicated Downstream Port DCP */
212 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
213       hpcd->BCDCallback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
214 #else
215       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
216 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
217     }
218     else
219     {
220       /* Charging Downstream Port CDP */
221 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
222       hpcd->BCDCallback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
223 #else
224       HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
225 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
226     }
227   }
228   else /* NO */
229   {
230     /* Standard Downstream Port */
231 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
232     hpcd->BCDCallback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
233 #else
234     HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
235 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
236   }
237 
238   /* Battery Charging capability discovery finished Start Enumeration */
239   (void)HAL_PCDEx_DeActivateBCD(hpcd);
240 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
241   hpcd->BCDCallback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
242 #else
243   HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
244 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
245 }
246 
247 
248 /**
249   * @brief  Activate LPM feature.
250   * @param  hpcd PCD handle
251   * @retval HAL status
252   */
HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef * hpcd)253 HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd)
254 {
255 
256   USB_TypeDef *USBx = hpcd->Instance;
257   hpcd->lpm_active = 1U;
258   hpcd->LPM_State = LPM_L0;
259 
260   USBx->LPMCSR |= USB_LPMCSR_LMPEN;
261   USBx->LPMCSR |= USB_LPMCSR_LPMACK;
262 
263   return HAL_OK;
264 }
265 
266 /**
267   * @brief  Deactivate LPM feature.
268   * @param  hpcd PCD handle
269   * @retval HAL status
270   */
HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef * hpcd)271 HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd)
272 {
273   USB_TypeDef *USBx = hpcd->Instance;
274 
275   hpcd->lpm_active = 0U;
276 
277   USBx->LPMCSR &= ~(USB_LPMCSR_LMPEN);
278   USBx->LPMCSR &= ~(USB_LPMCSR_LPMACK);
279 
280   return HAL_OK;
281 }
282 
283 
284 
285 /**
286   * @brief  Send LPM message to user layer callback.
287   * @param  hpcd PCD handle
288   * @param  msg LPM message
289   * @retval HAL status
290   */
HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef * hpcd,PCD_LPM_MsgTypeDef msg)291 __weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
292 {
293   /* Prevent unused argument(s) compilation warning */
294   UNUSED(hpcd);
295   UNUSED(msg);
296 
297   /* NOTE : This function should not be modified, when the callback is needed,
298             the HAL_PCDEx_LPM_Callback could be implemented in the user file
299    */
300 }
301 
302 /**
303   * @brief  Send BatteryCharging message to user layer callback.
304   * @param  hpcd PCD handle
305   * @param  msg LPM message
306   * @retval HAL status
307   */
HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef * hpcd,PCD_BCD_MsgTypeDef msg)308 __weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg)
309 {
310   /* Prevent unused argument(s) compilation warning */
311   UNUSED(hpcd);
312   UNUSED(msg);
313 
314   /* NOTE : This function should not be modified, when the callback is needed,
315             the HAL_PCDEx_BCD_Callback could be implemented in the user file
316    */
317 }
318 
319 /**
320   * @}
321   */
322 
323 /**
324   * @}
325   */
326 #endif /* defined (USB) */
327 #endif /* HAL_PCD_MODULE_ENABLED */
328 
329 /**
330   * @}
331   */
332 
333 /**
334   * @}
335   */
336