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