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