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