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