1 /**
2 ******************************************************************************
3 * @file stm32f4xx_hal_pcd.c
4 * @author MCD Application Team
5 * @brief PCD HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the USB Peripheral Controller:
8 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
12 *
13 @verbatim
14 ==============================================================================
15 ##### How to use this driver #####
16 ==============================================================================
17 [..]
18 The PCD HAL driver can be used as follows:
19
20 (#) Declare a PCD_HandleTypeDef handle structure, for example:
21 PCD_HandleTypeDef hpcd;
22
23 (#) Fill parameters of Init structure in HCD handle
24
25 (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
26
27 (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
28 (##) Enable the PCD/USB Low Level interface clock using
29 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
30 (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
31
32 (##) Initialize the related GPIO clocks
33 (##) Configure PCD pin-out
34 (##) Configure PCD NVIC interrupt
35
36 (#)Associate the Upper USB device stack to the HAL PCD Driver:
37 (##) hpcd.pData = pdev;
38
39 (#)Enable PCD transmission and reception:
40 (##) HAL_PCD_Start();
41
42 @endverbatim
43 ******************************************************************************
44 * @attention
45 *
46 * <h2><center>© Copyright (c) 2016 STMicroelectronics.
47 * All rights reserved.</center></h2>
48 *
49 * This software component is licensed by ST under BSD 3-Clause license,
50 * the "License"; You may not use this file except in compliance with the
51 * License. You may obtain a copy of the License at:
52 * opensource.org/licenses/BSD-3-Clause
53 *
54 ******************************************************************************
55 */
56
57 /* Includes ------------------------------------------------------------------*/
58 #include "stm32f4xx_hal.h"
59
60 /** @addtogroup STM32F4xx_HAL_Driver
61 * @{
62 */
63
64 /** @defgroup PCD PCD
65 * @brief PCD HAL module driver
66 * @{
67 */
68
69 #ifdef HAL_PCD_MODULE_ENABLED
70
71 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
72
73 /* Private types -------------------------------------------------------------*/
74 /* Private variables ---------------------------------------------------------*/
75 /* Private constants ---------------------------------------------------------*/
76 /* Private macros ------------------------------------------------------------*/
77 /** @defgroup PCD_Private_Macros PCD Private Macros
78 * @{
79 */
80 #define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b))
81 #define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b))
82 /**
83 * @}
84 */
85
86 /* Private functions prototypes ----------------------------------------------*/
87 /** @defgroup PCD_Private_Functions PCD Private Functions
88 * @{
89 */
90 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
91 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
92 static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
93 static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
94 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
95 /**
96 * @}
97 */
98
99 /* Exported functions --------------------------------------------------------*/
100 /** @defgroup PCD_Exported_Functions PCD Exported Functions
101 * @{
102 */
103
104 /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
105 * @brief Initialization and Configuration functions
106 *
107 @verbatim
108 ===============================================================================
109 ##### Initialization and de-initialization functions #####
110 ===============================================================================
111 [..] This section provides functions allowing to:
112
113 @endverbatim
114 * @{
115 */
116
117 /**
118 * @brief Initializes the PCD according to the specified
119 * parameters in the PCD_InitTypeDef and initialize the associated handle.
120 * @param hpcd PCD handle
121 * @retval HAL status
122 */
HAL_PCD_Init(PCD_HandleTypeDef * hpcd)123 HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
124 {
125 USB_OTG_GlobalTypeDef *USBx;
126 uint8_t i;
127
128 /* Check the PCD handle allocation */
129 if (hpcd == NULL)
130 {
131 return HAL_ERROR;
132 }
133
134 /* Check the parameters */
135 assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
136
137 USBx = hpcd->Instance;
138
139 if (hpcd->State == HAL_PCD_STATE_RESET)
140 {
141 /* Allocate lock resource and initialize it */
142 hpcd->Lock = HAL_UNLOCKED;
143
144 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
145 hpcd->SOFCallback = HAL_PCD_SOFCallback;
146 hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
147 hpcd->ResetCallback = HAL_PCD_ResetCallback;
148 hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
149 hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
150 hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
151 hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
152 hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
153 hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
154 hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
155 hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
156 hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;
157 hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;
158
159 if (hpcd->MspInitCallback == NULL)
160 {
161 hpcd->MspInitCallback = HAL_PCD_MspInit;
162 }
163
164 /* Init the low level hardware */
165 hpcd->MspInitCallback(hpcd);
166 #else
167 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
168 HAL_PCD_MspInit(hpcd);
169 #endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
170 }
171
172 hpcd->State = HAL_PCD_STATE_BUSY;
173
174 /* Disable DMA mode for FS instance */
175 if ((USBx->CID & (0x1U << 8)) == 0U)
176 {
177 hpcd->Init.dma_enable = 0U;
178 }
179
180 /* Disable the Interrupts */
181 __HAL_PCD_DISABLE(hpcd);
182
183 /*Init the Core (common init.) */
184 if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
185 {
186 hpcd->State = HAL_PCD_STATE_ERROR;
187 return HAL_ERROR;
188 }
189
190 /* Force Device Mode*/
191 (void)USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE);
192
193 /* Init endpoints structures */
194 for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
195 {
196 /* Init ep structure */
197 hpcd->IN_ep[i].is_in = 1U;
198 hpcd->IN_ep[i].num = i;
199 hpcd->IN_ep[i].tx_fifo_num = i;
200 /* Control until ep is activated */
201 hpcd->IN_ep[i].type = EP_TYPE_CTRL;
202 hpcd->IN_ep[i].maxpacket = 0U;
203 hpcd->IN_ep[i].xfer_buff = 0U;
204 hpcd->IN_ep[i].xfer_len = 0U;
205 }
206
207 for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
208 {
209 hpcd->OUT_ep[i].is_in = 0U;
210 hpcd->OUT_ep[i].num = i;
211 /* Control until ep is activated */
212 hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
213 hpcd->OUT_ep[i].maxpacket = 0U;
214 hpcd->OUT_ep[i].xfer_buff = 0U;
215 hpcd->OUT_ep[i].xfer_len = 0U;
216 }
217
218 /* Init Device */
219 if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
220 {
221 hpcd->State = HAL_PCD_STATE_ERROR;
222 return HAL_ERROR;
223 }
224
225 hpcd->USB_Address = 0U;
226 hpcd->State = HAL_PCD_STATE_READY;
227 #if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
228 /* Activate LPM */
229 if (hpcd->Init.lpm_enable == 1U)
230 {
231 (void)HAL_PCDEx_ActivateLPM(hpcd);
232 }
233 #endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
234 (void)USB_DevDisconnect(hpcd->Instance);
235
236 return HAL_OK;
237 }
238
239 /**
240 * @brief DeInitializes the PCD peripheral.
241 * @param hpcd PCD handle
242 * @retval HAL status
243 */
HAL_PCD_DeInit(PCD_HandleTypeDef * hpcd)244 HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
245 {
246 /* Check the PCD handle allocation */
247 if (hpcd == NULL)
248 {
249 return HAL_ERROR;
250 }
251
252 hpcd->State = HAL_PCD_STATE_BUSY;
253
254 /* Stop Device */
255 if (USB_StopDevice(hpcd->Instance) != HAL_OK)
256 {
257 return HAL_ERROR;
258 }
259
260 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
261 if (hpcd->MspDeInitCallback == NULL)
262 {
263 hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit */
264 }
265
266 /* DeInit the low level hardware */
267 hpcd->MspDeInitCallback(hpcd);
268 #else
269 /* DeInit the low level hardware: CLOCK, NVIC.*/
270 HAL_PCD_MspDeInit(hpcd);
271 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
272
273 hpcd->State = HAL_PCD_STATE_RESET;
274
275 return HAL_OK;
276 }
277
278 /**
279 * @brief Initializes the PCD MSP.
280 * @param hpcd PCD handle
281 * @retval None
282 */
HAL_PCD_MspInit(PCD_HandleTypeDef * hpcd)283 __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
284 {
285 /* Prevent unused argument(s) compilation warning */
286 UNUSED(hpcd);
287
288 /* NOTE : This function should not be modified, when the callback is needed,
289 the HAL_PCD_MspInit could be implemented in the user file
290 */
291 }
292
293 /**
294 * @brief DeInitializes PCD MSP.
295 * @param hpcd PCD handle
296 * @retval None
297 */
HAL_PCD_MspDeInit(PCD_HandleTypeDef * hpcd)298 __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
299 {
300 /* Prevent unused argument(s) compilation warning */
301 UNUSED(hpcd);
302
303 /* NOTE : This function should not be modified, when the callback is needed,
304 the HAL_PCD_MspDeInit could be implemented in the user file
305 */
306 }
307
308 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
309 /**
310 * @brief Register a User USB PCD Callback
311 * To be used instead of the weak predefined callback
312 * @param hpcd USB PCD handle
313 * @param CallbackID ID of the callback to be registered
314 * This parameter can be one of the following values:
315 * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
316 * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
317 * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
318 * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
319 * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
320 * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
321 * @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
322 * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
323 * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
324 * @param pCallback pointer to the Callback function
325 * @retval HAL status
326 */
HAL_PCD_RegisterCallback(PCD_HandleTypeDef * hpcd,HAL_PCD_CallbackIDTypeDef CallbackID,pPCD_CallbackTypeDef pCallback)327 HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
328 HAL_PCD_CallbackIDTypeDef CallbackID,
329 pPCD_CallbackTypeDef pCallback)
330 {
331 HAL_StatusTypeDef status = HAL_OK;
332
333 if (pCallback == NULL)
334 {
335 /* Update the error code */
336 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
337 return HAL_ERROR;
338 }
339 /* Process locked */
340 __HAL_LOCK(hpcd);
341
342 if (hpcd->State == HAL_PCD_STATE_READY)
343 {
344 switch (CallbackID)
345 {
346 case HAL_PCD_SOF_CB_ID :
347 hpcd->SOFCallback = pCallback;
348 break;
349
350 case HAL_PCD_SETUPSTAGE_CB_ID :
351 hpcd->SetupStageCallback = pCallback;
352 break;
353
354 case HAL_PCD_RESET_CB_ID :
355 hpcd->ResetCallback = pCallback;
356 break;
357
358 case HAL_PCD_SUSPEND_CB_ID :
359 hpcd->SuspendCallback = pCallback;
360 break;
361
362 case HAL_PCD_RESUME_CB_ID :
363 hpcd->ResumeCallback = pCallback;
364 break;
365
366 case HAL_PCD_CONNECT_CB_ID :
367 hpcd->ConnectCallback = pCallback;
368 break;
369
370 case HAL_PCD_DISCONNECT_CB_ID :
371 hpcd->DisconnectCallback = pCallback;
372 break;
373
374 case HAL_PCD_MSPINIT_CB_ID :
375 hpcd->MspInitCallback = pCallback;
376 break;
377
378 case HAL_PCD_MSPDEINIT_CB_ID :
379 hpcd->MspDeInitCallback = pCallback;
380 break;
381
382 default :
383 /* Update the error code */
384 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
385 /* Return error status */
386 status = HAL_ERROR;
387 break;
388 }
389 }
390 else if (hpcd->State == HAL_PCD_STATE_RESET)
391 {
392 switch (CallbackID)
393 {
394 case HAL_PCD_MSPINIT_CB_ID :
395 hpcd->MspInitCallback = pCallback;
396 break;
397
398 case HAL_PCD_MSPDEINIT_CB_ID :
399 hpcd->MspDeInitCallback = pCallback;
400 break;
401
402 default :
403 /* Update the error code */
404 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
405 /* Return error status */
406 status = HAL_ERROR;
407 break;
408 }
409 }
410 else
411 {
412 /* Update the error code */
413 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
414 /* Return error status */
415 status = HAL_ERROR;
416 }
417
418 /* Release Lock */
419 __HAL_UNLOCK(hpcd);
420 return status;
421 }
422
423 /**
424 * @brief Unregister an USB PCD Callback
425 * USB PCD callabck is redirected to the weak predefined callback
426 * @param hpcd USB PCD handle
427 * @param CallbackID ID of the callback to be unregistered
428 * This parameter can be one of the following values:
429 * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
430 * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
431 * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
432 * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
433 * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
434 * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
435 * @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
436 * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
437 * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
438 * @retval HAL status
439 */
HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef * hpcd,HAL_PCD_CallbackIDTypeDef CallbackID)440 HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
441 {
442 HAL_StatusTypeDef status = HAL_OK;
443
444 /* Process locked */
445 __HAL_LOCK(hpcd);
446
447 /* Setup Legacy weak Callbacks */
448 if (hpcd->State == HAL_PCD_STATE_READY)
449 {
450 switch (CallbackID)
451 {
452 case HAL_PCD_SOF_CB_ID :
453 hpcd->SOFCallback = HAL_PCD_SOFCallback;
454 break;
455
456 case HAL_PCD_SETUPSTAGE_CB_ID :
457 hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
458 break;
459
460 case HAL_PCD_RESET_CB_ID :
461 hpcd->ResetCallback = HAL_PCD_ResetCallback;
462 break;
463
464 case HAL_PCD_SUSPEND_CB_ID :
465 hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
466 break;
467
468 case HAL_PCD_RESUME_CB_ID :
469 hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
470 break;
471
472 case HAL_PCD_CONNECT_CB_ID :
473 hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
474 break;
475
476 case HAL_PCD_DISCONNECT_CB_ID :
477 hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
478 break;
479
480 case HAL_PCD_MSPINIT_CB_ID :
481 hpcd->MspInitCallback = HAL_PCD_MspInit;
482 break;
483
484 case HAL_PCD_MSPDEINIT_CB_ID :
485 hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
486 break;
487
488 default :
489 /* Update the error code */
490 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
491
492 /* Return error status */
493 status = HAL_ERROR;
494 break;
495 }
496 }
497 else if (hpcd->State == HAL_PCD_STATE_RESET)
498 {
499 switch (CallbackID)
500 {
501 case HAL_PCD_MSPINIT_CB_ID :
502 hpcd->MspInitCallback = HAL_PCD_MspInit;
503 break;
504
505 case HAL_PCD_MSPDEINIT_CB_ID :
506 hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
507 break;
508
509 default :
510 /* Update the error code */
511 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
512
513 /* Return error status */
514 status = HAL_ERROR;
515 break;
516 }
517 }
518 else
519 {
520 /* Update the error code */
521 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
522
523 /* Return error status */
524 status = HAL_ERROR;
525 }
526
527 /* Release Lock */
528 __HAL_UNLOCK(hpcd);
529 return status;
530 }
531
532 /**
533 * @brief Register USB PCD Data OUT Stage Callback
534 * To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
535 * @param hpcd PCD handle
536 * @param pCallback pointer to the USB PCD Data OUT Stage Callback function
537 * @retval HAL status
538 */
HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef * hpcd,pPCD_DataOutStageCallbackTypeDef pCallback)539 HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
540 pPCD_DataOutStageCallbackTypeDef pCallback)
541 {
542 HAL_StatusTypeDef status = HAL_OK;
543
544 if (pCallback == NULL)
545 {
546 /* Update the error code */
547 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
548
549 return HAL_ERROR;
550 }
551
552 /* Process locked */
553 __HAL_LOCK(hpcd);
554
555 if (hpcd->State == HAL_PCD_STATE_READY)
556 {
557 hpcd->DataOutStageCallback = pCallback;
558 }
559 else
560 {
561 /* Update the error code */
562 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
563
564 /* Return error status */
565 status = HAL_ERROR;
566 }
567
568 /* Release Lock */
569 __HAL_UNLOCK(hpcd);
570
571 return status;
572 }
573
574 /**
575 * @brief Unregister the USB PCD Data OUT Stage Callback
576 * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
577 * @param hpcd PCD handle
578 * @retval HAL status
579 */
HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef * hpcd)580 HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
581 {
582 HAL_StatusTypeDef status = HAL_OK;
583
584 /* Process locked */
585 __HAL_LOCK(hpcd);
586
587 if (hpcd->State == HAL_PCD_STATE_READY)
588 {
589 hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback */
590 }
591 else
592 {
593 /* Update the error code */
594 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
595
596 /* Return error status */
597 status = HAL_ERROR;
598 }
599
600 /* Release Lock */
601 __HAL_UNLOCK(hpcd);
602
603 return status;
604 }
605
606 /**
607 * @brief Register USB PCD Data IN Stage Callback
608 * To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
609 * @param hpcd PCD handle
610 * @param pCallback pointer to the USB PCD Data IN Stage Callback function
611 * @retval HAL status
612 */
HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef * hpcd,pPCD_DataInStageCallbackTypeDef pCallback)613 HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
614 pPCD_DataInStageCallbackTypeDef pCallback)
615 {
616 HAL_StatusTypeDef status = HAL_OK;
617
618 if (pCallback == NULL)
619 {
620 /* Update the error code */
621 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
622
623 return HAL_ERROR;
624 }
625
626 /* Process locked */
627 __HAL_LOCK(hpcd);
628
629 if (hpcd->State == HAL_PCD_STATE_READY)
630 {
631 hpcd->DataInStageCallback = pCallback;
632 }
633 else
634 {
635 /* Update the error code */
636 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
637
638 /* Return error status */
639 status = HAL_ERROR;
640 }
641
642 /* Release Lock */
643 __HAL_UNLOCK(hpcd);
644
645 return status;
646 }
647
648 /**
649 * @brief Unregister the USB PCD Data IN Stage Callback
650 * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
651 * @param hpcd PCD handle
652 * @retval HAL status
653 */
HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef * hpcd)654 HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
655 {
656 HAL_StatusTypeDef status = HAL_OK;
657
658 /* Process locked */
659 __HAL_LOCK(hpcd);
660
661 if (hpcd->State == HAL_PCD_STATE_READY)
662 {
663 hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback */
664 }
665 else
666 {
667 /* Update the error code */
668 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
669
670 /* Return error status */
671 status = HAL_ERROR;
672 }
673
674 /* Release Lock */
675 __HAL_UNLOCK(hpcd);
676
677 return status;
678 }
679
680 /**
681 * @brief Register USB PCD Iso OUT incomplete Callback
682 * To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
683 * @param hpcd PCD handle
684 * @param pCallback pointer to the USB PCD Iso OUT incomplete Callback function
685 * @retval HAL status
686 */
HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef * hpcd,pPCD_IsoOutIncpltCallbackTypeDef pCallback)687 HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
688 pPCD_IsoOutIncpltCallbackTypeDef pCallback)
689 {
690 HAL_StatusTypeDef status = HAL_OK;
691
692 if (pCallback == NULL)
693 {
694 /* Update the error code */
695 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
696
697 return HAL_ERROR;
698 }
699
700 /* Process locked */
701 __HAL_LOCK(hpcd);
702
703 if (hpcd->State == HAL_PCD_STATE_READY)
704 {
705 hpcd->ISOOUTIncompleteCallback = pCallback;
706 }
707 else
708 {
709 /* Update the error code */
710 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
711
712 /* Return error status */
713 status = HAL_ERROR;
714 }
715
716 /* Release Lock */
717 __HAL_UNLOCK(hpcd);
718
719 return status;
720 }
721
722 /**
723 * @brief Unregister the USB PCD Iso OUT incomplete Callback
724 * USB PCD Iso OUT incomplete Callback is redirected
725 * to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
726 * @param hpcd PCD handle
727 * @retval HAL status
728 */
HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef * hpcd)729 HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
730 {
731 HAL_StatusTypeDef status = HAL_OK;
732
733 /* Process locked */
734 __HAL_LOCK(hpcd);
735
736 if (hpcd->State == HAL_PCD_STATE_READY)
737 {
738 hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback */
739 }
740 else
741 {
742 /* Update the error code */
743 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
744
745 /* Return error status */
746 status = HAL_ERROR;
747 }
748
749 /* Release Lock */
750 __HAL_UNLOCK(hpcd);
751
752 return status;
753 }
754
755 /**
756 * @brief Register USB PCD Iso IN incomplete Callback
757 * To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
758 * @param hpcd PCD handle
759 * @param pCallback pointer to the USB PCD Iso IN incomplete Callback function
760 * @retval HAL status
761 */
HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef * hpcd,pPCD_IsoInIncpltCallbackTypeDef pCallback)762 HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
763 pPCD_IsoInIncpltCallbackTypeDef pCallback)
764 {
765 HAL_StatusTypeDef status = HAL_OK;
766
767 if (pCallback == NULL)
768 {
769 /* Update the error code */
770 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
771
772 return HAL_ERROR;
773 }
774
775 /* Process locked */
776 __HAL_LOCK(hpcd);
777
778 if (hpcd->State == HAL_PCD_STATE_READY)
779 {
780 hpcd->ISOINIncompleteCallback = pCallback;
781 }
782 else
783 {
784 /* Update the error code */
785 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
786
787 /* Return error status */
788 status = HAL_ERROR;
789 }
790
791 /* Release Lock */
792 __HAL_UNLOCK(hpcd);
793
794 return status;
795 }
796
797 /**
798 * @brief Unregister the USB PCD Iso IN incomplete Callback
799 * USB PCD Iso IN incomplete Callback is redirected
800 * to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
801 * @param hpcd PCD handle
802 * @retval HAL status
803 */
HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef * hpcd)804 HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
805 {
806 HAL_StatusTypeDef status = HAL_OK;
807
808 /* Process locked */
809 __HAL_LOCK(hpcd);
810
811 if (hpcd->State == HAL_PCD_STATE_READY)
812 {
813 hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback */
814 }
815 else
816 {
817 /* Update the error code */
818 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
819
820 /* Return error status */
821 status = HAL_ERROR;
822 }
823
824 /* Release Lock */
825 __HAL_UNLOCK(hpcd);
826
827 return status;
828 }
829
830 /**
831 * @brief Register USB PCD BCD Callback
832 * To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
833 * @param hpcd PCD handle
834 * @param pCallback pointer to the USB PCD BCD Callback function
835 * @retval HAL status
836 */
HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef * hpcd,pPCD_BcdCallbackTypeDef pCallback)837 HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
838 {
839 HAL_StatusTypeDef status = HAL_OK;
840
841 if (pCallback == NULL)
842 {
843 /* Update the error code */
844 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
845
846 return HAL_ERROR;
847 }
848
849 /* Process locked */
850 __HAL_LOCK(hpcd);
851
852 if (hpcd->State == HAL_PCD_STATE_READY)
853 {
854 hpcd->BCDCallback = pCallback;
855 }
856 else
857 {
858 /* Update the error code */
859 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
860
861 /* Return error status */
862 status = HAL_ERROR;
863 }
864
865 /* Release Lock */
866 __HAL_UNLOCK(hpcd);
867
868 return status;
869 }
870
871 /**
872 * @brief Unregister the USB PCD BCD Callback
873 * USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
874 * @param hpcd PCD handle
875 * @retval HAL status
876 */
HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef * hpcd)877 HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
878 {
879 HAL_StatusTypeDef status = HAL_OK;
880
881 /* Process locked */
882 __HAL_LOCK(hpcd);
883
884 if (hpcd->State == HAL_PCD_STATE_READY)
885 {
886 hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback */
887 }
888 else
889 {
890 /* Update the error code */
891 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
892
893 /* Return error status */
894 status = HAL_ERROR;
895 }
896
897 /* Release Lock */
898 __HAL_UNLOCK(hpcd);
899
900 return status;
901 }
902
903 /**
904 * @brief Register USB PCD LPM Callback
905 * To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
906 * @param hpcd PCD handle
907 * @param pCallback pointer to the USB PCD LPM Callback function
908 * @retval HAL status
909 */
HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef * hpcd,pPCD_LpmCallbackTypeDef pCallback)910 HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
911 {
912 HAL_StatusTypeDef status = HAL_OK;
913
914 if (pCallback == NULL)
915 {
916 /* Update the error code */
917 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
918
919 return HAL_ERROR;
920 }
921
922 /* Process locked */
923 __HAL_LOCK(hpcd);
924
925 if (hpcd->State == HAL_PCD_STATE_READY)
926 {
927 hpcd->LPMCallback = pCallback;
928 }
929 else
930 {
931 /* Update the error code */
932 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
933
934 /* Return error status */
935 status = HAL_ERROR;
936 }
937
938 /* Release Lock */
939 __HAL_UNLOCK(hpcd);
940
941 return status;
942 }
943
944 /**
945 * @brief Unregister the USB PCD LPM Callback
946 * USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
947 * @param hpcd PCD handle
948 * @retval HAL status
949 */
HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef * hpcd)950 HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
951 {
952 HAL_StatusTypeDef status = HAL_OK;
953
954 /* Process locked */
955 __HAL_LOCK(hpcd);
956
957 if (hpcd->State == HAL_PCD_STATE_READY)
958 {
959 hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback */
960 }
961 else
962 {
963 /* Update the error code */
964 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
965
966 /* Return error status */
967 status = HAL_ERROR;
968 }
969
970 /* Release Lock */
971 __HAL_UNLOCK(hpcd);
972
973 return status;
974 }
975 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
976
977 /**
978 * @}
979 */
980
981 /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
982 * @brief Data transfers functions
983 *
984 @verbatim
985 ===============================================================================
986 ##### IO operation functions #####
987 ===============================================================================
988 [..]
989 This subsection provides a set of functions allowing to manage the PCD data
990 transfers.
991
992 @endverbatim
993 * @{
994 */
995
996 /**
997 * @brief Start the USB device
998 * @param hpcd PCD handle
999 * @retval HAL status
1000 */
HAL_PCD_Start(PCD_HandleTypeDef * hpcd)1001 HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
1002 {
1003 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1004
1005 __HAL_LOCK(hpcd);
1006
1007 if ((hpcd->Init.battery_charging_enable == 1U) &&
1008 (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
1009 {
1010 /* Enable USB Transceiver */
1011 USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
1012 }
1013
1014 __HAL_PCD_ENABLE(hpcd);
1015 (void)USB_DevConnect(hpcd->Instance);
1016 __HAL_UNLOCK(hpcd);
1017
1018 return HAL_OK;
1019 }
1020
1021 /**
1022 * @brief Stop the USB device.
1023 * @param hpcd PCD handle
1024 * @retval HAL status
1025 */
HAL_PCD_Stop(PCD_HandleTypeDef * hpcd)1026 HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
1027 {
1028 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1029
1030 __HAL_LOCK(hpcd);
1031 __HAL_PCD_DISABLE(hpcd);
1032 (void)USB_DevDisconnect(hpcd->Instance);
1033
1034 (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
1035
1036 if ((hpcd->Init.battery_charging_enable == 1U) &&
1037 (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
1038 {
1039 /* Disable USB Transceiver */
1040 USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
1041 }
1042
1043 __HAL_UNLOCK(hpcd);
1044
1045 return HAL_OK;
1046 }
1047
1048 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1049 /**
1050 * @brief Handles PCD interrupt request.
1051 * @param hpcd PCD handle
1052 * @retval HAL status
1053 */
HAL_PCD_IRQHandler(PCD_HandleTypeDef * hpcd)1054 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
1055 {
1056 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1057 uint32_t USBx_BASE = (uint32_t)USBx;
1058 USB_OTG_EPTypeDef *ep;
1059 uint32_t i;
1060 uint32_t ep_intr;
1061 uint32_t epint;
1062 uint32_t epnum;
1063 uint32_t fifoemptymsk;
1064 uint32_t temp;
1065
1066 /* ensure that we are in device mode */
1067 if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
1068 {
1069 /* avoid spurious interrupt */
1070 if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
1071 {
1072 return;
1073 }
1074
1075 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
1076 {
1077 /* incorrect mode, acknowledge the interrupt */
1078 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
1079 }
1080
1081 /* Handle RxQLevel Interrupt */
1082 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
1083 {
1084 USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
1085
1086 temp = USBx->GRXSTSP;
1087
1088 ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
1089
1090 if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
1091 {
1092 if ((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
1093 {
1094 (void)USB_ReadPacket(USBx, ep->xfer_buff,
1095 (uint16_t)((temp & USB_OTG_GRXSTSP_BCNT) >> 4));
1096
1097 ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
1098 ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
1099 }
1100 }
1101 else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
1102 {
1103 (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
1104 ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
1105 }
1106 else
1107 {
1108 /* ... */
1109 }
1110 USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
1111 }
1112
1113 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
1114 {
1115 epnum = 0U;
1116
1117 /* Read in the device interrupt bits */
1118 ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
1119
1120 while (ep_intr != 0U)
1121 {
1122 if ((ep_intr & 0x1U) != 0U)
1123 {
1124 epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
1125
1126 if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
1127 {
1128 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
1129 (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
1130 }
1131
1132 if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
1133 {
1134 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
1135 /* Class B setup phase done for previous decoded setup */
1136 (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
1137 }
1138
1139 if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
1140 {
1141 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
1142 }
1143
1144 /* Clear Status Phase Received interrupt */
1145 if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
1146 {
1147 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
1148 }
1149
1150 /* Clear OUT NAK interrupt */
1151 if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
1152 {
1153 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
1154 }
1155 }
1156 epnum++;
1157 ep_intr >>= 1U;
1158 }
1159 }
1160
1161 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
1162 {
1163 /* Read in the device interrupt bits */
1164 ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
1165
1166 epnum = 0U;
1167
1168 while (ep_intr != 0U)
1169 {
1170 if ((ep_intr & 0x1U) != 0U) /* In ITR */
1171 {
1172 epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
1173
1174 if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
1175 {
1176 fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
1177 USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1178
1179 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
1180
1181 if (hpcd->Init.dma_enable == 1U)
1182 {
1183 hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
1184
1185 /* this is ZLP, so prepare EP0 for next setup */
1186 if ((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U))
1187 {
1188 /* prepare to rx more setup packets */
1189 (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
1190 }
1191 }
1192
1193 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1194 hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
1195 #else
1196 HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
1197 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1198 }
1199 if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
1200 {
1201 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
1202 }
1203 if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
1204 {
1205 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
1206 }
1207 if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
1208 {
1209 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
1210 }
1211 if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
1212 {
1213 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
1214 }
1215 if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
1216 {
1217 (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
1218 }
1219 }
1220 epnum++;
1221 ep_intr >>= 1U;
1222 }
1223 }
1224
1225 /* Handle Resume Interrupt */
1226 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
1227 {
1228 /* Clear the Remote Wake-up Signaling */
1229 USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1230
1231 if (hpcd->LPM_State == LPM_L1)
1232 {
1233 hpcd->LPM_State = LPM_L0;
1234
1235 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1236 hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
1237 #else
1238 HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
1239 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1240 }
1241 else
1242 {
1243 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1244 hpcd->ResumeCallback(hpcd);
1245 #else
1246 HAL_PCD_ResumeCallback(hpcd);
1247 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1248 }
1249
1250 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
1251 }
1252
1253 /* Handle Suspend Interrupt */
1254 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
1255 {
1256 if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
1257 {
1258 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1259 hpcd->SuspendCallback(hpcd);
1260 #else
1261 HAL_PCD_SuspendCallback(hpcd);
1262 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1263 }
1264 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
1265 }
1266 #if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
1267 /* Handle LPM Interrupt */
1268 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
1269 {
1270 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);
1271
1272 if (hpcd->LPM_State == LPM_L0)
1273 {
1274 hpcd->LPM_State = LPM_L1;
1275 hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >> 2U;
1276
1277 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1278 hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
1279 #else
1280 HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
1281 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1282 }
1283 else
1284 {
1285 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1286 hpcd->SuspendCallback(hpcd);
1287 #else
1288 HAL_PCD_SuspendCallback(hpcd);
1289 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1290 }
1291 }
1292 #endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
1293 /* Handle Reset Interrupt */
1294 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
1295 {
1296 USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1297 (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
1298
1299 for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
1300 {
1301 USBx_INEP(i)->DIEPINT = 0xFB7FU;
1302 USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
1303 USBx_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
1304 USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
1305 USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
1306 USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
1307 }
1308 USBx_DEVICE->DAINTMSK |= 0x10001U;
1309
1310 if (hpcd->Init.use_dedicated_ep1 != 0U)
1311 {
1312 USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
1313 USB_OTG_DOEPMSK_XFRCM |
1314 USB_OTG_DOEPMSK_EPDM;
1315
1316 USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
1317 USB_OTG_DIEPMSK_XFRCM |
1318 USB_OTG_DIEPMSK_EPDM;
1319 }
1320 else
1321 {
1322 USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
1323 USB_OTG_DOEPMSK_XFRCM |
1324 USB_OTG_DOEPMSK_EPDM |
1325 USB_OTG_DOEPMSK_OTEPSPRM |
1326 USB_OTG_DOEPMSK_NAKM;
1327
1328 USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
1329 USB_OTG_DIEPMSK_XFRCM |
1330 USB_OTG_DIEPMSK_EPDM;
1331 }
1332
1333 /* Set Default Address to 0 */
1334 USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
1335
1336 /* setup EP0 to receive SETUP packets */
1337 (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable,
1338 (uint8_t *)hpcd->Setup);
1339
1340 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
1341 }
1342
1343 /* Handle Enumeration done Interrupt */
1344 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
1345 {
1346 (void)USB_ActivateSetup(hpcd->Instance);
1347 hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
1348
1349 /* Set USB Turnaround time */
1350 (void)USB_SetTurnaroundTime(hpcd->Instance,
1351 HAL_RCC_GetHCLKFreq(),
1352 (uint8_t)hpcd->Init.speed);
1353
1354 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1355 hpcd->ResetCallback(hpcd);
1356 #else
1357 HAL_PCD_ResetCallback(hpcd);
1358 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1359
1360 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
1361 }
1362
1363 /* Handle SOF Interrupt */
1364 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
1365 {
1366 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1367 hpcd->SOFCallback(hpcd);
1368 #else
1369 HAL_PCD_SOFCallback(hpcd);
1370 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1371
1372 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
1373 }
1374
1375 /* Handle Incomplete ISO IN Interrupt */
1376 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
1377 {
1378 /* Keep application checking the corresponding Iso IN endpoint
1379 causing the incomplete Interrupt */
1380 epnum = 0U;
1381
1382 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1383 hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1384 #else
1385 HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1386 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1387
1388 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
1389 }
1390
1391 /* Handle Incomplete ISO OUT Interrupt */
1392 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
1393 {
1394 /* Keep application checking the corresponding Iso OUT endpoint
1395 causing the incomplete Interrupt */
1396 epnum = 0U;
1397
1398 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1399 hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1400 #else
1401 HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1402 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1403
1404 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
1405 }
1406
1407 /* Handle Connection event Interrupt */
1408 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
1409 {
1410 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1411 hpcd->ConnectCallback(hpcd);
1412 #else
1413 HAL_PCD_ConnectCallback(hpcd);
1414 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1415
1416 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
1417 }
1418
1419 /* Handle Disconnection event Interrupt */
1420 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
1421 {
1422 temp = hpcd->Instance->GOTGINT;
1423
1424 if ((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
1425 {
1426 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1427 hpcd->DisconnectCallback(hpcd);
1428 #else
1429 HAL_PCD_DisconnectCallback(hpcd);
1430 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1431 }
1432 hpcd->Instance->GOTGINT |= temp;
1433 }
1434 }
1435 }
1436
1437
1438 /**
1439 * @brief Handles PCD Wakeup interrupt request.
1440 * @param hpcd PCD handle
1441 * @retval HAL status
1442 */
HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef * hpcd)1443 void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
1444 {
1445 USB_OTG_GlobalTypeDef *USBx;
1446
1447 USBx = hpcd->Instance;
1448
1449 if ((USBx->CID & (0x1U << 8)) == 0U)
1450 {
1451 /* Clear EXTI pending Bit */
1452 __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG();
1453 }
1454 else
1455 {
1456 /* Clear EXTI pending Bit */
1457 __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG();
1458 }
1459 }
1460 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1461
1462
1463 /**
1464 * @brief Data OUT stage callback.
1465 * @param hpcd PCD handle
1466 * @param epnum endpoint number
1467 * @retval None
1468 */
HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1469 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1470 {
1471 /* Prevent unused argument(s) compilation warning */
1472 UNUSED(hpcd);
1473 UNUSED(epnum);
1474
1475 /* NOTE : This function should not be modified, when the callback is needed,
1476 the HAL_PCD_DataOutStageCallback could be implemented in the user file
1477 */
1478 }
1479
1480 /**
1481 * @brief Data IN stage callback
1482 * @param hpcd PCD handle
1483 * @param epnum endpoint number
1484 * @retval None
1485 */
HAL_PCD_DataInStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1486 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1487 {
1488 /* Prevent unused argument(s) compilation warning */
1489 UNUSED(hpcd);
1490 UNUSED(epnum);
1491
1492 /* NOTE : This function should not be modified, when the callback is needed,
1493 the HAL_PCD_DataInStageCallback could be implemented in the user file
1494 */
1495 }
1496 /**
1497 * @brief Setup stage callback
1498 * @param hpcd PCD handle
1499 * @retval None
1500 */
HAL_PCD_SetupStageCallback(PCD_HandleTypeDef * hpcd)1501 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
1502 {
1503 /* Prevent unused argument(s) compilation warning */
1504 UNUSED(hpcd);
1505
1506 /* NOTE : This function should not be modified, when the callback is needed,
1507 the HAL_PCD_SetupStageCallback could be implemented in the user file
1508 */
1509 }
1510
1511 /**
1512 * @brief USB Start Of Frame callback.
1513 * @param hpcd PCD handle
1514 * @retval None
1515 */
HAL_PCD_SOFCallback(PCD_HandleTypeDef * hpcd)1516 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
1517 {
1518 /* Prevent unused argument(s) compilation warning */
1519 UNUSED(hpcd);
1520
1521 /* NOTE : This function should not be modified, when the callback is needed,
1522 the HAL_PCD_SOFCallback could be implemented in the user file
1523 */
1524 }
1525
1526 /**
1527 * @brief USB Reset callback.
1528 * @param hpcd PCD handle
1529 * @retval None
1530 */
HAL_PCD_ResetCallback(PCD_HandleTypeDef * hpcd)1531 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
1532 {
1533 /* Prevent unused argument(s) compilation warning */
1534 UNUSED(hpcd);
1535
1536 /* NOTE : This function should not be modified, when the callback is needed,
1537 the HAL_PCD_ResetCallback could be implemented in the user file
1538 */
1539 }
1540
1541 /**
1542 * @brief Suspend event callback.
1543 * @param hpcd PCD handle
1544 * @retval None
1545 */
HAL_PCD_SuspendCallback(PCD_HandleTypeDef * hpcd)1546 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
1547 {
1548 /* Prevent unused argument(s) compilation warning */
1549 UNUSED(hpcd);
1550
1551 /* NOTE : This function should not be modified, when the callback is needed,
1552 the HAL_PCD_SuspendCallback could be implemented in the user file
1553 */
1554 }
1555
1556 /**
1557 * @brief Resume event callback.
1558 * @param hpcd PCD handle
1559 * @retval None
1560 */
HAL_PCD_ResumeCallback(PCD_HandleTypeDef * hpcd)1561 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
1562 {
1563 /* Prevent unused argument(s) compilation warning */
1564 UNUSED(hpcd);
1565
1566 /* NOTE : This function should not be modified, when the callback is needed,
1567 the HAL_PCD_ResumeCallback could be implemented in the user file
1568 */
1569 }
1570
1571 /**
1572 * @brief Incomplete ISO OUT callback.
1573 * @param hpcd PCD handle
1574 * @param epnum endpoint number
1575 * @retval None
1576 */
HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1577 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1578 {
1579 /* Prevent unused argument(s) compilation warning */
1580 UNUSED(hpcd);
1581 UNUSED(epnum);
1582
1583 /* NOTE : This function should not be modified, when the callback is needed,
1584 the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
1585 */
1586 }
1587
1588 /**
1589 * @brief Incomplete ISO IN callback.
1590 * @param hpcd PCD handle
1591 * @param epnum endpoint number
1592 * @retval None
1593 */
HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1594 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1595 {
1596 /* Prevent unused argument(s) compilation warning */
1597 UNUSED(hpcd);
1598 UNUSED(epnum);
1599
1600 /* NOTE : This function should not be modified, when the callback is needed,
1601 the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1602 */
1603 }
1604
1605 /**
1606 * @brief Connection event callback.
1607 * @param hpcd PCD handle
1608 * @retval None
1609 */
HAL_PCD_ConnectCallback(PCD_HandleTypeDef * hpcd)1610 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
1611 {
1612 /* Prevent unused argument(s) compilation warning */
1613 UNUSED(hpcd);
1614
1615 /* NOTE : This function should not be modified, when the callback is needed,
1616 the HAL_PCD_ConnectCallback could be implemented in the user file
1617 */
1618 }
1619
1620 /**
1621 * @brief Disconnection event callback.
1622 * @param hpcd PCD handle
1623 * @retval None
1624 */
HAL_PCD_DisconnectCallback(PCD_HandleTypeDef * hpcd)1625 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
1626 {
1627 /* Prevent unused argument(s) compilation warning */
1628 UNUSED(hpcd);
1629
1630 /* NOTE : This function should not be modified, when the callback is needed,
1631 the HAL_PCD_DisconnectCallback could be implemented in the user file
1632 */
1633 }
1634
1635 /**
1636 * @}
1637 */
1638
1639 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
1640 * @brief management functions
1641 *
1642 @verbatim
1643 ===============================================================================
1644 ##### Peripheral Control functions #####
1645 ===============================================================================
1646 [..]
1647 This subsection provides a set of functions allowing to control the PCD data
1648 transfers.
1649
1650 @endverbatim
1651 * @{
1652 */
1653
1654 /**
1655 * @brief Connect the USB device
1656 * @param hpcd PCD handle
1657 * @retval HAL status
1658 */
HAL_PCD_DevConnect(PCD_HandleTypeDef * hpcd)1659 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
1660 {
1661 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1662
1663 __HAL_LOCK(hpcd);
1664
1665 if ((hpcd->Init.battery_charging_enable == 1U) &&
1666 (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
1667 {
1668 /* Enable USB Transceiver */
1669 USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
1670 }
1671 (void)USB_DevConnect(hpcd->Instance);
1672 __HAL_UNLOCK(hpcd);
1673
1674 return HAL_OK;
1675 }
1676
1677 /**
1678 * @brief Disconnect the USB device.
1679 * @param hpcd PCD handle
1680 * @retval HAL status
1681 */
HAL_PCD_DevDisconnect(PCD_HandleTypeDef * hpcd)1682 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
1683 {
1684 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1685
1686 __HAL_LOCK(hpcd);
1687 (void)USB_DevDisconnect(hpcd->Instance);
1688
1689 if ((hpcd->Init.battery_charging_enable == 1U) &&
1690 (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
1691 {
1692 /* Disable USB Transceiver */
1693 USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
1694 }
1695
1696 __HAL_UNLOCK(hpcd);
1697
1698 return HAL_OK;
1699 }
1700
1701 /**
1702 * @brief Set the USB Device address.
1703 * @param hpcd PCD handle
1704 * @param address new device address
1705 * @retval HAL status
1706 */
HAL_PCD_SetAddress(PCD_HandleTypeDef * hpcd,uint8_t address)1707 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
1708 {
1709 __HAL_LOCK(hpcd);
1710 hpcd->USB_Address = address;
1711 (void)USB_SetDevAddress(hpcd->Instance, address);
1712 __HAL_UNLOCK(hpcd);
1713
1714 return HAL_OK;
1715 }
1716 /**
1717 * @brief Open and configure an endpoint.
1718 * @param hpcd PCD handle
1719 * @param ep_addr endpoint address
1720 * @param ep_mps endpoint max packet size
1721 * @param ep_type endpoint type
1722 * @retval HAL status
1723 */
HAL_PCD_EP_Open(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint16_t ep_mps,uint8_t ep_type)1724 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
1725 uint16_t ep_mps, uint8_t ep_type)
1726 {
1727 HAL_StatusTypeDef ret = HAL_OK;
1728 PCD_EPTypeDef *ep;
1729
1730 if ((ep_addr & 0x80U) == 0x80U)
1731 {
1732 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1733 ep->is_in = 1U;
1734 }
1735 else
1736 {
1737 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1738 ep->is_in = 0U;
1739 }
1740
1741 ep->num = ep_addr & EP_ADDR_MSK;
1742 ep->maxpacket = ep_mps;
1743 ep->type = ep_type;
1744
1745 if (ep->is_in != 0U)
1746 {
1747 /* Assign a Tx FIFO */
1748 ep->tx_fifo_num = ep->num;
1749 }
1750 /* Set initial data PID. */
1751 if (ep_type == EP_TYPE_BULK)
1752 {
1753 ep->data_pid_start = 0U;
1754 }
1755
1756 __HAL_LOCK(hpcd);
1757 (void)USB_ActivateEndpoint(hpcd->Instance, ep);
1758 __HAL_UNLOCK(hpcd);
1759
1760 return ret;
1761 }
1762
1763 /**
1764 * @brief Deactivate an endpoint.
1765 * @param hpcd PCD handle
1766 * @param ep_addr endpoint address
1767 * @retval HAL status
1768 */
HAL_PCD_EP_Close(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1769 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1770 {
1771 PCD_EPTypeDef *ep;
1772
1773 if ((ep_addr & 0x80U) == 0x80U)
1774 {
1775 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1776 ep->is_in = 1U;
1777 }
1778 else
1779 {
1780 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1781 ep->is_in = 0U;
1782 }
1783 ep->num = ep_addr & EP_ADDR_MSK;
1784
1785 __HAL_LOCK(hpcd);
1786 (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
1787 __HAL_UNLOCK(hpcd);
1788 return HAL_OK;
1789 }
1790
1791
1792 /**
1793 * @brief Receive an amount of data.
1794 * @param hpcd PCD handle
1795 * @param ep_addr endpoint address
1796 * @param pBuf pointer to the reception buffer
1797 * @param len amount of data to be received
1798 * @retval HAL status
1799 */
HAL_PCD_EP_Receive(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)1800 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1801 {
1802 PCD_EPTypeDef *ep;
1803
1804 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1805
1806 /*setup and start the Xfer */
1807 ep->xfer_buff = pBuf;
1808 ep->xfer_len = len;
1809 ep->xfer_count = 0U;
1810 ep->is_in = 0U;
1811 ep->num = ep_addr & EP_ADDR_MSK;
1812
1813 if (hpcd->Init.dma_enable == 1U)
1814 {
1815 ep->dma_addr = (uint32_t)pBuf;
1816 }
1817
1818 if ((ep_addr & EP_ADDR_MSK) == 0U)
1819 {
1820 (void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
1821 }
1822 else
1823 {
1824 (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
1825 }
1826
1827 return HAL_OK;
1828 }
1829
1830 /**
1831 * @brief Get Received Data Size
1832 * @param hpcd PCD handle
1833 * @param ep_addr endpoint address
1834 * @retval Data Size
1835 */
HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1836 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1837 {
1838 return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
1839 }
1840 /**
1841 * @brief Send an amount of data
1842 * @param hpcd PCD handle
1843 * @param ep_addr endpoint address
1844 * @param pBuf pointer to the transmission buffer
1845 * @param len amount of data to be sent
1846 * @retval HAL status
1847 */
HAL_PCD_EP_Transmit(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)1848 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1849 {
1850 PCD_EPTypeDef *ep;
1851
1852 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1853
1854 /*setup and start the Xfer */
1855 ep->xfer_buff = pBuf;
1856 ep->xfer_len = len;
1857 ep->xfer_count = 0U;
1858 ep->is_in = 1U;
1859 ep->num = ep_addr & EP_ADDR_MSK;
1860
1861 if (hpcd->Init.dma_enable == 1U)
1862 {
1863 ep->dma_addr = (uint32_t)pBuf;
1864 }
1865
1866 if ((ep_addr & EP_ADDR_MSK) == 0U)
1867 {
1868 (void)USB_EP0StartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
1869 }
1870 else
1871 {
1872 (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
1873 }
1874
1875 return HAL_OK;
1876 }
1877
1878 /**
1879 * @brief Set a STALL condition over an endpoint
1880 * @param hpcd PCD handle
1881 * @param ep_addr endpoint address
1882 * @retval HAL status
1883 */
HAL_PCD_EP_SetStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1884 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1885 {
1886 PCD_EPTypeDef *ep;
1887
1888 if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
1889 {
1890 return HAL_ERROR;
1891 }
1892
1893 if ((0x80U & ep_addr) == 0x80U)
1894 {
1895 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1896 ep->is_in = 1U;
1897 }
1898 else
1899 {
1900 ep = &hpcd->OUT_ep[ep_addr];
1901 ep->is_in = 0U;
1902 }
1903
1904 ep->is_stall = 1U;
1905 ep->num = ep_addr & EP_ADDR_MSK;
1906
1907 __HAL_LOCK(hpcd);
1908
1909 (void)USB_EPSetStall(hpcd->Instance, ep);
1910
1911 if ((ep_addr & EP_ADDR_MSK) == 0U)
1912 {
1913 (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
1914 }
1915
1916 __HAL_UNLOCK(hpcd);
1917
1918 return HAL_OK;
1919 }
1920
1921 /**
1922 * @brief Clear a STALL condition over in an endpoint
1923 * @param hpcd PCD handle
1924 * @param ep_addr endpoint address
1925 * @retval HAL status
1926 */
HAL_PCD_EP_ClrStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1927 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1928 {
1929 PCD_EPTypeDef *ep;
1930
1931 if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
1932 {
1933 return HAL_ERROR;
1934 }
1935
1936 if ((0x80U & ep_addr) == 0x80U)
1937 {
1938 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1939 ep->is_in = 1U;
1940 }
1941 else
1942 {
1943 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1944 ep->is_in = 0U;
1945 }
1946
1947 ep->is_stall = 0U;
1948 ep->num = ep_addr & EP_ADDR_MSK;
1949
1950 __HAL_LOCK(hpcd);
1951 (void)USB_EPClearStall(hpcd->Instance, ep);
1952 __HAL_UNLOCK(hpcd);
1953
1954 return HAL_OK;
1955 }
1956
1957 /**
1958 * @brief Flush an endpoint
1959 * @param hpcd PCD handle
1960 * @param ep_addr endpoint address
1961 * @retval HAL status
1962 */
HAL_PCD_EP_Flush(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1963 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1964 {
1965 __HAL_LOCK(hpcd);
1966
1967 if ((ep_addr & 0x80U) == 0x80U)
1968 {
1969 (void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
1970 }
1971 else
1972 {
1973 (void)USB_FlushRxFifo(hpcd->Instance);
1974 }
1975
1976 __HAL_UNLOCK(hpcd);
1977
1978 return HAL_OK;
1979 }
1980
1981 /**
1982 * @brief Activate remote wakeup signalling
1983 * @param hpcd PCD handle
1984 * @retval HAL status
1985 */
HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1986 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1987 {
1988 return (USB_ActivateRemoteWakeup(hpcd->Instance));
1989 }
1990
1991 /**
1992 * @brief De-activate remote wakeup signalling.
1993 * @param hpcd PCD handle
1994 * @retval HAL status
1995 */
HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1996 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1997 {
1998 return (USB_DeActivateRemoteWakeup(hpcd->Instance));
1999 }
2000
2001 /**
2002 * @}
2003 */
2004
2005 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
2006 * @brief Peripheral State functions
2007 *
2008 @verbatim
2009 ===============================================================================
2010 ##### Peripheral State functions #####
2011 ===============================================================================
2012 [..]
2013 This subsection permits to get in run-time the status of the peripheral
2014 and the data flow.
2015
2016 @endverbatim
2017 * @{
2018 */
2019
2020 /**
2021 * @brief Return the PCD handle state.
2022 * @param hpcd PCD handle
2023 * @retval HAL state
2024 */
HAL_PCD_GetState(PCD_HandleTypeDef * hpcd)2025 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
2026 {
2027 return hpcd->State;
2028 }
2029
2030 /**
2031 * @}
2032 */
2033
2034 /**
2035 * @}
2036 */
2037
2038 /* Private functions ---------------------------------------------------------*/
2039 /** @addtogroup PCD_Private_Functions
2040 * @{
2041 */
2042 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
2043 /**
2044 * @brief Check FIFO for the next packet to be loaded.
2045 * @param hpcd PCD handle
2046 * @param epnum endpoint number
2047 * @retval HAL status
2048 */
PCD_WriteEmptyTxFifo(PCD_HandleTypeDef * hpcd,uint32_t epnum)2049 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2050 {
2051 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2052 uint32_t USBx_BASE = (uint32_t)USBx;
2053 USB_OTG_EPTypeDef *ep;
2054 uint32_t len;
2055 uint32_t len32b;
2056 uint32_t fifoemptymsk;
2057
2058 ep = &hpcd->IN_ep[epnum];
2059
2060 if (ep->xfer_count > ep->xfer_len)
2061 {
2062 return HAL_ERROR;
2063 }
2064
2065 len = ep->xfer_len - ep->xfer_count;
2066
2067 if (len > ep->maxpacket)
2068 {
2069 len = ep->maxpacket;
2070 }
2071
2072 len32b = (len + 3U) / 4U;
2073
2074 while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
2075 (ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
2076 {
2077 /* Write the FIFO */
2078 len = ep->xfer_len - ep->xfer_count;
2079
2080 if (len > ep->maxpacket)
2081 {
2082 len = ep->maxpacket;
2083 }
2084 len32b = (len + 3U) / 4U;
2085
2086 (void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len,
2087 (uint8_t)hpcd->Init.dma_enable);
2088
2089 ep->xfer_buff += len;
2090 ep->xfer_count += len;
2091 }
2092
2093 if (ep->xfer_len <= ep->xfer_count)
2094 {
2095 fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
2096 USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
2097 }
2098
2099 return HAL_OK;
2100 }
2101
2102
2103 /**
2104 * @brief process EP OUT transfer complete interrupt.
2105 * @param hpcd PCD handle
2106 * @param epnum endpoint number
2107 * @retval HAL status
2108 */
PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef * hpcd,uint32_t epnum)2109 static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2110 {
2111 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2112 uint32_t USBx_BASE = (uint32_t)USBx;
2113 uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);
2114 uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
2115
2116 if (hpcd->Init.dma_enable == 1U)
2117 {
2118 if ((DoepintReg & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) /* Class C */
2119 {
2120 /* StupPktRcvd = 1 this is a setup packet */
2121 if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
2122 ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
2123 {
2124 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2125 }
2126 }
2127 else if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) /* Class E */
2128 {
2129 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
2130 }
2131 else if ((DoepintReg & (USB_OTG_DOEPINT_STUP | USB_OTG_DOEPINT_OTEPSPR)) == 0U)
2132 {
2133 /* StupPktRcvd = 1 this is a setup packet */
2134 if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
2135 ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
2136 {
2137 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2138 }
2139 else
2140 {
2141 /* out data packet received over EP0 */
2142 hpcd->OUT_ep[epnum].xfer_count =
2143 hpcd->OUT_ep[epnum].maxpacket -
2144 (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
2145
2146 hpcd->OUT_ep[epnum].xfer_buff += hpcd->OUT_ep[epnum].maxpacket;
2147
2148 if ((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U))
2149 {
2150 /* this is ZLP, so prepare EP0 for next setup */
2151 (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
2152 }
2153 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2154 hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2155 #else
2156 HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2157 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2158 }
2159 }
2160 else
2161 {
2162 /* ... */
2163 }
2164 }
2165 else
2166 {
2167 if (gSNPSiD == USB_OTG_CORE_ID_310A)
2168 {
2169 /* StupPktRcvd = 1 this is a setup packet */
2170 if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
2171 {
2172 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2173 }
2174 else
2175 {
2176 if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
2177 {
2178 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
2179 }
2180
2181 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2182 hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2183 #else
2184 HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2185 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2186 }
2187 }
2188 else
2189 {
2190 if ((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U))
2191 {
2192 /* this is ZLP, so prepare EP0 for next setup */
2193 (void)USB_EP0_OutStart(hpcd->Instance, 0U, (uint8_t *)hpcd->Setup);
2194 }
2195
2196 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2197 hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2198 #else
2199 HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2200 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2201 }
2202 }
2203
2204 return HAL_OK;
2205 }
2206
2207
2208 /**
2209 * @brief process EP OUT setup packet received interrupt.
2210 * @param hpcd PCD handle
2211 * @param epnum endpoint number
2212 * @retval HAL status
2213 */
PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef * hpcd,uint32_t epnum)2214 static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2215 {
2216 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2217 uint32_t USBx_BASE = (uint32_t)USBx;
2218 uint32_t gSNPSiD = *(__IO uint32_t *)(&USBx->CID + 0x1U);
2219 uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
2220
2221 if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
2222 ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
2223 {
2224 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2225 }
2226
2227 /* Inform the upper layer that a setup packet is available */
2228 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2229 hpcd->SetupStageCallback(hpcd);
2230 #else
2231 HAL_PCD_SetupStageCallback(hpcd);
2232 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2233
2234 if ((gSNPSiD > USB_OTG_CORE_ID_300A) && (hpcd->Init.dma_enable == 1U))
2235 {
2236 (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
2237 }
2238
2239 return HAL_OK;
2240 }
2241 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2242
2243
2244 /**
2245 * @}
2246 */
2247 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2248 #endif /* HAL_PCD_MODULE_ENABLED */
2249
2250 /**
2251 * @}
2252 */
2253
2254 /**
2255 * @}
2256 */
2257
2258 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2259