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