1 /**
2 ******************************************************************************
3 * @file stm32f0xx_hal_pcd.c
4 * @author MCD Application Team
5 * @brief PCD HAL module driver.
6 * This file provides firmware functions to manage the following
7 * functionalities of the USB Peripheral Controller:
8 * + Initialization and de-initialization functions
9 * + IO operation functions
10 * + Peripheral Control functions
11 * + Peripheral State functions
12 *
13 ******************************************************************************
14 * @attention
15 *
16 * Copyright (c) 2016 STMicroelectronics.
17 * All rights reserved.
18 *
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
22 *
23 ******************************************************************************
24 @verbatim
25 ==============================================================================
26 ##### How to use this driver #####
27 ==============================================================================
28 [..]
29 The PCD HAL driver can be used as follows:
30
31 (#) Declare a PCD_HandleTypeDef handle structure, for example:
32 PCD_HandleTypeDef hpcd;
33
34 (#) Fill parameters of Init structure in HCD handle
35
36 (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
37
38 (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
39 (##) Enable the PCD/USB Low Level interface clock using
40 (+++) __HAL_RCC_USB_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 "stm32f0xx_hal.h"
58
59 /** @addtogroup STM32F0xx_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)
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 if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
1012 {
1013 /* servicing of the endpoint correct transfer interrupt */
1014 /* clear of the CTR flag into the sub */
1015 (void)PCD_EP_ISR_Handler(hpcd);
1016
1017 return;
1018 }
1019
1020 if ((wIstr & USB_ISTR_RESET) == USB_ISTR_RESET)
1021 {
1022 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
1023
1024 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1025 hpcd->ResetCallback(hpcd);
1026 #else
1027 HAL_PCD_ResetCallback(hpcd);
1028 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1029
1030 (void)HAL_PCD_SetAddress(hpcd, 0U);
1031
1032 return;
1033 }
1034
1035 if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
1036 {
1037 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
1038
1039 return;
1040 }
1041
1042 if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
1043 {
1044 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
1045
1046 return;
1047 }
1048
1049 if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
1050 {
1051 hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_LPMODE);
1052 hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
1053
1054 if (hpcd->LPM_State == LPM_L1)
1055 {
1056 hpcd->LPM_State = LPM_L0;
1057 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1058 hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
1059 #else
1060 HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
1061 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1062 }
1063
1064 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1065 hpcd->ResumeCallback(hpcd);
1066 #else
1067 HAL_PCD_ResumeCallback(hpcd);
1068 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1069
1070 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
1071
1072 return;
1073 }
1074
1075 if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
1076 {
1077 /* Force low-power mode in the macrocell */
1078 hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
1079
1080 /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
1081 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
1082
1083 hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LPMODE;
1084
1085 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1086 hpcd->SuspendCallback(hpcd);
1087 #else
1088 HAL_PCD_SuspendCallback(hpcd);
1089 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1090
1091 return;
1092 }
1093
1094 /* Handle LPM Interrupt */
1095 if ((wIstr & USB_ISTR_L1REQ) == USB_ISTR_L1REQ)
1096 {
1097 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ);
1098 if (hpcd->LPM_State == LPM_L0)
1099 {
1100 /* Force suspend and low-power mode before going to L1 state*/
1101 hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LPMODE;
1102 hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
1103
1104 hpcd->LPM_State = LPM_L1;
1105 hpcd->BESL = ((uint32_t)hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >> 2;
1106 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1107 hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
1108 #else
1109 HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
1110 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1111 }
1112 else
1113 {
1114 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1115 hpcd->SuspendCallback(hpcd);
1116 #else
1117 HAL_PCD_SuspendCallback(hpcd);
1118 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1119 }
1120
1121 return;
1122 }
1123
1124 if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
1125 {
1126 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
1127
1128 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1129 hpcd->SOFCallback(hpcd);
1130 #else
1131 HAL_PCD_SOFCallback(hpcd);
1132 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1133
1134 return;
1135 }
1136
1137 if ((wIstr & USB_ISTR_ESOF) == USB_ISTR_ESOF)
1138 {
1139 /* clear ESOF flag in ISTR */
1140 __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
1141
1142 return;
1143 }
1144 }
1145
1146
1147 /**
1148 * @brief Data OUT stage callback.
1149 * @param hpcd PCD handle
1150 * @param epnum endpoint number
1151 * @retval None
1152 */
HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1153 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1154 {
1155 /* Prevent unused argument(s) compilation warning */
1156 UNUSED(hpcd);
1157 UNUSED(epnum);
1158
1159 /* NOTE : This function should not be modified, when the callback is needed,
1160 the HAL_PCD_DataOutStageCallback could be implemented in the user file
1161 */
1162 }
1163
1164 /**
1165 * @brief Data IN stage callback
1166 * @param hpcd PCD handle
1167 * @param epnum endpoint number
1168 * @retval None
1169 */
HAL_PCD_DataInStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1170 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1171 {
1172 /* Prevent unused argument(s) compilation warning */
1173 UNUSED(hpcd);
1174 UNUSED(epnum);
1175
1176 /* NOTE : This function should not be modified, when the callback is needed,
1177 the HAL_PCD_DataInStageCallback could be implemented in the user file
1178 */
1179 }
1180 /**
1181 * @brief Setup stage callback
1182 * @param hpcd PCD handle
1183 * @retval None
1184 */
HAL_PCD_SetupStageCallback(PCD_HandleTypeDef * hpcd)1185 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
1186 {
1187 /* Prevent unused argument(s) compilation warning */
1188 UNUSED(hpcd);
1189
1190 /* NOTE : This function should not be modified, when the callback is needed,
1191 the HAL_PCD_SetupStageCallback could be implemented in the user file
1192 */
1193 }
1194
1195 /**
1196 * @brief USB Start Of Frame callback.
1197 * @param hpcd PCD handle
1198 * @retval None
1199 */
HAL_PCD_SOFCallback(PCD_HandleTypeDef * hpcd)1200 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
1201 {
1202 /* Prevent unused argument(s) compilation warning */
1203 UNUSED(hpcd);
1204
1205 /* NOTE : This function should not be modified, when the callback is needed,
1206 the HAL_PCD_SOFCallback could be implemented in the user file
1207 */
1208 }
1209
1210 /**
1211 * @brief USB Reset callback.
1212 * @param hpcd PCD handle
1213 * @retval None
1214 */
HAL_PCD_ResetCallback(PCD_HandleTypeDef * hpcd)1215 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
1216 {
1217 /* Prevent unused argument(s) compilation warning */
1218 UNUSED(hpcd);
1219
1220 /* NOTE : This function should not be modified, when the callback is needed,
1221 the HAL_PCD_ResetCallback could be implemented in the user file
1222 */
1223 }
1224
1225 /**
1226 * @brief Suspend event callback.
1227 * @param hpcd PCD handle
1228 * @retval None
1229 */
HAL_PCD_SuspendCallback(PCD_HandleTypeDef * hpcd)1230 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
1231 {
1232 /* Prevent unused argument(s) compilation warning */
1233 UNUSED(hpcd);
1234
1235 /* NOTE : This function should not be modified, when the callback is needed,
1236 the HAL_PCD_SuspendCallback could be implemented in the user file
1237 */
1238 }
1239
1240 /**
1241 * @brief Resume event callback.
1242 * @param hpcd PCD handle
1243 * @retval None
1244 */
HAL_PCD_ResumeCallback(PCD_HandleTypeDef * hpcd)1245 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
1246 {
1247 /* Prevent unused argument(s) compilation warning */
1248 UNUSED(hpcd);
1249
1250 /* NOTE : This function should not be modified, when the callback is needed,
1251 the HAL_PCD_ResumeCallback could be implemented in the user file
1252 */
1253 }
1254
1255 /**
1256 * @brief Incomplete ISO OUT callback.
1257 * @param hpcd PCD handle
1258 * @param epnum endpoint number
1259 * @retval None
1260 */
HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1261 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1262 {
1263 /* Prevent unused argument(s) compilation warning */
1264 UNUSED(hpcd);
1265 UNUSED(epnum);
1266
1267 /* NOTE : This function should not be modified, when the callback is needed,
1268 the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
1269 */
1270 }
1271
1272 /**
1273 * @brief Incomplete ISO IN callback.
1274 * @param hpcd PCD handle
1275 * @param epnum endpoint number
1276 * @retval None
1277 */
HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1278 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1279 {
1280 /* Prevent unused argument(s) compilation warning */
1281 UNUSED(hpcd);
1282 UNUSED(epnum);
1283
1284 /* NOTE : This function should not be modified, when the callback is needed,
1285 the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1286 */
1287 }
1288
1289 /**
1290 * @brief Connection event callback.
1291 * @param hpcd PCD handle
1292 * @retval None
1293 */
HAL_PCD_ConnectCallback(PCD_HandleTypeDef * hpcd)1294 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
1295 {
1296 /* Prevent unused argument(s) compilation warning */
1297 UNUSED(hpcd);
1298
1299 /* NOTE : This function should not be modified, when the callback is needed,
1300 the HAL_PCD_ConnectCallback could be implemented in the user file
1301 */
1302 }
1303
1304 /**
1305 * @brief Disconnection event callback.
1306 * @param hpcd PCD handle
1307 * @retval None
1308 */
HAL_PCD_DisconnectCallback(PCD_HandleTypeDef * hpcd)1309 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
1310 {
1311 /* Prevent unused argument(s) compilation warning */
1312 UNUSED(hpcd);
1313
1314 /* NOTE : This function should not be modified, when the callback is needed,
1315 the HAL_PCD_DisconnectCallback could be implemented in the user file
1316 */
1317 }
1318
1319 /**
1320 * @}
1321 */
1322
1323 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
1324 * @brief management functions
1325 *
1326 @verbatim
1327 ===============================================================================
1328 ##### Peripheral Control functions #####
1329 ===============================================================================
1330 [..]
1331 This subsection provides a set of functions allowing to control the PCD data
1332 transfers.
1333
1334 @endverbatim
1335 * @{
1336 */
1337
1338 /**
1339 * @brief Connect the USB device
1340 * @param hpcd PCD handle
1341 * @retval HAL status
1342 */
HAL_PCD_DevConnect(PCD_HandleTypeDef * hpcd)1343 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
1344 {
1345 __HAL_LOCK(hpcd);
1346 (void)USB_DevConnect(hpcd->Instance);
1347 __HAL_UNLOCK(hpcd);
1348
1349 return HAL_OK;
1350 }
1351
1352 /**
1353 * @brief Disconnect the USB device.
1354 * @param hpcd PCD handle
1355 * @retval HAL status
1356 */
HAL_PCD_DevDisconnect(PCD_HandleTypeDef * hpcd)1357 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
1358 {
1359 __HAL_LOCK(hpcd);
1360 (void)USB_DevDisconnect(hpcd->Instance);
1361 __HAL_UNLOCK(hpcd);
1362
1363 return HAL_OK;
1364 }
1365
1366 /**
1367 * @brief Set the USB Device address.
1368 * @param hpcd PCD handle
1369 * @param address new device address
1370 * @retval HAL status
1371 */
HAL_PCD_SetAddress(PCD_HandleTypeDef * hpcd,uint8_t address)1372 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
1373 {
1374 __HAL_LOCK(hpcd);
1375 hpcd->USB_Address = address;
1376 (void)USB_SetDevAddress(hpcd->Instance, address);
1377 __HAL_UNLOCK(hpcd);
1378
1379 return HAL_OK;
1380 }
1381 /**
1382 * @brief Open and configure an endpoint.
1383 * @param hpcd PCD handle
1384 * @param ep_addr endpoint address
1385 * @param ep_mps endpoint max packet size
1386 * @param ep_type endpoint type
1387 * @retval HAL status
1388 */
HAL_PCD_EP_Open(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint16_t ep_mps,uint8_t ep_type)1389 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
1390 uint16_t ep_mps, uint8_t ep_type)
1391 {
1392 HAL_StatusTypeDef ret = HAL_OK;
1393 PCD_EPTypeDef *ep;
1394
1395 if ((ep_addr & 0x80U) == 0x80U)
1396 {
1397 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1398 ep->is_in = 1U;
1399 }
1400 else
1401 {
1402 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1403 ep->is_in = 0U;
1404 }
1405
1406 ep->num = ep_addr & EP_ADDR_MSK;
1407 ep->maxpacket = ep_mps;
1408 ep->type = ep_type;
1409
1410 /* Set initial data PID. */
1411 if (ep_type == EP_TYPE_BULK)
1412 {
1413 ep->data_pid_start = 0U;
1414 }
1415
1416 __HAL_LOCK(hpcd);
1417 (void)USB_ActivateEndpoint(hpcd->Instance, ep);
1418 __HAL_UNLOCK(hpcd);
1419
1420 return ret;
1421 }
1422
1423 /**
1424 * @brief Deactivate an endpoint.
1425 * @param hpcd PCD handle
1426 * @param ep_addr endpoint address
1427 * @retval HAL status
1428 */
HAL_PCD_EP_Close(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1429 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1430 {
1431 PCD_EPTypeDef *ep;
1432
1433 if ((ep_addr & 0x80U) == 0x80U)
1434 {
1435 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1436 ep->is_in = 1U;
1437 }
1438 else
1439 {
1440 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1441 ep->is_in = 0U;
1442 }
1443 ep->num = ep_addr & EP_ADDR_MSK;
1444
1445 __HAL_LOCK(hpcd);
1446 (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
1447 __HAL_UNLOCK(hpcd);
1448 return HAL_OK;
1449 }
1450
1451
1452 /**
1453 * @brief Receive an amount of data.
1454 * @param hpcd PCD handle
1455 * @param ep_addr endpoint address
1456 * @param pBuf pointer to the reception buffer
1457 * @param len amount of data to be received
1458 * @retval HAL status
1459 */
HAL_PCD_EP_Receive(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)1460 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1461 {
1462 PCD_EPTypeDef *ep;
1463
1464 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1465
1466 /*setup and start the Xfer */
1467 ep->xfer_buff = pBuf;
1468 ep->xfer_len = len;
1469 ep->xfer_count = 0U;
1470 ep->is_in = 0U;
1471 ep->num = ep_addr & EP_ADDR_MSK;
1472
1473 (void)USB_EPStartXfer(hpcd->Instance, ep);
1474
1475 return HAL_OK;
1476 }
1477
1478 /**
1479 * @brief Get Received Data Size
1480 * @param hpcd PCD handle
1481 * @param ep_addr endpoint address
1482 * @retval Data Size
1483 */
HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1484 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1485 {
1486 return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
1487 }
1488 /**
1489 * @brief Send an amount of data
1490 * @param hpcd PCD handle
1491 * @param ep_addr endpoint address
1492 * @param pBuf pointer to the transmission buffer
1493 * @param len amount of data to be sent
1494 * @retval HAL status
1495 */
HAL_PCD_EP_Transmit(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)1496 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
1497 {
1498 PCD_EPTypeDef *ep;
1499
1500 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1501
1502 /*setup and start the Xfer */
1503 ep->xfer_buff = pBuf;
1504 ep->xfer_len = len;
1505 ep->xfer_fill_db = 1U;
1506 ep->xfer_len_db = len;
1507 ep->xfer_count = 0U;
1508 ep->is_in = 1U;
1509 ep->num = ep_addr & EP_ADDR_MSK;
1510
1511 (void)USB_EPStartXfer(hpcd->Instance, ep);
1512
1513 return HAL_OK;
1514 }
1515
1516 /**
1517 * @brief Set a STALL condition over an endpoint
1518 * @param hpcd PCD handle
1519 * @param ep_addr endpoint address
1520 * @retval HAL status
1521 */
HAL_PCD_EP_SetStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1522 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1523 {
1524 PCD_EPTypeDef *ep;
1525
1526 if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
1527 {
1528 return HAL_ERROR;
1529 }
1530
1531 if ((0x80U & ep_addr) == 0x80U)
1532 {
1533 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1534 ep->is_in = 1U;
1535 }
1536 else
1537 {
1538 ep = &hpcd->OUT_ep[ep_addr];
1539 ep->is_in = 0U;
1540 }
1541
1542 ep->is_stall = 1U;
1543 ep->num = ep_addr & EP_ADDR_MSK;
1544
1545 __HAL_LOCK(hpcd);
1546
1547 (void)USB_EPSetStall(hpcd->Instance, ep);
1548
1549 __HAL_UNLOCK(hpcd);
1550
1551 return HAL_OK;
1552 }
1553
1554 /**
1555 * @brief Clear a STALL condition over in an endpoint
1556 * @param hpcd PCD handle
1557 * @param ep_addr endpoint address
1558 * @retval HAL status
1559 */
HAL_PCD_EP_ClrStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1560 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1561 {
1562 PCD_EPTypeDef *ep;
1563
1564 if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
1565 {
1566 return HAL_ERROR;
1567 }
1568
1569 if ((0x80U & ep_addr) == 0x80U)
1570 {
1571 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1572 ep->is_in = 1U;
1573 }
1574 else
1575 {
1576 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1577 ep->is_in = 0U;
1578 }
1579
1580 ep->is_stall = 0U;
1581 ep->num = ep_addr & EP_ADDR_MSK;
1582
1583 __HAL_LOCK(hpcd);
1584 (void)USB_EPClearStall(hpcd->Instance, ep);
1585 __HAL_UNLOCK(hpcd);
1586
1587 return HAL_OK;
1588 }
1589
1590 /**
1591 * @brief Abort an USB EP transaction.
1592 * @param hpcd PCD handle
1593 * @param ep_addr endpoint address
1594 * @retval HAL status
1595 */
HAL_PCD_EP_Abort(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1596 HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1597 {
1598 HAL_StatusTypeDef ret;
1599 PCD_EPTypeDef *ep;
1600
1601 if ((0x80U & ep_addr) == 0x80U)
1602 {
1603 ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1604 }
1605 else
1606 {
1607 ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1608 }
1609
1610 /* Stop Xfer */
1611 ret = USB_EPStopXfer(hpcd->Instance, ep);
1612
1613 return ret;
1614 }
1615
1616 /**
1617 * @brief Flush an endpoint
1618 * @param hpcd PCD handle
1619 * @param ep_addr endpoint address
1620 * @retval HAL status
1621 */
HAL_PCD_EP_Flush(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1622 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1623 {
1624 /* Prevent unused argument(s) compilation warning */
1625 UNUSED(hpcd);
1626 UNUSED(ep_addr);
1627
1628 return HAL_OK;
1629 }
1630
1631 /**
1632 * @brief Activate remote wakeup signalling
1633 * @param hpcd PCD handle
1634 * @retval HAL status
1635 */
HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1636 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1637 {
1638 return (USB_ActivateRemoteWakeup(hpcd->Instance));
1639 }
1640
1641 /**
1642 * @brief De-activate remote wakeup signalling.
1643 * @param hpcd PCD handle
1644 * @retval HAL status
1645 */
HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)1646 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
1647 {
1648 return (USB_DeActivateRemoteWakeup(hpcd->Instance));
1649 }
1650
1651 /**
1652 * @}
1653 */
1654
1655 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1656 * @brief Peripheral State functions
1657 *
1658 @verbatim
1659 ===============================================================================
1660 ##### Peripheral State functions #####
1661 ===============================================================================
1662 [..]
1663 This subsection permits to get in run-time the status of the peripheral
1664 and the data flow.
1665
1666 @endverbatim
1667 * @{
1668 */
1669
1670 /**
1671 * @brief Return the PCD handle state.
1672 * @param hpcd PCD handle
1673 * @retval HAL state
1674 */
HAL_PCD_GetState(PCD_HandleTypeDef * hpcd)1675 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef *hpcd)
1676 {
1677 return hpcd->State;
1678 }
1679
1680 /**
1681 * @}
1682 */
1683
1684 /**
1685 * @}
1686 */
1687
1688 /* Private functions ---------------------------------------------------------*/
1689 /** @addtogroup PCD_Private_Functions
1690 * @{
1691 */
1692
1693
1694 /**
1695 * @brief This function handles PCD Endpoint interrupt request.
1696 * @param hpcd PCD handle
1697 * @retval HAL status
1698 */
PCD_EP_ISR_Handler(PCD_HandleTypeDef * hpcd)1699 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
1700 {
1701 PCD_EPTypeDef *ep;
1702 uint16_t count;
1703 uint16_t wIstr;
1704 uint16_t wEPVal;
1705 uint16_t TxPctSize;
1706 uint8_t epindex;
1707
1708 #if (USE_USB_DOUBLE_BUFFER != 1U)
1709 count = 0U;
1710 #endif /* USE_USB_DOUBLE_BUFFER */
1711
1712 /* stay in loop while pending interrupts */
1713 while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
1714 {
1715 wIstr = hpcd->Instance->ISTR;
1716
1717 /* extract highest priority endpoint number */
1718 epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
1719
1720 if (epindex == 0U)
1721 {
1722 /* Decode and service control endpoint interrupt */
1723
1724 /* DIR bit = origin of the interrupt */
1725 if ((wIstr & USB_ISTR_DIR) == 0U)
1726 {
1727 /* DIR = 0 */
1728
1729 /* DIR = 0 => IN int */
1730 /* DIR = 0 implies that (EP_CTR_TX = 1) always */
1731 PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1732 ep = &hpcd->IN_ep[0];
1733
1734 ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1735 ep->xfer_buff += ep->xfer_count;
1736
1737 /* TX COMPLETE */
1738 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1739 hpcd->DataInStageCallback(hpcd, 0U);
1740 #else
1741 HAL_PCD_DataInStageCallback(hpcd, 0U);
1742 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1743
1744 if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
1745 {
1746 hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
1747 hpcd->USB_Address = 0U;
1748 }
1749 }
1750 else
1751 {
1752 /* DIR = 1 */
1753
1754 /* DIR = 1 & CTR_RX => SETUP or OUT int */
1755 /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
1756 ep = &hpcd->OUT_ep[0];
1757 wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1758
1759 if ((wEPVal & USB_EP_SETUP) != 0U)
1760 {
1761 /* Get SETUP Packet */
1762 ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1763
1764 USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
1765 ep->pmaadress, (uint16_t)ep->xfer_count);
1766
1767 /* SETUP bit kept frozen while CTR_RX = 1 */
1768 PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1769
1770 /* Process SETUP Packet*/
1771 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1772 hpcd->SetupStageCallback(hpcd);
1773 #else
1774 HAL_PCD_SetupStageCallback(hpcd);
1775 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1776 }
1777 else if ((wEPVal & USB_EP_CTR_RX) != 0U)
1778 {
1779 PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
1780
1781 /* Get Control Data OUT Packet */
1782 ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1783
1784 if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
1785 {
1786 USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
1787 ep->pmaadress, (uint16_t)ep->xfer_count);
1788
1789 ep->xfer_buff += ep->xfer_count;
1790
1791 /* Process Control Data OUT Packet */
1792 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1793 hpcd->DataOutStageCallback(hpcd, 0U);
1794 #else
1795 HAL_PCD_DataOutStageCallback(hpcd, 0U);
1796 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1797 }
1798
1799 wEPVal = (uint16_t)PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
1800
1801 if (((wEPVal & USB_EP_SETUP) == 0U) && ((wEPVal & USB_EP_RX_STRX) != USB_EP_RX_VALID))
1802 {
1803 PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
1804 PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
1805 }
1806 }
1807 }
1808 }
1809 else
1810 {
1811 /* Decode and service non control endpoints interrupt */
1812 /* process related endpoint register */
1813 wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
1814
1815 if ((wEPVal & USB_EP_CTR_RX) != 0U)
1816 {
1817 /* clear int flag */
1818 PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
1819 ep = &hpcd->OUT_ep[epindex];
1820
1821 /* OUT Single Buffering */
1822 if (ep->doublebuffer == 0U)
1823 {
1824 count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
1825
1826 if (count != 0U)
1827 {
1828 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
1829 }
1830 }
1831 #if (USE_USB_DOUBLE_BUFFER == 1U)
1832 else
1833 {
1834 /* manage double buffer bulk out */
1835 if (ep->type == EP_TYPE_BULK)
1836 {
1837 count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
1838 }
1839 else /* manage double buffer iso out */
1840 {
1841 /* free EP OUT Buffer */
1842 PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
1843
1844 if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
1845 {
1846 /* read from endpoint BUF0Addr buffer */
1847 count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1848
1849 if (count != 0U)
1850 {
1851 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
1852 }
1853 }
1854 else
1855 {
1856 /* read from endpoint BUF1Addr buffer */
1857 count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
1858
1859 if (count != 0U)
1860 {
1861 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
1862 }
1863 }
1864 }
1865 }
1866 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1867
1868 /* multi-packet on the NON control OUT endpoint */
1869 ep->xfer_count += count;
1870 ep->xfer_buff += count;
1871
1872 if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
1873 {
1874 /* RX COMPLETE */
1875 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1876 hpcd->DataOutStageCallback(hpcd, ep->num);
1877 #else
1878 HAL_PCD_DataOutStageCallback(hpcd, ep->num);
1879 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1880 }
1881 else
1882 {
1883 (void)USB_EPStartXfer(hpcd->Instance, ep);
1884 }
1885 }
1886
1887 if ((wEPVal & USB_EP_CTR_TX) != 0U)
1888 {
1889 ep = &hpcd->IN_ep[epindex];
1890
1891 /* clear int flag */
1892 PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
1893
1894 if (ep->type == EP_TYPE_ISOC)
1895 {
1896 ep->xfer_len = 0U;
1897
1898 #if (USE_USB_DOUBLE_BUFFER == 1U)
1899 if (ep->doublebuffer != 0U)
1900 {
1901 if ((wEPVal & USB_EP_DTOG_TX) != 0U)
1902 {
1903 PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
1904 }
1905 else
1906 {
1907 PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
1908 }
1909 }
1910 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1911
1912 /* TX COMPLETE */
1913 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1914 hpcd->DataInStageCallback(hpcd, ep->num);
1915 #else
1916 HAL_PCD_DataInStageCallback(hpcd, ep->num);
1917 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1918 }
1919 else
1920 {
1921 /* Manage Single Buffer Transaction */
1922 if ((wEPVal & USB_EP_KIND) == 0U)
1923 {
1924 /* multi-packet on the NON control IN endpoint */
1925 TxPctSize = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
1926
1927 if (ep->xfer_len > TxPctSize)
1928 {
1929 ep->xfer_len -= TxPctSize;
1930 }
1931 else
1932 {
1933 ep->xfer_len = 0U;
1934 }
1935
1936 /* Zero Length Packet? */
1937 if (ep->xfer_len == 0U)
1938 {
1939 /* TX COMPLETE */
1940 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1941 hpcd->DataInStageCallback(hpcd, ep->num);
1942 #else
1943 HAL_PCD_DataInStageCallback(hpcd, ep->num);
1944 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1945 }
1946 else
1947 {
1948 /* Transfer is not yet Done */
1949 ep->xfer_buff += TxPctSize;
1950 ep->xfer_count += TxPctSize;
1951 (void)USB_EPStartXfer(hpcd->Instance, ep);
1952 }
1953 }
1954 #if (USE_USB_DOUBLE_BUFFER == 1U)
1955 /* Double Buffer bulk IN (bulk transfer Len > Ep_Mps) */
1956 else
1957 {
1958 (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
1959 }
1960 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
1961 }
1962 }
1963 }
1964 }
1965
1966 return HAL_OK;
1967 }
1968
1969
1970 #if (USE_USB_DOUBLE_BUFFER == 1U)
1971 /**
1972 * @brief Manage double buffer bulk out transaction from ISR
1973 * @param hpcd PCD handle
1974 * @param ep current endpoint handle
1975 * @param wEPVal Last snapshot of EPRx register value taken in ISR
1976 * @retval HAL status
1977 */
HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)1978 static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
1979 PCD_EPTypeDef *ep, uint16_t wEPVal)
1980 {
1981 uint16_t count;
1982
1983 /* Manage Buffer0 OUT */
1984 if ((wEPVal & USB_EP_DTOG_RX) != 0U)
1985 {
1986 /* Get count of received Data on buffer0 */
1987 count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
1988
1989 if (ep->xfer_len >= count)
1990 {
1991 ep->xfer_len -= count;
1992 }
1993 else
1994 {
1995 ep->xfer_len = 0U;
1996 }
1997
1998 if (ep->xfer_len == 0U)
1999 {
2000 /* set NAK to OUT endpoint since double buffer is enabled */
2001 PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2002 }
2003
2004 /* Check if Buffer1 is in blocked state which requires to toggle */
2005 if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2006 {
2007 PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2008 }
2009
2010 if (count != 0U)
2011 {
2012 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2013 }
2014 }
2015 /* Manage Buffer 1 DTOG_RX=0 */
2016 else
2017 {
2018 /* Get count of received data */
2019 count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2020
2021 if (ep->xfer_len >= count)
2022 {
2023 ep->xfer_len -= count;
2024 }
2025 else
2026 {
2027 ep->xfer_len = 0U;
2028 }
2029
2030 if (ep->xfer_len == 0U)
2031 {
2032 /* set NAK on the current endpoint */
2033 PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2034 }
2035
2036 /*Need to FreeUser Buffer*/
2037 if ((wEPVal & USB_EP_DTOG_TX) == 0U)
2038 {
2039 PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2040 }
2041
2042 if (count != 0U)
2043 {
2044 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2045 }
2046 }
2047
2048 return count;
2049 }
2050
2051
2052 /**
2053 * @brief Manage double buffer bulk IN transaction from ISR
2054 * @param hpcd PCD handle
2055 * @param ep current endpoint handle
2056 * @param wEPVal Last snapshot of EPRx register value taken in ISR
2057 * @retval HAL status
2058 */
HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)2059 static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
2060 PCD_EPTypeDef *ep, uint16_t wEPVal)
2061 {
2062 uint32_t len;
2063 uint16_t TxPctSize;
2064
2065 /* Data Buffer0 ACK received */
2066 if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2067 {
2068 /* multi-packet on the NON control IN endpoint */
2069 TxPctSize = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2070
2071 if (ep->xfer_len > TxPctSize)
2072 {
2073 ep->xfer_len -= TxPctSize;
2074 }
2075 else
2076 {
2077 ep->xfer_len = 0U;
2078 }
2079
2080 /* Transfer is completed */
2081 if (ep->xfer_len == 0U)
2082 {
2083 PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2084 PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2085
2086 /* TX COMPLETE */
2087 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2088 hpcd->DataInStageCallback(hpcd, ep->num);
2089 #else
2090 HAL_PCD_DataInStageCallback(hpcd, ep->num);
2091 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2092
2093 if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2094 {
2095 PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2096 }
2097 }
2098 else /* Transfer is not yet Done */
2099 {
2100 /* need to Free USB Buff */
2101 if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2102 {
2103 PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2104 }
2105
2106 /* Still there is data to Fill in the next Buffer */
2107 if (ep->xfer_fill_db == 1U)
2108 {
2109 ep->xfer_buff += TxPctSize;
2110 ep->xfer_count += TxPctSize;
2111
2112 /* Calculate the len of the new buffer to fill */
2113 if (ep->xfer_len_db >= ep->maxpacket)
2114 {
2115 len = ep->maxpacket;
2116 ep->xfer_len_db -= len;
2117 }
2118 else if (ep->xfer_len_db == 0U)
2119 {
2120 len = TxPctSize;
2121 ep->xfer_fill_db = 0U;
2122 }
2123 else
2124 {
2125 ep->xfer_fill_db = 0U;
2126 len = ep->xfer_len_db;
2127 ep->xfer_len_db = 0U;
2128 }
2129
2130 /* Write remaining Data to Buffer */
2131 /* Set the Double buffer counter for pma buffer1 */
2132 PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2133
2134 /* Copy user buffer to USB PMA */
2135 USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, (uint16_t)len);
2136 }
2137 }
2138 }
2139 else /* Data Buffer1 ACK received */
2140 {
2141 /* multi-packet on the NON control IN endpoint */
2142 TxPctSize = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2143
2144 if (ep->xfer_len >= TxPctSize)
2145 {
2146 ep->xfer_len -= TxPctSize;
2147 }
2148 else
2149 {
2150 ep->xfer_len = 0U;
2151 }
2152
2153 /* Transfer is completed */
2154 if (ep->xfer_len == 0U)
2155 {
2156 PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2157 PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2158
2159 /* TX COMPLETE */
2160 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2161 hpcd->DataInStageCallback(hpcd, ep->num);
2162 #else
2163 HAL_PCD_DataInStageCallback(hpcd, ep->num);
2164 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2165
2166 /* need to Free USB Buff */
2167 if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2168 {
2169 PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2170 }
2171 }
2172 else /* Transfer is not yet Done */
2173 {
2174 /* need to Free USB Buff */
2175 if ((wEPVal & USB_EP_DTOG_RX) == 0U)
2176 {
2177 PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2178 }
2179
2180 /* Still there is data to Fill in the next Buffer */
2181 if (ep->xfer_fill_db == 1U)
2182 {
2183 ep->xfer_buff += TxPctSize;
2184 ep->xfer_count += TxPctSize;
2185
2186 /* Calculate the len of the new buffer to fill */
2187 if (ep->xfer_len_db >= ep->maxpacket)
2188 {
2189 len = ep->maxpacket;
2190 ep->xfer_len_db -= len;
2191 }
2192 else if (ep->xfer_len_db == 0U)
2193 {
2194 len = TxPctSize;
2195 ep->xfer_fill_db = 0U;
2196 }
2197 else
2198 {
2199 len = ep->xfer_len_db;
2200 ep->xfer_len_db = 0U;
2201 ep->xfer_fill_db = 0;
2202 }
2203
2204 /* Set the Double buffer counter for pmabuffer1 */
2205 PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2206
2207 /* Copy the user buffer to USB PMA */
2208 USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, (uint16_t)len);
2209 }
2210 }
2211 }
2212
2213 /*enable endpoint IN*/
2214 PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
2215
2216 return HAL_OK;
2217 }
2218 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2219
2220
2221
2222 /**
2223 * @}
2224 */
2225 #endif /* defined (USB) */
2226 #endif /* HAL_PCD_MODULE_ENABLED */
2227
2228 /**
2229 * @}
2230 */
2231
2232 /**
2233 * @}
2234 */
2235