1 /**
2 ******************************************************************************
3 * @file stm32l4xx_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 * <h2><center>© Copyright (c) 2017 STMicroelectronics.
14 * All rights reserved.</center></h2>
15 *
16 * This software component is licensed by ST under BSD 3-Clause license,
17 * the "License"; You may not use this file except in compliance with the
18 * License. You may obtain a copy of the License at:
19 * opensource.org/licenses/BSD-3-Clause
20 *
21 ******************************************************************************
22 */
23
24 /* Includes ------------------------------------------------------------------*/
25 #include "stm32l4xx_hal.h"
26
27 /** @addtogroup STM32L4xx_HAL_Driver
28 * @{
29 */
30
31 /** @defgroup PCDEx PCDEx
32 * @brief PCD Extended HAL module driver
33 * @{
34 */
35
36 #ifdef HAL_PCD_MODULE_ENABLED
37
38 #if defined (USB) || defined (USB_OTG_FS)
39 /* Private types -------------------------------------------------------------*/
40 /* Private variables ---------------------------------------------------------*/
41 /* Private constants ---------------------------------------------------------*/
42 /* Private macros ------------------------------------------------------------*/
43 /* Private functions ---------------------------------------------------------*/
44 /* Exported functions --------------------------------------------------------*/
45
46 /** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions
47 * @{
48 */
49
50 /** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions
51 * @brief PCDEx control functions
52 *
53 @verbatim
54 ===============================================================================
55 ##### Extended features functions #####
56 ===============================================================================
57 [..] This section provides functions allowing to:
58 (+) Update FIFO configuration
59
60 @endverbatim
61 * @{
62 */
63 #if defined (USB_OTG_FS)
64 /**
65 * @brief Set Tx FIFO
66 * @param hpcd PCD handle
67 * @param fifo The number of Tx fifo
68 * @param size Fifo size
69 * @retval HAL status
70 */
HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef * hpcd,uint8_t fifo,uint16_t size)71 HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size)
72 {
73 uint8_t i;
74 uint32_t Tx_Offset;
75
76 /* TXn min size = 16 words. (n : Transmit FIFO index)
77 When a TxFIFO is not used, the Configuration should be as follows:
78 case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes)
79 --> Txm can use the space allocated for Txn.
80 case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes)
81 --> Txn should be configured with the minimum space of 16 words
82 The FIFO is used optimally when used TxFIFOs are allocated in the top
83 of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
84 When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */
85
86 Tx_Offset = hpcd->Instance->GRXFSIZ;
87
88 if (fifo == 0U)
89 {
90 hpcd->Instance->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset;
91 }
92 else
93 {
94 Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16;
95 for (i = 0U; i < (fifo - 1U); i++)
96 {
97 Tx_Offset += (hpcd->Instance->DIEPTXF[i] >> 16);
98 }
99
100 /* Multiply Tx_Size by 2 to get higher performance */
101 hpcd->Instance->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset;
102 }
103
104 return HAL_OK;
105 }
106
107 /**
108 * @brief Set Rx FIFO
109 * @param hpcd PCD handle
110 * @param size Size of Rx fifo
111 * @retval HAL status
112 */
HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef * hpcd,uint16_t size)113 HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size)
114 {
115 hpcd->Instance->GRXFSIZ = size;
116
117 return HAL_OK;
118 }
119
120 /**
121 * @brief Activate LPM feature.
122 * @param hpcd PCD handle
123 * @retval HAL status
124 */
HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef * hpcd)125 HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd)
126 {
127 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
128
129 hpcd->lpm_active = 1U;
130 hpcd->LPM_State = LPM_L0;
131 USBx->GINTMSK |= USB_OTG_GINTMSK_LPMINTM;
132 USBx->GLPMCFG |= (USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
133
134 return HAL_OK;
135 }
136
137 /**
138 * @brief Deactivate LPM feature.
139 * @param hpcd PCD handle
140 * @retval HAL status
141 */
HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef * hpcd)142 HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd)
143 {
144 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
145
146 hpcd->lpm_active = 0U;
147 USBx->GINTMSK &= ~USB_OTG_GINTMSK_LPMINTM;
148 USBx->GLPMCFG &= ~(USB_OTG_GLPMCFG_LPMEN | USB_OTG_GLPMCFG_LPMACK | USB_OTG_GLPMCFG_ENBESL);
149
150 return HAL_OK;
151 }
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_OTG_GlobalTypeDef *USBx = hpcd->Instance;
162 uint32_t tickstart = HAL_GetTick();
163
164 /* Enable DCD : Data Contact Detect */
165 USBx->GCCFG |= USB_OTG_GCCFG_DCDEN;
166
167 /* Wait Detect flag or a timeout is happen*/
168 while ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == 0U)
169 {
170 /* Check for the Timeout */
171 if ((HAL_GetTick() - tickstart) > 1000U)
172 {
173 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
174 hpcd->BCDCallback(hpcd, PCD_BCD_ERROR);
175 #else
176 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR);
177 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
178
179 return;
180 }
181 }
182
183 /* Right response got */
184 HAL_Delay(200U);
185
186 /* Check Detect flag*/
187 if ((USBx->GCCFG & USB_OTG_GCCFG_DCDET) == USB_OTG_GCCFG_DCDET)
188 {
189 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
190 hpcd->BCDCallback(hpcd, PCD_BCD_CONTACT_DETECTION);
191 #else
192 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION);
193 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
194 }
195
196 /*Primary detection: checks if connected to Standard Downstream Port
197 (without charging capability) */
198 USBx->GCCFG &= ~ USB_OTG_GCCFG_DCDEN;
199 HAL_Delay(50U);
200 USBx->GCCFG |= USB_OTG_GCCFG_PDEN;
201 HAL_Delay(50U);
202
203 if ((USBx->GCCFG & USB_OTG_GCCFG_PDET) == 0U)
204 {
205 /* Case of Standard Downstream Port */
206 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
207 hpcd->BCDCallback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
208 #else
209 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
210 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
211 }
212 else
213 {
214 /* start secondary detection to check connection to Charging Downstream
215 Port or Dedicated Charging Port */
216 USBx->GCCFG &= ~ USB_OTG_GCCFG_PDEN;
217 HAL_Delay(50U);
218 USBx->GCCFG |= USB_OTG_GCCFG_SDEN;
219 HAL_Delay(50U);
220
221 if ((USBx->GCCFG & USB_OTG_GCCFG_SDET) == USB_OTG_GCCFG_SDET)
222 {
223 /* case Dedicated Charging Port */
224 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
225 hpcd->BCDCallback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
226 #else
227 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
228 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
229 }
230 else
231 {
232 /* case Charging Downstream Port */
233 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
234 hpcd->BCDCallback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
235 #else
236 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
237 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
238 }
239 }
240
241 /* Battery Charging capability discovery finished */
242 (void)HAL_PCDEx_DeActivateBCD(hpcd);
243
244 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
245 hpcd->BCDCallback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
246 #else
247 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
248 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
249 }
250
251 /**
252 * @brief Activate BatteryCharging feature.
253 * @param hpcd PCD handle
254 * @retval HAL status
255 */
HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef * hpcd)256 HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd)
257 {
258 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
259
260 USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
261 USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
262
263 /* Power Down USB tranceiver */
264 USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
265
266 /* Enable Battery charging */
267 USBx->GCCFG |= USB_OTG_GCCFG_BCDEN;
268
269 hpcd->battery_charging_active = 1U;
270
271 return HAL_OK;
272 }
273
274 /**
275 * @brief Deactivate BatteryCharging feature.
276 * @param hpcd PCD handle
277 * @retval HAL status
278 */
HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef * hpcd)279 HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd)
280 {
281 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
282
283 USBx->GCCFG &= ~(USB_OTG_GCCFG_SDEN);
284 USBx->GCCFG &= ~(USB_OTG_GCCFG_PDEN);
285
286 /* Disable Battery charging */
287 USBx->GCCFG &= ~(USB_OTG_GCCFG_BCDEN);
288
289 hpcd->battery_charging_active = 0U;
290
291 return HAL_OK;
292 }
293
294 #endif /* defined (USB_OTG_FS) */
295 #if defined (USB)
296 /**
297 * @brief Configure PMA for EP
298 * @param hpcd Device instance
299 * @param ep_addr endpoint address
300 * @param ep_kind endpoint Kind
301 * USB_SNG_BUF: Single Buffer used
302 * USB_DBL_BUF: Double Buffer used
303 * @param pmaadress: EP address in The PMA: In case of single buffer endpoint
304 * this parameter is 16-bit value providing the address
305 * in PMA allocated to endpoint.
306 * In case of double buffer endpoint this parameter
307 * is a 32-bit value providing the endpoint buffer 0 address
308 * in the LSB part of 32-bit value and endpoint buffer 1 address
309 * in the MSB part of 32-bit value.
310 * @retval HAL status
311 */
312
HAL_PCDEx_PMAConfig(PCD_HandleTypeDef * hpcd,uint16_t ep_addr,uint16_t ep_kind,uint32_t pmaadress)313 HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd,
314 uint16_t ep_addr,
315 uint16_t ep_kind,
316 uint32_t pmaadress)
317 {
318 PCD_EPTypeDef *ep;
319
320 /* initialize ep structure*/
321 if ((0x80U & ep_addr) == 0x80U)
322 {
323 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
324 }
325 else
326 {
327 ep = &hpcd->OUT_ep[ep_addr];
328 }
329
330 /* Here we check if the endpoint is single or double Buffer*/
331 if (ep_kind == PCD_SNG_BUF)
332 {
333 /* Single Buffer */
334 ep->doublebuffer = 0U;
335 /* Configure the PMA */
336 ep->pmaadress = (uint16_t)pmaadress;
337 }
338 else /* USB_DBL_BUF */
339 {
340 /* Double Buffer Endpoint */
341 ep->doublebuffer = 1U;
342 /* Configure the PMA */
343 ep->pmaaddr0 = (uint16_t)(pmaadress & 0xFFFFU);
344 ep->pmaaddr1 = (uint16_t)((pmaadress & 0xFFFF0000U) >> 16);
345 }
346
347 return HAL_OK;
348 }
349
350 /**
351 * @brief Activate BatteryCharging feature.
352 * @param hpcd PCD handle
353 * @retval HAL status
354 */
HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef * hpcd)355 HAL_StatusTypeDef HAL_PCDEx_ActivateBCD(PCD_HandleTypeDef *hpcd)
356 {
357 USB_TypeDef *USBx = hpcd->Instance;
358 hpcd->battery_charging_active = 1U;
359
360 /* Enable BCD feature */
361 USBx->BCDR |= USB_BCDR_BCDEN;
362
363 /* Enable DCD : Data Contact Detect */
364 USBx->BCDR &= ~(USB_BCDR_PDEN);
365 USBx->BCDR &= ~(USB_BCDR_SDEN);
366 USBx->BCDR |= USB_BCDR_DCDEN;
367
368 return HAL_OK;
369 }
370
371 /**
372 * @brief Deactivate BatteryCharging feature.
373 * @param hpcd PCD handle
374 * @retval HAL status
375 */
HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef * hpcd)376 HAL_StatusTypeDef HAL_PCDEx_DeActivateBCD(PCD_HandleTypeDef *hpcd)
377 {
378 USB_TypeDef *USBx = hpcd->Instance;
379 hpcd->battery_charging_active = 0U;
380
381 /* Disable BCD feature */
382 USBx->BCDR &= ~(USB_BCDR_BCDEN);
383
384 return HAL_OK;
385 }
386
387 /**
388 * @brief Handle BatteryCharging Process.
389 * @param hpcd PCD handle
390 * @retval HAL status
391 */
HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef * hpcd)392 void HAL_PCDEx_BCD_VBUSDetect(PCD_HandleTypeDef *hpcd)
393 {
394 USB_TypeDef *USBx = hpcd->Instance;
395 uint32_t tickstart = HAL_GetTick();
396
397 /* Wait Detect flag or a timeout is happen*/
398 while ((USBx->BCDR & USB_BCDR_DCDET) == 0U)
399 {
400 /* Check for the Timeout */
401 if ((HAL_GetTick() - tickstart) > 1000U)
402 {
403 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
404 hpcd->BCDCallback(hpcd, PCD_BCD_ERROR);
405 #else
406 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_ERROR);
407 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
408
409 return;
410 }
411 }
412
413 HAL_Delay(200U);
414
415 /* Data Pin Contact ? Check Detect flag */
416 if ((USBx->BCDR & USB_BCDR_DCDET) == USB_BCDR_DCDET)
417 {
418 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
419 hpcd->BCDCallback(hpcd, PCD_BCD_CONTACT_DETECTION);
420 #else
421 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CONTACT_DETECTION);
422 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
423 }
424 /* Primary detection: checks if connected to Standard Downstream Port
425 (without charging capability) */
426 USBx->BCDR &= ~(USB_BCDR_DCDEN);
427 HAL_Delay(50U);
428 USBx->BCDR |= (USB_BCDR_PDEN);
429 HAL_Delay(50U);
430
431 /* If Charger detect ? */
432 if ((USBx->BCDR & USB_BCDR_PDET) == USB_BCDR_PDET)
433 {
434 /* Start secondary detection to check connection to Charging Downstream
435 Port or Dedicated Charging Port */
436 USBx->BCDR &= ~(USB_BCDR_PDEN);
437 HAL_Delay(50U);
438 USBx->BCDR |= (USB_BCDR_SDEN);
439 HAL_Delay(50U);
440
441 /* If CDP ? */
442 if ((USBx->BCDR & USB_BCDR_SDET) == USB_BCDR_SDET)
443 {
444 /* Dedicated Downstream Port DCP */
445 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
446 hpcd->BCDCallback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
447 #else
448 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DEDICATED_CHARGING_PORT);
449 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
450 }
451 else
452 {
453 /* Charging Downstream Port CDP */
454 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
455 hpcd->BCDCallback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
456 #else
457 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_CHARGING_DOWNSTREAM_PORT);
458 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
459 }
460 }
461 else /* NO */
462 {
463 /* Standard Downstream Port */
464 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
465 hpcd->BCDCallback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
466 #else
467 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_STD_DOWNSTREAM_PORT);
468 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
469 }
470
471 /* Battery Charging capability discovery finished Start Enumeration */
472 (void)HAL_PCDEx_DeActivateBCD(hpcd);
473 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
474 hpcd->BCDCallback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
475 #else
476 HAL_PCDEx_BCD_Callback(hpcd, PCD_BCD_DISCOVERY_COMPLETED);
477 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
478 }
479
480
481 /**
482 * @brief Activate LPM feature.
483 * @param hpcd PCD handle
484 * @retval HAL status
485 */
HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef * hpcd)486 HAL_StatusTypeDef HAL_PCDEx_ActivateLPM(PCD_HandleTypeDef *hpcd)
487 {
488
489 USB_TypeDef *USBx = hpcd->Instance;
490 hpcd->lpm_active = 1U;
491 hpcd->LPM_State = LPM_L0;
492
493 USBx->LPMCSR |= USB_LPMCSR_LMPEN;
494 USBx->LPMCSR |= USB_LPMCSR_LPMACK;
495
496 return HAL_OK;
497 }
498
499 /**
500 * @brief Deactivate LPM feature.
501 * @param hpcd PCD handle
502 * @retval HAL status
503 */
HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef * hpcd)504 HAL_StatusTypeDef HAL_PCDEx_DeActivateLPM(PCD_HandleTypeDef *hpcd)
505 {
506 USB_TypeDef *USBx = hpcd->Instance;
507
508 hpcd->lpm_active = 0U;
509
510 USBx->LPMCSR &= ~(USB_LPMCSR_LMPEN);
511 USBx->LPMCSR &= ~(USB_LPMCSR_LPMACK);
512
513 return HAL_OK;
514 }
515
516 #endif /* defined (USB) */
517
518 /**
519 * @brief Send LPM message to user layer callback.
520 * @param hpcd PCD handle
521 * @param msg LPM message
522 * @retval HAL status
523 */
HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef * hpcd,PCD_LPM_MsgTypeDef msg)524 __weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
525 {
526 /* Prevent unused argument(s) compilation warning */
527 UNUSED(hpcd);
528 UNUSED(msg);
529
530 /* NOTE : This function should not be modified, when the callback is needed,
531 the HAL_PCDEx_LPM_Callback could be implemented in the user file
532 */
533 }
534
535 /**
536 * @brief Send BatteryCharging message to user layer callback.
537 * @param hpcd PCD handle
538 * @param msg LPM message
539 * @retval HAL status
540 */
HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef * hpcd,PCD_BCD_MsgTypeDef msg)541 __weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg)
542 {
543 /* Prevent unused argument(s) compilation warning */
544 UNUSED(hpcd);
545 UNUSED(msg);
546
547 /* NOTE : This function should not be modified, when the callback is needed,
548 the HAL_PCDEx_BCD_Callback could be implemented in the user file
549 */
550 }
551
552 /**
553 * @}
554 */
555
556 /**
557 * @}
558 */
559 #endif /* defined (USB) || defined (USB_OTG_FS) */
560 #endif /* HAL_PCD_MODULE_ENABLED */
561
562 /**
563 * @}
564 */
565
566 /**
567 * @}
568 */
569
570 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
571