source: S-port/trunk/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 61.5 KB
Line 
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>&copy; 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)
91static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
92static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
93static 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 */
123HAL_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 */
244HAL_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 */
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 */
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 */
327HAL_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 */
440HAL_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 */
539HAL_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 */
580HAL_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 */
613HAL_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 */
654HAL_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 */
687HAL_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 to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
725 * @param hpcd PCD handle
726 * @retval HAL status
727 */
728HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
729{
730 HAL_StatusTypeDef status = HAL_OK;
731
732 /* Process locked */
733 __HAL_LOCK(hpcd);
734
735 if (hpcd->State == HAL_PCD_STATE_READY)
736 {
737 hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback */
738 }
739 else
740 {
741 /* Update the error code */
742 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
743
744 /* Return error status */
745 status = HAL_ERROR;
746 }
747
748 /* Release Lock */
749 __HAL_UNLOCK(hpcd);
750
751 return status;
752}
753
754/**
755 * @brief Register USB PCD Iso IN incomplete Callback
756 * To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
757 * @param hpcd PCD handle
758 * @param pCallback pointer to the USB PCD Iso IN incomplete Callback function
759 * @retval HAL status
760 */
761HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
762 pPCD_IsoInIncpltCallbackTypeDef pCallback)
763{
764 HAL_StatusTypeDef status = HAL_OK;
765
766 if (pCallback == NULL)
767 {
768 /* Update the error code */
769 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
770
771 return HAL_ERROR;
772 }
773
774 /* Process locked */
775 __HAL_LOCK(hpcd);
776
777 if (hpcd->State == HAL_PCD_STATE_READY)
778 {
779 hpcd->ISOINIncompleteCallback = pCallback;
780 }
781 else
782 {
783 /* Update the error code */
784 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
785
786 /* Return error status */
787 status = HAL_ERROR;
788 }
789
790 /* Release Lock */
791 __HAL_UNLOCK(hpcd);
792
793 return status;
794}
795
796/**
797 * @brief Unregister the USB PCD Iso IN incomplete Callback
798 * USB PCD Iso IN incomplete Callback is redirected to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
799 * @param hpcd PCD handle
800 * @retval HAL status
801 */
802HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
803{
804 HAL_StatusTypeDef status = HAL_OK;
805
806 /* Process locked */
807 __HAL_LOCK(hpcd);
808
809 if (hpcd->State == HAL_PCD_STATE_READY)
810 {
811 hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback */
812 }
813 else
814 {
815 /* Update the error code */
816 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
817
818 /* Return error status */
819 status = HAL_ERROR;
820 }
821
822 /* Release Lock */
823 __HAL_UNLOCK(hpcd);
824
825 return status;
826}
827
828/**
829 * @brief Register USB PCD BCD Callback
830 * To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
831 * @param hpcd PCD handle
832 * @param pCallback pointer to the USB PCD BCD Callback function
833 * @retval HAL status
834 */
835HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
836{
837 HAL_StatusTypeDef status = HAL_OK;
838
839 if (pCallback == NULL)
840 {
841 /* Update the error code */
842 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
843
844 return HAL_ERROR;
845 }
846
847 /* Process locked */
848 __HAL_LOCK(hpcd);
849
850 if (hpcd->State == HAL_PCD_STATE_READY)
851 {
852 hpcd->BCDCallback = pCallback;
853 }
854 else
855 {
856 /* Update the error code */
857 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
858
859 /* Return error status */
860 status = HAL_ERROR;
861 }
862
863 /* Release Lock */
864 __HAL_UNLOCK(hpcd);
865
866 return status;
867}
868
869/**
870 * @brief Unregister the USB PCD BCD Callback
871 * USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
872 * @param hpcd PCD handle
873 * @retval HAL status
874 */
875HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
876{
877 HAL_StatusTypeDef status = HAL_OK;
878
879 /* Process locked */
880 __HAL_LOCK(hpcd);
881
882 if (hpcd->State == HAL_PCD_STATE_READY)
883 {
884 hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback */
885 }
886 else
887 {
888 /* Update the error code */
889 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
890
891 /* Return error status */
892 status = HAL_ERROR;
893 }
894
895 /* Release Lock */
896 __HAL_UNLOCK(hpcd);
897
898 return status;
899}
900
901/**
902 * @brief Register USB PCD LPM Callback
903 * To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
904 * @param hpcd PCD handle
905 * @param pCallback pointer to the USB PCD LPM Callback function
906 * @retval HAL status
907 */
908HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
909{
910 HAL_StatusTypeDef status = HAL_OK;
911
912 if (pCallback == NULL)
913 {
914 /* Update the error code */
915 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
916
917 return HAL_ERROR;
918 }
919
920 /* Process locked */
921 __HAL_LOCK(hpcd);
922
923 if (hpcd->State == HAL_PCD_STATE_READY)
924 {
925 hpcd->LPMCallback = pCallback;
926 }
927 else
928 {
929 /* Update the error code */
930 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
931
932 /* Return error status */
933 status = HAL_ERROR;
934 }
935
936 /* Release Lock */
937 __HAL_UNLOCK(hpcd);
938
939 return status;
940}
941
942/**
943 * @brief Unregister the USB PCD LPM Callback
944 * USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
945 * @param hpcd PCD handle
946 * @retval HAL status
947 */
948HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
949{
950 HAL_StatusTypeDef status = HAL_OK;
951
952 /* Process locked */
953 __HAL_LOCK(hpcd);
954
955 if (hpcd->State == HAL_PCD_STATE_READY)
956 {
957 hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback */
958 }
959 else
960 {
961 /* Update the error code */
962 hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
963
964 /* Return error status */
965 status = HAL_ERROR;
966 }
967
968 /* Release Lock */
969 __HAL_UNLOCK(hpcd);
970
971 return status;
972}
973#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
974
975/**
976 * @}
977 */
978
979/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
980 * @brief Data transfers functions
981 *
982@verbatim
983 ===============================================================================
984 ##### IO operation functions #####
985 ===============================================================================
986 [..]
987 This subsection provides a set of functions allowing to manage the PCD data
988 transfers.
989
990@endverbatim
991 * @{
992 */
993
994/**
995 * @brief Start the USB device
996 * @param hpcd PCD handle
997 * @retval HAL status
998 */
999HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
1000{
1001 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1002
1003 __HAL_LOCK(hpcd);
1004
1005 if ((hpcd->Init.battery_charging_enable == 1U) &&
1006 (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
1007 {
1008 /* Enable USB Transceiver */
1009 USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
1010 }
1011
1012 __HAL_PCD_ENABLE(hpcd);
1013 (void)USB_DevConnect(hpcd->Instance);
1014 __HAL_UNLOCK(hpcd);
1015
1016 return HAL_OK;
1017}
1018
1019/**
1020 * @brief Stop the USB device.
1021 * @param hpcd PCD handle
1022 * @retval HAL status
1023 */
1024HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
1025{
1026 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1027
1028 __HAL_LOCK(hpcd);
1029 __HAL_PCD_DISABLE(hpcd);
1030 (void)USB_DevDisconnect(hpcd->Instance);
1031
1032 (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
1033
1034 if ((hpcd->Init.battery_charging_enable == 1U) &&
1035 (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
1036 {
1037 /* Disable USB Transceiver */
1038 USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
1039 }
1040 __HAL_UNLOCK(hpcd);
1041
1042 return HAL_OK;
1043}
1044
1045#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1046/**
1047 * @brief Handles PCD interrupt request.
1048 * @param hpcd PCD handle
1049 * @retval HAL status
1050 */
1051void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
1052{
1053 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1054 uint32_t USBx_BASE = (uint32_t)USBx;
1055 uint32_t i, ep_intr, epint, epnum;
1056 uint32_t fifoemptymsk, temp;
1057 USB_OTG_EPTypeDef *ep;
1058
1059 /* ensure that we are in device mode */
1060 if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
1061 {
1062 /* avoid spurious interrupt */
1063 if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
1064 {
1065 return;
1066 }
1067
1068 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
1069 {
1070 /* incorrect mode, acknowledge the interrupt */
1071 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
1072 }
1073
1074 /* Handle RxQLevel Interrupt */
1075 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
1076 {
1077 USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
1078
1079 temp = USBx->GRXSTSP;
1080
1081 ep = &hpcd->OUT_ep[temp & USB_OTG_GRXSTSP_EPNUM];
1082
1083 if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
1084 {
1085 if ((temp & USB_OTG_GRXSTSP_BCNT) != 0U)
1086 {
1087 (void)USB_ReadPacket(USBx, ep->xfer_buff,
1088 (uint16_t)((temp & USB_OTG_GRXSTSP_BCNT) >> 4));
1089
1090 ep->xfer_buff += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
1091 ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
1092 }
1093 }
1094 else if (((temp & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
1095 {
1096 (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
1097 ep->xfer_count += (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
1098 }
1099 else
1100 {
1101 /* ... */
1102 }
1103 USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
1104 }
1105
1106 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
1107 {
1108 epnum = 0U;
1109
1110 /* Read in the device interrupt bits */
1111 ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
1112
1113 while (ep_intr != 0U)
1114 {
1115 if ((ep_intr & 0x1U) != 0U)
1116 {
1117 epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
1118
1119 if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
1120 {
1121 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
1122 (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
1123 }
1124
1125 if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
1126 {
1127 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
1128 /* Class B setup phase done for previous decoded setup */
1129 (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
1130 }
1131
1132 if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
1133 {
1134 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
1135 }
1136
1137 /* Clear Status Phase Received interrupt */
1138 if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
1139 {
1140 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
1141 }
1142
1143 /* Clear OUT NAK interrupt */
1144 if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
1145 {
1146 CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
1147 }
1148 }
1149 epnum++;
1150 ep_intr >>= 1U;
1151 }
1152 }
1153
1154 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
1155 {
1156 /* Read in the device interrupt bits */
1157 ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
1158
1159 epnum = 0U;
1160
1161 while (ep_intr != 0U)
1162 {
1163 if ((ep_intr & 0x1U) != 0U) /* In ITR */
1164 {
1165 epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
1166
1167 if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
1168 {
1169 fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
1170 USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1171
1172 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
1173
1174 if (hpcd->Init.dma_enable == 1U)
1175 {
1176 hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
1177
1178 /* this is ZLP, so prepare EP0 for next setup */
1179 if ((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U))
1180 {
1181 /* prepare to rx more setup packets */
1182 (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
1183 }
1184 }
1185
1186#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1187 hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
1188#else
1189 HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
1190#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1191 }
1192 if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
1193 {
1194 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
1195 }
1196 if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
1197 {
1198 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
1199 }
1200 if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
1201 {
1202 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
1203 }
1204 if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
1205 {
1206 CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
1207 }
1208 if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
1209 {
1210 (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
1211 }
1212 }
1213 epnum++;
1214 ep_intr >>= 1U;
1215 }
1216 }
1217
1218 /* Handle Resume Interrupt */
1219 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
1220 {
1221 /* Clear the Remote Wake-up Signaling */
1222 USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1223
1224 if (hpcd->LPM_State == LPM_L1)
1225 {
1226 hpcd->LPM_State = LPM_L0;
1227
1228#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1229 hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
1230#else
1231 HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
1232#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1233 }
1234 else
1235 {
1236#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1237 hpcd->ResumeCallback(hpcd);
1238#else
1239 HAL_PCD_ResumeCallback(hpcd);
1240#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1241 }
1242
1243 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
1244 }
1245
1246 /* Handle Suspend Interrupt */
1247 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
1248 {
1249 if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
1250 {
1251#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1252 hpcd->SuspendCallback(hpcd);
1253#else
1254 HAL_PCD_SuspendCallback(hpcd);
1255#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1256 }
1257 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
1258 }
1259#if defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
1260 /* Handle LPM Interrupt */
1261 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
1262 {
1263 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);
1264
1265 if (hpcd->LPM_State == LPM_L0)
1266 {
1267 hpcd->LPM_State = LPM_L1;
1268 hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >> 2U;
1269
1270#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1271 hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
1272#else
1273 HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
1274#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1275 }
1276 else
1277 {
1278#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1279 hpcd->SuspendCallback(hpcd);
1280#else
1281 HAL_PCD_SuspendCallback(hpcd);
1282#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1283 }
1284 }
1285#endif /* defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx) */
1286 /* Handle Reset Interrupt */
1287 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
1288 {
1289 USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1290 (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
1291
1292 for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
1293 {
1294 USBx_INEP(i)->DIEPINT = 0xFB7FU;
1295 USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
1296 USBx_INEP(i)->DIEPCTL |= USB_OTG_DIEPCTL_SNAK;
1297 USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
1298 USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
1299 USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
1300 }
1301 USBx_DEVICE->DAINTMSK |= 0x10001U;
1302
1303 if (hpcd->Init.use_dedicated_ep1 != 0U)
1304 {
1305 USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
1306 USB_OTG_DOEPMSK_XFRCM |
1307 USB_OTG_DOEPMSK_EPDM;
1308
1309 USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
1310 USB_OTG_DIEPMSK_XFRCM |
1311 USB_OTG_DIEPMSK_EPDM;
1312 }
1313 else
1314 {
1315 USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
1316 USB_OTG_DOEPMSK_XFRCM |
1317 USB_OTG_DOEPMSK_EPDM |
1318 USB_OTG_DOEPMSK_OTEPSPRM |
1319 USB_OTG_DOEPMSK_NAKM;
1320
1321 USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
1322 USB_OTG_DIEPMSK_XFRCM |
1323 USB_OTG_DIEPMSK_EPDM;
1324 }
1325
1326 /* Set Default Address to 0 */
1327 USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
1328
1329 /* setup EP0 to receive SETUP packets */
1330 (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable,
1331 (uint8_t *)hpcd->Setup);
1332
1333 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
1334 }
1335
1336 /* Handle Enumeration done Interrupt */
1337 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
1338 {
1339 (void)USB_ActivateSetup(hpcd->Instance);
1340 hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
1341
1342 /* Set USB Turnaround time */
1343 (void)USB_SetTurnaroundTime(hpcd->Instance,
1344 HAL_RCC_GetHCLKFreq(),
1345 (uint8_t)hpcd->Init.speed);
1346
1347#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1348 hpcd->ResetCallback(hpcd);
1349#else
1350 HAL_PCD_ResetCallback(hpcd);
1351#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1352
1353 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
1354 }
1355
1356 /* Handle SOF Interrupt */
1357 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
1358 {
1359#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1360 hpcd->SOFCallback(hpcd);
1361#else
1362 HAL_PCD_SOFCallback(hpcd);
1363#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1364
1365 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
1366 }
1367
1368 /* Handle Incomplete ISO IN Interrupt */
1369 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
1370 {
1371 /* Keep application checking the corresponding Iso IN endpoint
1372 causing the incomplete Interrupt */
1373 epnum = 0U;
1374
1375#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1376 hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1377#else
1378 HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1379#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1380
1381 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
1382 }
1383
1384 /* Handle Incomplete ISO OUT Interrupt */
1385 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
1386 {
1387 /* Keep application checking the corresponding Iso OUT endpoint
1388 causing the incomplete Interrupt */
1389 epnum = 0U;
1390
1391#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1392 hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1393#else
1394 HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1395#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1396
1397 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
1398 }
1399
1400 /* Handle Connection event Interrupt */
1401 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
1402 {
1403#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1404 hpcd->ConnectCallback(hpcd);
1405#else
1406 HAL_PCD_ConnectCallback(hpcd);
1407#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1408
1409 __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
1410 }
1411
1412 /* Handle Disconnection event Interrupt */
1413 if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
1414 {
1415 temp = hpcd->Instance->GOTGINT;
1416
1417 if ((temp & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
1418 {
1419#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1420 hpcd->DisconnectCallback(hpcd);
1421#else
1422 HAL_PCD_DisconnectCallback(hpcd);
1423#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1424 }
1425 hpcd->Instance->GOTGINT |= temp;
1426 }
1427 }
1428}
1429
1430
1431/**
1432 * @brief Handles PCD Wakeup interrupt request.
1433 * @param hpcd PCD handle
1434 * @retval HAL status
1435 */
1436void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
1437{
1438 USB_OTG_GlobalTypeDef *USBx;
1439
1440 USBx = hpcd->Instance;
1441
1442 if ((USBx->CID & (0x1U << 8)) == 0U)
1443 {
1444 /* Clear EXTI pending Bit */
1445 __HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG();
1446 }
1447 else
1448 {
1449 /* Clear EXTI pending Bit */
1450 __HAL_USB_OTG_HS_WAKEUP_EXTI_CLEAR_FLAG();
1451 }
1452}
1453#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1454
1455
1456/**
1457 * @brief Data OUT stage callback.
1458 * @param hpcd PCD handle
1459 * @param epnum endpoint number
1460 * @retval None
1461 */
1462__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1463{
1464 /* Prevent unused argument(s) compilation warning */
1465 UNUSED(hpcd);
1466 UNUSED(epnum);
1467
1468 /* NOTE : This function should not be modified, when the callback is needed,
1469 the HAL_PCD_DataOutStageCallback could be implemented in the user file
1470 */
1471}
1472
1473/**
1474 * @brief Data IN stage callback
1475 * @param hpcd PCD handle
1476 * @param epnum endpoint number
1477 * @retval None
1478 */
1479__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1480{
1481 /* Prevent unused argument(s) compilation warning */
1482 UNUSED(hpcd);
1483 UNUSED(epnum);
1484
1485 /* NOTE : This function should not be modified, when the callback is needed,
1486 the HAL_PCD_DataInStageCallback could be implemented in the user file
1487 */
1488}
1489/**
1490 * @brief Setup stage callback
1491 * @param hpcd PCD handle
1492 * @retval None
1493 */
1494__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
1495{
1496 /* Prevent unused argument(s) compilation warning */
1497 UNUSED(hpcd);
1498
1499 /* NOTE : This function should not be modified, when the callback is needed,
1500 the HAL_PCD_SetupStageCallback could be implemented in the user file
1501 */
1502}
1503
1504/**
1505 * @brief USB Start Of Frame callback.
1506 * @param hpcd PCD handle
1507 * @retval None
1508 */
1509__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
1510{
1511 /* Prevent unused argument(s) compilation warning */
1512 UNUSED(hpcd);
1513
1514 /* NOTE : This function should not be modified, when the callback is needed,
1515 the HAL_PCD_SOFCallback could be implemented in the user file
1516 */
1517}
1518
1519/**
1520 * @brief USB Reset callback.
1521 * @param hpcd PCD handle
1522 * @retval None
1523 */
1524__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
1525{
1526 /* Prevent unused argument(s) compilation warning */
1527 UNUSED(hpcd);
1528
1529 /* NOTE : This function should not be modified, when the callback is needed,
1530 the HAL_PCD_ResetCallback could be implemented in the user file
1531 */
1532}
1533
1534/**
1535 * @brief Suspend event callback.
1536 * @param hpcd PCD handle
1537 * @retval None
1538 */
1539__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
1540{
1541 /* Prevent unused argument(s) compilation warning */
1542 UNUSED(hpcd);
1543
1544 /* NOTE : This function should not be modified, when the callback is needed,
1545 the HAL_PCD_SuspendCallback could be implemented in the user file
1546 */
1547}
1548
1549/**
1550 * @brief Resume event callback.
1551 * @param hpcd PCD handle
1552 * @retval None
1553 */
1554__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
1555{
1556 /* Prevent unused argument(s) compilation warning */
1557 UNUSED(hpcd);
1558
1559 /* NOTE : This function should not be modified, when the callback is needed,
1560 the HAL_PCD_ResumeCallback could be implemented in the user file
1561 */
1562}
1563
1564/**
1565 * @brief Incomplete ISO OUT callback.
1566 * @param hpcd PCD handle
1567 * @param epnum endpoint number
1568 * @retval None
1569 */
1570__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1571{
1572 /* Prevent unused argument(s) compilation warning */
1573 UNUSED(hpcd);
1574 UNUSED(epnum);
1575
1576 /* NOTE : This function should not be modified, when the callback is needed,
1577 the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
1578 */
1579}
1580
1581/**
1582 * @brief Incomplete ISO IN callback.
1583 * @param hpcd PCD handle
1584 * @param epnum endpoint number
1585 * @retval None
1586 */
1587__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1588{
1589 /* Prevent unused argument(s) compilation warning */
1590 UNUSED(hpcd);
1591 UNUSED(epnum);
1592
1593 /* NOTE : This function should not be modified, when the callback is needed,
1594 the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1595 */
1596}
1597
1598/**
1599 * @brief Connection event callback.
1600 * @param hpcd PCD handle
1601 * @retval None
1602 */
1603__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
1604{
1605 /* Prevent unused argument(s) compilation warning */
1606 UNUSED(hpcd);
1607
1608 /* NOTE : This function should not be modified, when the callback is needed,
1609 the HAL_PCD_ConnectCallback could be implemented in the user file
1610 */
1611}
1612
1613/**
1614 * @brief Disconnection event callback.
1615 * @param hpcd PCD handle
1616 * @retval None
1617 */
1618__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
1619{
1620 /* Prevent unused argument(s) compilation warning */
1621 UNUSED(hpcd);
1622
1623 /* NOTE : This function should not be modified, when the callback is needed,
1624 the HAL_PCD_DisconnectCallback could be implemented in the user file
1625 */
1626}
1627
1628/**
1629 * @}
1630 */
1631
1632/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
1633 * @brief management functions
1634 *
1635@verbatim
1636 ===============================================================================
1637 ##### Peripheral Control functions #####
1638 ===============================================================================
1639 [..]
1640 This subsection provides a set of functions allowing to control the PCD data
1641 transfers.
1642
1643@endverbatim
1644 * @{
1645 */
1646
1647/**
1648 * @brief Connect the USB device
1649 * @param hpcd PCD handle
1650 * @retval HAL status
1651 */
1652HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
1653{
1654#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1655 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1656#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1657
1658 __HAL_LOCK(hpcd);
1659#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1660 if ((hpcd->Init.battery_charging_enable == 1U) &&
1661 (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
1662 {
1663 /* Enable USB Transceiver */
1664 USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
1665 }
1666#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1667 (void)USB_DevConnect(hpcd->Instance);
1668 __HAL_UNLOCK(hpcd);
1669
1670 return HAL_OK;
1671}
1672
1673/**
1674 * @brief Disconnect the USB device.
1675 * @param hpcd PCD handle
1676 * @retval HAL status
1677 */
1678HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
1679{
1680#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1681 USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1682#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1683
1684 __HAL_LOCK(hpcd);
1685 (void)USB_DevDisconnect(hpcd->Instance);
1686
1687#if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1688 if ((hpcd->Init.battery_charging_enable == 1U) &&
1689 (hpcd->Init.phy_itface != USB_OTG_ULPI_PHY))
1690 {
1691 /* Disable USB Transceiver */
1692 USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
1693 }
1694#endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
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 */
1707HAL_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 */
1724HAL_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 */
1769HAL_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 */
1800HAL_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 */
1836uint32_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 */
1848HAL_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 */
1884HAL_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 */
1927HAL_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 */
1963HAL_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 */
1986HAL_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 */
1996HAL_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 */
2025PCD_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 */
2049static 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 */
2109static 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 */
2214static 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****/
Note: See TracBrowser for help on using the repository browser.