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