1 /**
2   ******************************************************************************
3   * @file    stm32h5xx_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) 2023 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               (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
42               (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
43 
44          (##) Initialize the related GPIO clocks
45          (##) Configure PCD pin-out
46          (##) Configure PCD NVIC interrupt
47 
48      (#)Associate the Upper USB device stack to the HAL PCD Driver:
49          (##) hpcd.pData = pdev;
50 
51      (#)Enable PCD transmission and reception:
52          (##) HAL_PCD_Start();
53 
54   @endverbatim
55   ******************************************************************************
56   */
57 
58 /* Includes ------------------------------------------------------------------*/
59 #include "stm32h5xx_hal.h"
60 
61 /** @addtogroup STM32H5xx_HAL_Driver
62   * @{
63   */
64 
65 /** @defgroup PCD PCD
66   * @brief PCD HAL module driver
67   * @{
68   */
69 
70 #ifdef HAL_PCD_MODULE_ENABLED
71 
72 #if defined (USB_OTG_FS) || defined (USB_OTG_HS) || defined (USB_DRD_FS)
73 
74 /* Private types -------------------------------------------------------------*/
75 /* Private variables ---------------------------------------------------------*/
76 /* Private constants ---------------------------------------------------------*/
77 /* Private macros ------------------------------------------------------------*/
78 /** @defgroup PCD_Private_Macros PCD Private Macros
79   * @{
80   */
81 #define PCD_MIN(a, b)  (((a) < (b)) ? (a) : (b))
82 #define PCD_MAX(a, b)  (((a) > (b)) ? (a) : (b))
83 /**
84   * @}
85   */
86 
87 /* Private functions prototypes ----------------------------------------------*/
88 /** @defgroup PCD_Private_Functions PCD Private Functions
89   * @{
90   */
91 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
92 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
93 static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
94 static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
95 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
96 
97 #if defined (USB_DRD_FS)
98 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
99 #if (USE_USB_DOUBLE_BUFFER == 1U)
100 static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
101 static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
102 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
103 #endif /* defined (USB_DRD_FS) */
104 /**
105   * @}
106   */
107 
108 /* Exported functions --------------------------------------------------------*/
109 /** @defgroup PCD_Exported_Functions PCD Exported Functions
110   * @{
111   */
112 
113 /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
114   *  @brief    Initialization and Configuration functions
115   *
116 @verbatim
117  ===============================================================================
118             ##### Initialization and de-initialization functions #####
119  ===============================================================================
120     [..]  This section provides functions allowing to:
121 
122 @endverbatim
123   * @{
124   */
125 
126 /**
127   * @brief  Initializes the PCD according to the specified
128   *         parameters in the PCD_InitTypeDef and initialize the associated handle.
129   * @param  hpcd PCD handle
130   * @retval HAL status
131   */
HAL_PCD_Init(PCD_HandleTypeDef * hpcd)132 HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
133 {
134 #if defined (USB_OTG_FS)
135   const USB_OTG_GlobalTypeDef *USBx;
136 #endif /* defined (USB_OTG_FS) */
137   uint8_t i;
138 
139   /* Check the PCD handle allocation */
140   if (hpcd == NULL)
141   {
142     return HAL_ERROR;
143   }
144 
145   /* Check the parameters */
146   assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
147 
148 #if defined (USB_OTG_FS)
149   USBx = hpcd->Instance;
150 #endif /* defined (USB_OTG_FS) */
151 
152   if (hpcd->State == HAL_PCD_STATE_RESET)
153   {
154     /* Allocate lock resource and initialize it */
155     hpcd->Lock = HAL_UNLOCKED;
156 
157 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
158     hpcd->SOFCallback = HAL_PCD_SOFCallback;
159     hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
160     hpcd->ResetCallback = HAL_PCD_ResetCallback;
161     hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
162     hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
163     hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
164     hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
165     hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
166     hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
167     hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
168     hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
169     hpcd->LPMCallback = HAL_PCDEx_LPM_Callback;
170     hpcd->BCDCallback = HAL_PCDEx_BCD_Callback;
171 
172     if (hpcd->MspInitCallback == NULL)
173     {
174       hpcd->MspInitCallback = HAL_PCD_MspInit;
175     }
176 
177     /* Init the low level hardware */
178     hpcd->MspInitCallback(hpcd);
179 #else
180     /* Init the low level hardware : GPIO, CLOCK, NVIC... */
181     HAL_PCD_MspInit(hpcd);
182 #endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
183   }
184 
185   hpcd->State = HAL_PCD_STATE_BUSY;
186 
187 #if defined (USB_OTG_FS)
188   /* Disable DMA mode for FS instance */
189   if (USBx == USB_OTG_FS)
190   {
191     hpcd->Init.dma_enable = 0U;
192   }
193 #endif /* defined (USB_OTG_FS) */
194 
195   /* Disable the Interrupts */
196   __HAL_PCD_DISABLE(hpcd);
197 
198   /*Init the Core (common init.) */
199   if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
200   {
201     hpcd->State = HAL_PCD_STATE_ERROR;
202     return HAL_ERROR;
203   }
204 
205   /* Force Device Mode */
206   if (USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE) != HAL_OK)
207   {
208     hpcd->State = HAL_PCD_STATE_ERROR;
209     return HAL_ERROR;
210   }
211 
212   /* Init endpoints structures */
213   for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
214   {
215     /* Init ep structure */
216     hpcd->IN_ep[i].is_in = 1U;
217     hpcd->IN_ep[i].num = i;
218 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
219     hpcd->IN_ep[i].tx_fifo_num = i;
220 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
221     /* Control until ep is activated */
222     hpcd->IN_ep[i].type = EP_TYPE_CTRL;
223     hpcd->IN_ep[i].maxpacket = 0U;
224     hpcd->IN_ep[i].xfer_buff = 0U;
225     hpcd->IN_ep[i].xfer_len = 0U;
226   }
227 
228   for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
229   {
230     hpcd->OUT_ep[i].is_in = 0U;
231     hpcd->OUT_ep[i].num = i;
232     /* Control until ep is activated */
233     hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
234     hpcd->OUT_ep[i].maxpacket = 0U;
235     hpcd->OUT_ep[i].xfer_buff = 0U;
236     hpcd->OUT_ep[i].xfer_len = 0U;
237   }
238 
239   /* Init Device */
240   if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
241   {
242     hpcd->State = HAL_PCD_STATE_ERROR;
243     return HAL_ERROR;
244   }
245 
246   hpcd->USB_Address = 0U;
247   hpcd->State = HAL_PCD_STATE_READY;
248 
249   /* Activate LPM */
250   if (hpcd->Init.lpm_enable == 1U)
251   {
252     (void)HAL_PCDEx_ActivateLPM(hpcd);
253   }
254 
255   (void)USB_DevDisconnect(hpcd->Instance);
256 
257   return HAL_OK;
258 }
259 
260 /**
261   * @brief  DeInitializes the PCD peripheral.
262   * @param  hpcd PCD handle
263   * @retval HAL status
264   */
HAL_PCD_DeInit(PCD_HandleTypeDef * hpcd)265 HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
266 {
267   /* Check the PCD handle allocation */
268   if (hpcd == NULL)
269   {
270     return HAL_ERROR;
271   }
272 
273   hpcd->State = HAL_PCD_STATE_BUSY;
274 
275   /* Stop Device */
276   if (USB_StopDevice(hpcd->Instance) != HAL_OK)
277   {
278     return HAL_ERROR;
279   }
280 
281 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
282   if (hpcd->MspDeInitCallback == NULL)
283   {
284     hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit  */
285   }
286 
287   /* DeInit the low level hardware */
288   hpcd->MspDeInitCallback(hpcd);
289 #else
290   /* DeInit the low level hardware: CLOCK, NVIC.*/
291   HAL_PCD_MspDeInit(hpcd);
292 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
293 
294   hpcd->State = HAL_PCD_STATE_RESET;
295 
296   return HAL_OK;
297 }
298 
299 /**
300   * @brief  Initializes the PCD MSP.
301   * @param  hpcd PCD handle
302   * @retval None
303   */
HAL_PCD_MspInit(PCD_HandleTypeDef * hpcd)304 __weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
305 {
306   /* Prevent unused argument(s) compilation warning */
307   UNUSED(hpcd);
308 
309   /* NOTE : This function should not be modified, when the callback is needed,
310             the HAL_PCD_MspInit could be implemented in the user file
311    */
312 }
313 
314 /**
315   * @brief  DeInitializes PCD MSP.
316   * @param  hpcd PCD handle
317   * @retval None
318   */
HAL_PCD_MspDeInit(PCD_HandleTypeDef * hpcd)319 __weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
320 {
321   /* Prevent unused argument(s) compilation warning */
322   UNUSED(hpcd);
323 
324   /* NOTE : This function should not be modified, when the callback is needed,
325             the HAL_PCD_MspDeInit could be implemented in the user file
326    */
327 }
328 
329 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
330 /**
331   * @brief  Register a User USB PCD Callback
332   *         To be used instead of the weak predefined callback
333   * @param  hpcd USB PCD handle
334   * @param  CallbackID ID of the callback to be registered
335   *         This parameter can be one of the following values:
336   *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
337   *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
338   *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
339   *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
340   *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
341   *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
342   *          @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
343   *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
344   *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
345   * @param  pCallback pointer to the Callback function
346   * @retval HAL status
347   */
HAL_PCD_RegisterCallback(PCD_HandleTypeDef * hpcd,HAL_PCD_CallbackIDTypeDef CallbackID,pPCD_CallbackTypeDef pCallback)348 HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
349                                            HAL_PCD_CallbackIDTypeDef CallbackID,
350                                            pPCD_CallbackTypeDef pCallback)
351 {
352   HAL_StatusTypeDef status = HAL_OK;
353 
354   if (pCallback == NULL)
355   {
356     /* Update the error code */
357     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
358     return HAL_ERROR;
359   }
360   /* Process locked */
361   __HAL_LOCK(hpcd);
362 
363   if (hpcd->State == HAL_PCD_STATE_READY)
364   {
365     switch (CallbackID)
366     {
367       case HAL_PCD_SOF_CB_ID :
368         hpcd->SOFCallback = pCallback;
369         break;
370 
371       case HAL_PCD_SETUPSTAGE_CB_ID :
372         hpcd->SetupStageCallback = pCallback;
373         break;
374 
375       case HAL_PCD_RESET_CB_ID :
376         hpcd->ResetCallback = pCallback;
377         break;
378 
379       case HAL_PCD_SUSPEND_CB_ID :
380         hpcd->SuspendCallback = pCallback;
381         break;
382 
383       case HAL_PCD_RESUME_CB_ID :
384         hpcd->ResumeCallback = pCallback;
385         break;
386 
387       case HAL_PCD_CONNECT_CB_ID :
388         hpcd->ConnectCallback = pCallback;
389         break;
390 
391       case HAL_PCD_DISCONNECT_CB_ID :
392         hpcd->DisconnectCallback = pCallback;
393         break;
394 
395       case HAL_PCD_MSPINIT_CB_ID :
396         hpcd->MspInitCallback = pCallback;
397         break;
398 
399       case HAL_PCD_MSPDEINIT_CB_ID :
400         hpcd->MspDeInitCallback = pCallback;
401         break;
402 
403       default :
404         /* Update the error code */
405         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
406         /* Return error status */
407         status =  HAL_ERROR;
408         break;
409     }
410   }
411   else if (hpcd->State == HAL_PCD_STATE_RESET)
412   {
413     switch (CallbackID)
414     {
415       case HAL_PCD_MSPINIT_CB_ID :
416         hpcd->MspInitCallback = pCallback;
417         break;
418 
419       case HAL_PCD_MSPDEINIT_CB_ID :
420         hpcd->MspDeInitCallback = pCallback;
421         break;
422 
423       default :
424         /* Update the error code */
425         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
426         /* Return error status */
427         status =  HAL_ERROR;
428         break;
429     }
430   }
431   else
432   {
433     /* Update the error code */
434     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
435     /* Return error status */
436     status =  HAL_ERROR;
437   }
438 
439   /* Release Lock */
440   __HAL_UNLOCK(hpcd);
441   return status;
442 }
443 
444 /**
445   * @brief  Unregister an USB PCD Callback
446   *         USB PCD callback is redirected to the weak predefined callback
447   * @param  hpcd USB PCD handle
448   * @param  CallbackID ID of the callback to be unregistered
449   *         This parameter can be one of the following values:
450   *          @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
451   *          @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
452   *          @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
453   *          @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
454   *          @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
455   *          @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
456   *          @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
457   *          @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
458   *          @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
459   * @retval HAL status
460   */
HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef * hpcd,HAL_PCD_CallbackIDTypeDef CallbackID)461 HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
462 {
463   HAL_StatusTypeDef status = HAL_OK;
464 
465   /* Process locked */
466   __HAL_LOCK(hpcd);
467 
468   /* Setup Legacy weak Callbacks  */
469   if (hpcd->State == HAL_PCD_STATE_READY)
470   {
471     switch (CallbackID)
472     {
473       case HAL_PCD_SOF_CB_ID :
474         hpcd->SOFCallback = HAL_PCD_SOFCallback;
475         break;
476 
477       case HAL_PCD_SETUPSTAGE_CB_ID :
478         hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
479         break;
480 
481       case HAL_PCD_RESET_CB_ID :
482         hpcd->ResetCallback = HAL_PCD_ResetCallback;
483         break;
484 
485       case HAL_PCD_SUSPEND_CB_ID :
486         hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
487         break;
488 
489       case HAL_PCD_RESUME_CB_ID :
490         hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
491         break;
492 
493       case HAL_PCD_CONNECT_CB_ID :
494         hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
495         break;
496 
497       case HAL_PCD_DISCONNECT_CB_ID :
498         hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
499         break;
500 
501       case HAL_PCD_MSPINIT_CB_ID :
502         hpcd->MspInitCallback = HAL_PCD_MspInit;
503         break;
504 
505       case HAL_PCD_MSPDEINIT_CB_ID :
506         hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
507         break;
508 
509       default :
510         /* Update the error code */
511         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
512 
513         /* Return error status */
514         status =  HAL_ERROR;
515         break;
516     }
517   }
518   else if (hpcd->State == HAL_PCD_STATE_RESET)
519   {
520     switch (CallbackID)
521     {
522       case HAL_PCD_MSPINIT_CB_ID :
523         hpcd->MspInitCallback = HAL_PCD_MspInit;
524         break;
525 
526       case HAL_PCD_MSPDEINIT_CB_ID :
527         hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
528         break;
529 
530       default :
531         /* Update the error code */
532         hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
533 
534         /* Return error status */
535         status =  HAL_ERROR;
536         break;
537     }
538   }
539   else
540   {
541     /* Update the error code */
542     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
543 
544     /* Return error status */
545     status =  HAL_ERROR;
546   }
547 
548   /* Release Lock */
549   __HAL_UNLOCK(hpcd);
550   return status;
551 }
552 
553 /**
554   * @brief  Register USB PCD Data OUT Stage Callback
555   *         To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
556   * @param  hpcd PCD handle
557   * @param  pCallback pointer to the USB PCD Data OUT Stage Callback function
558   * @retval HAL status
559   */
HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef * hpcd,pPCD_DataOutStageCallbackTypeDef pCallback)560 HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
561                                                        pPCD_DataOutStageCallbackTypeDef pCallback)
562 {
563   HAL_StatusTypeDef status = HAL_OK;
564 
565   if (pCallback == NULL)
566   {
567     /* Update the error code */
568     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
569 
570     return HAL_ERROR;
571   }
572 
573   /* Process locked */
574   __HAL_LOCK(hpcd);
575 
576   if (hpcd->State == HAL_PCD_STATE_READY)
577   {
578     hpcd->DataOutStageCallback = pCallback;
579   }
580   else
581   {
582     /* Update the error code */
583     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
584 
585     /* Return error status */
586     status =  HAL_ERROR;
587   }
588 
589   /* Release Lock */
590   __HAL_UNLOCK(hpcd);
591 
592   return status;
593 }
594 
595 /**
596   * @brief  Unregister the USB PCD Data OUT Stage Callback
597   *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
598   * @param  hpcd PCD handle
599   * @retval HAL status
600   */
HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef * hpcd)601 HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
602 {
603   HAL_StatusTypeDef status = HAL_OK;
604 
605   /* Process locked */
606   __HAL_LOCK(hpcd);
607 
608   if (hpcd->State == HAL_PCD_STATE_READY)
609   {
610     hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback  */
611   }
612   else
613   {
614     /* Update the error code */
615     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
616 
617     /* Return error status */
618     status =  HAL_ERROR;
619   }
620 
621   /* Release Lock */
622   __HAL_UNLOCK(hpcd);
623 
624   return status;
625 }
626 
627 /**
628   * @brief  Register USB PCD Data IN Stage Callback
629   *         To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
630   * @param  hpcd PCD handle
631   * @param  pCallback pointer to the USB PCD Data IN Stage Callback function
632   * @retval HAL status
633   */
HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef * hpcd,pPCD_DataInStageCallbackTypeDef pCallback)634 HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
635                                                       pPCD_DataInStageCallbackTypeDef pCallback)
636 {
637   HAL_StatusTypeDef status = HAL_OK;
638 
639   if (pCallback == NULL)
640   {
641     /* Update the error code */
642     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
643 
644     return HAL_ERROR;
645   }
646 
647   /* Process locked */
648   __HAL_LOCK(hpcd);
649 
650   if (hpcd->State == HAL_PCD_STATE_READY)
651   {
652     hpcd->DataInStageCallback = pCallback;
653   }
654   else
655   {
656     /* Update the error code */
657     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
658 
659     /* Return error status */
660     status =  HAL_ERROR;
661   }
662 
663   /* Release Lock */
664   __HAL_UNLOCK(hpcd);
665 
666   return status;
667 }
668 
669 /**
670   * @brief  Unregister the USB PCD Data IN Stage Callback
671   *         USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
672   * @param  hpcd PCD handle
673   * @retval HAL status
674   */
HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef * hpcd)675 HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
676 {
677   HAL_StatusTypeDef status = HAL_OK;
678 
679   /* Process locked */
680   __HAL_LOCK(hpcd);
681 
682   if (hpcd->State == HAL_PCD_STATE_READY)
683   {
684     hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback  */
685   }
686   else
687   {
688     /* Update the error code */
689     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
690 
691     /* Return error status */
692     status =  HAL_ERROR;
693   }
694 
695   /* Release Lock */
696   __HAL_UNLOCK(hpcd);
697 
698   return status;
699 }
700 
701 /**
702   * @brief  Register USB PCD Iso OUT incomplete Callback
703   *         To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
704   * @param  hpcd PCD handle
705   * @param  pCallback pointer to the USB PCD Iso OUT incomplete Callback function
706   * @retval HAL status
707   */
HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef * hpcd,pPCD_IsoOutIncpltCallbackTypeDef pCallback)708 HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
709                                                        pPCD_IsoOutIncpltCallbackTypeDef pCallback)
710 {
711   HAL_StatusTypeDef status = HAL_OK;
712 
713   if (pCallback == NULL)
714   {
715     /* Update the error code */
716     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
717 
718     return HAL_ERROR;
719   }
720 
721   /* Process locked */
722   __HAL_LOCK(hpcd);
723 
724   if (hpcd->State == HAL_PCD_STATE_READY)
725   {
726     hpcd->ISOOUTIncompleteCallback = pCallback;
727   }
728   else
729   {
730     /* Update the error code */
731     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
732 
733     /* Return error status */
734     status =  HAL_ERROR;
735   }
736 
737   /* Release Lock */
738   __HAL_UNLOCK(hpcd);
739 
740   return status;
741 }
742 
743 /**
744   * @brief  Unregister the USB PCD Iso OUT incomplete Callback
745   *         USB PCD Iso OUT incomplete Callback is redirected
746   *         to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
747   * @param  hpcd PCD handle
748   * @retval HAL status
749   */
HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef * hpcd)750 HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
751 {
752   HAL_StatusTypeDef status = HAL_OK;
753 
754   /* Process locked */
755   __HAL_LOCK(hpcd);
756 
757   if (hpcd->State == HAL_PCD_STATE_READY)
758   {
759     hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback  */
760   }
761   else
762   {
763     /* Update the error code */
764     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
765 
766     /* Return error status */
767     status =  HAL_ERROR;
768   }
769 
770   /* Release Lock */
771   __HAL_UNLOCK(hpcd);
772 
773   return status;
774 }
775 
776 /**
777   * @brief  Register USB PCD Iso IN incomplete Callback
778   *         To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
779   * @param  hpcd PCD handle
780   * @param  pCallback pointer to the USB PCD Iso IN incomplete Callback function
781   * @retval HAL status
782   */
HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef * hpcd,pPCD_IsoInIncpltCallbackTypeDef pCallback)783 HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
784                                                       pPCD_IsoInIncpltCallbackTypeDef pCallback)
785 {
786   HAL_StatusTypeDef status = HAL_OK;
787 
788   if (pCallback == NULL)
789   {
790     /* Update the error code */
791     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
792 
793     return HAL_ERROR;
794   }
795 
796   /* Process locked */
797   __HAL_LOCK(hpcd);
798 
799   if (hpcd->State == HAL_PCD_STATE_READY)
800   {
801     hpcd->ISOINIncompleteCallback = pCallback;
802   }
803   else
804   {
805     /* Update the error code */
806     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
807 
808     /* Return error status */
809     status =  HAL_ERROR;
810   }
811 
812   /* Release Lock */
813   __HAL_UNLOCK(hpcd);
814 
815   return status;
816 }
817 
818 /**
819   * @brief  Unregister the USB PCD Iso IN incomplete Callback
820   *         USB PCD Iso IN incomplete Callback is redirected
821   *         to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
822   * @param  hpcd PCD handle
823   * @retval HAL status
824   */
HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef * hpcd)825 HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
826 {
827   HAL_StatusTypeDef status = HAL_OK;
828 
829   /* Process locked */
830   __HAL_LOCK(hpcd);
831 
832   if (hpcd->State == HAL_PCD_STATE_READY)
833   {
834     hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback  */
835   }
836   else
837   {
838     /* Update the error code */
839     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
840 
841     /* Return error status */
842     status =  HAL_ERROR;
843   }
844 
845   /* Release Lock */
846   __HAL_UNLOCK(hpcd);
847 
848   return status;
849 }
850 
851 /**
852   * @brief  Register USB PCD BCD Callback
853   *         To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
854   * @param  hpcd PCD handle
855   * @param  pCallback pointer to the USB PCD BCD Callback function
856   * @retval HAL status
857   */
HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef * hpcd,pPCD_BcdCallbackTypeDef pCallback)858 HAL_StatusTypeDef HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef *hpcd, pPCD_BcdCallbackTypeDef pCallback)
859 {
860   HAL_StatusTypeDef status = HAL_OK;
861 
862   if (pCallback == NULL)
863   {
864     /* Update the error code */
865     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
866 
867     return HAL_ERROR;
868   }
869 
870   /* Process locked */
871   __HAL_LOCK(hpcd);
872 
873   if (hpcd->State == HAL_PCD_STATE_READY)
874   {
875     hpcd->BCDCallback = pCallback;
876   }
877   else
878   {
879     /* Update the error code */
880     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
881 
882     /* Return error status */
883     status =  HAL_ERROR;
884   }
885 
886   /* Release Lock */
887   __HAL_UNLOCK(hpcd);
888 
889   return status;
890 }
891 
892 /**
893   * @brief  Unregister the USB PCD BCD Callback
894   *         USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
895   * @param  hpcd PCD handle
896   * @retval HAL status
897   */
HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef * hpcd)898 HAL_StatusTypeDef HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef *hpcd)
899 {
900   HAL_StatusTypeDef status = HAL_OK;
901 
902   /* Process locked */
903   __HAL_LOCK(hpcd);
904 
905   if (hpcd->State == HAL_PCD_STATE_READY)
906   {
907     hpcd->BCDCallback = HAL_PCDEx_BCD_Callback; /* Legacy weak HAL_PCDEx_BCD_Callback  */
908   }
909   else
910   {
911     /* Update the error code */
912     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
913 
914     /* Return error status */
915     status =  HAL_ERROR;
916   }
917 
918   /* Release Lock */
919   __HAL_UNLOCK(hpcd);
920 
921   return status;
922 }
923 
924 /**
925   * @brief  Register USB PCD LPM Callback
926   *         To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
927   * @param  hpcd PCD handle
928   * @param  pCallback pointer to the USB PCD LPM Callback function
929   * @retval HAL status
930   */
HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef * hpcd,pPCD_LpmCallbackTypeDef pCallback)931 HAL_StatusTypeDef HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef *hpcd, pPCD_LpmCallbackTypeDef pCallback)
932 {
933   HAL_StatusTypeDef status = HAL_OK;
934 
935   if (pCallback == NULL)
936   {
937     /* Update the error code */
938     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
939 
940     return HAL_ERROR;
941   }
942 
943   /* Process locked */
944   __HAL_LOCK(hpcd);
945 
946   if (hpcd->State == HAL_PCD_STATE_READY)
947   {
948     hpcd->LPMCallback = pCallback;
949   }
950   else
951   {
952     /* Update the error code */
953     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
954 
955     /* Return error status */
956     status =  HAL_ERROR;
957   }
958 
959   /* Release Lock */
960   __HAL_UNLOCK(hpcd);
961 
962   return status;
963 }
964 
965 /**
966   * @brief  Unregister the USB PCD LPM Callback
967   *         USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
968   * @param  hpcd PCD handle
969   * @retval HAL status
970   */
HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef * hpcd)971 HAL_StatusTypeDef HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef *hpcd)
972 {
973   HAL_StatusTypeDef status = HAL_OK;
974 
975   /* Process locked */
976   __HAL_LOCK(hpcd);
977 
978   if (hpcd->State == HAL_PCD_STATE_READY)
979   {
980     hpcd->LPMCallback = HAL_PCDEx_LPM_Callback; /* Legacy weak HAL_PCDEx_LPM_Callback  */
981   }
982   else
983   {
984     /* Update the error code */
985     hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
986 
987     /* Return error status */
988     status =  HAL_ERROR;
989   }
990 
991   /* Release Lock */
992   __HAL_UNLOCK(hpcd);
993 
994   return status;
995 }
996 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
997 
998 /**
999   * @}
1000   */
1001 
1002 /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
1003   *  @brief   Data transfers functions
1004   *
1005 @verbatim
1006  ===============================================================================
1007                       ##### IO operation functions #####
1008  ===============================================================================
1009     [..]
1010     This subsection provides a set of functions allowing to manage the PCD data
1011     transfers.
1012 
1013 @endverbatim
1014   * @{
1015   */
1016 
1017 /**
1018   * @brief  Start the USB device
1019   * @param  hpcd PCD handle
1020   * @retval HAL status
1021   */
HAL_PCD_Start(PCD_HandleTypeDef * hpcd)1022 HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
1023 {
1024 #if defined (USB_OTG_FS)
1025   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1026 #endif /* defined (USB_OTG_FS) */
1027 
1028   __HAL_LOCK(hpcd);
1029 #if defined (USB_OTG_FS)
1030   if (hpcd->Init.battery_charging_enable == 1U)
1031   {
1032     /* Enable USB Transceiver */
1033     USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
1034   }
1035 #endif /* defined (USB_OTG_FS) */
1036   __HAL_PCD_ENABLE(hpcd);
1037   (void)USB_DevConnect(hpcd->Instance);
1038   __HAL_UNLOCK(hpcd);
1039 
1040   return HAL_OK;
1041 }
1042 
1043 /**
1044   * @brief  Stop the USB device.
1045   * @param  hpcd PCD handle
1046   * @retval HAL status
1047   */
HAL_PCD_Stop(PCD_HandleTypeDef * hpcd)1048 HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
1049 {
1050 #if defined (USB_OTG_FS)
1051   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1052 #endif /* defined (USB_OTG_FS) */
1053 
1054   __HAL_LOCK(hpcd);
1055   __HAL_PCD_DISABLE(hpcd);
1056   (void)USB_DevDisconnect(hpcd->Instance);
1057 
1058 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1059   (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
1060 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1061 
1062 #if defined (USB_OTG_FS)
1063   if (hpcd->Init.battery_charging_enable == 1U)
1064   {
1065     /* Disable USB Transceiver */
1066     USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
1067   }
1068 #endif /* defined (USB_OTG_FS) */
1069 
1070   __HAL_UNLOCK(hpcd);
1071 
1072   return HAL_OK;
1073 }
1074 
1075 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1076 /**
1077   * @brief  Handles PCD interrupt request.
1078   * @param  hpcd PCD handle
1079   * @retval HAL status
1080   */
HAL_PCD_IRQHandler(PCD_HandleTypeDef * hpcd)1081 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
1082 {
1083   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1084   uint32_t USBx_BASE = (uint32_t)USBx;
1085   USB_OTG_EPTypeDef *ep;
1086   uint32_t i;
1087   uint32_t ep_intr;
1088   uint32_t epint;
1089   uint32_t epnum;
1090   uint32_t fifoemptymsk;
1091   uint32_t RegVal;
1092 
1093   /* ensure that we are in device mode */
1094   if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
1095   {
1096     /* avoid spurious interrupt */
1097     if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
1098     {
1099       return;
1100     }
1101 
1102     /* store current frame number */
1103     hpcd->FrameNumber = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos;
1104 
1105     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
1106     {
1107       /* incorrect mode, acknowledge the interrupt */
1108       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
1109     }
1110 
1111     /* Handle RxQLevel Interrupt */
1112     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
1113     {
1114       USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
1115 
1116       RegVal = USBx->GRXSTSP;
1117 
1118       ep = &hpcd->OUT_ep[RegVal & USB_OTG_GRXSTSP_EPNUM];
1119 
1120       if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) ==  STS_DATA_UPDT)
1121       {
1122         if ((RegVal & USB_OTG_GRXSTSP_BCNT) != 0U)
1123         {
1124           (void)USB_ReadPacket(USBx, ep->xfer_buff,
1125                                (uint16_t)((RegVal & USB_OTG_GRXSTSP_BCNT) >> 4));
1126 
1127           ep->xfer_buff += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
1128           ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
1129         }
1130       }
1131       else if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
1132       {
1133         (void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
1134         ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
1135       }
1136       else
1137       {
1138         /* ... */
1139       }
1140 
1141       USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
1142     }
1143 
1144     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
1145     {
1146       epnum = 0U;
1147 
1148       /* Read in the device interrupt bits */
1149       ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
1150 
1151       while (ep_intr != 0U)
1152       {
1153         if ((ep_intr & 0x1U) != 0U)
1154         {
1155           epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
1156 
1157           if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
1158           {
1159             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
1160             (void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
1161           }
1162 
1163           if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
1164           {
1165             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
1166             /* Class B setup phase done for previous decoded setup */
1167             (void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
1168           }
1169 
1170           if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
1171           {
1172             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
1173           }
1174 
1175           /* Clear OUT Endpoint disable interrupt */
1176           if ((epint & USB_OTG_DOEPINT_EPDISD) == USB_OTG_DOEPINT_EPDISD)
1177           {
1178             if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == USB_OTG_GINTSTS_BOUTNAKEFF)
1179             {
1180               USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;
1181             }
1182 
1183             ep = &hpcd->OUT_ep[epnum];
1184 
1185             if (ep->is_iso_incomplete == 1U)
1186             {
1187               ep->is_iso_incomplete = 0U;
1188 
1189 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1190               hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1191 #else
1192               HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
1193 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1194             }
1195 
1196             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_EPDISD);
1197           }
1198 
1199           /* Clear Status Phase Received interrupt */
1200           if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
1201           {
1202             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
1203           }
1204 
1205           /* Clear OUT NAK interrupt */
1206           if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
1207           {
1208             CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
1209           }
1210         }
1211         epnum++;
1212         ep_intr >>= 1U;
1213       }
1214     }
1215 
1216     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
1217     {
1218       /* Read in the device interrupt bits */
1219       ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
1220 
1221       epnum = 0U;
1222 
1223       while (ep_intr != 0U)
1224       {
1225         if ((ep_intr & 0x1U) != 0U) /* In ITR */
1226         {
1227           epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
1228 
1229           if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
1230           {
1231             fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
1232             USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
1233 
1234             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
1235 
1236             if (hpcd->Init.dma_enable == 1U)
1237             {
1238               hpcd->IN_ep[epnum].xfer_buff += hpcd->IN_ep[epnum].maxpacket;
1239 
1240               /* this is ZLP, so prepare EP0 for next setup */
1241               if ((epnum == 0U) && (hpcd->IN_ep[epnum].xfer_len == 0U))
1242               {
1243                 /* prepare to rx more setup packets */
1244                 (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
1245               }
1246             }
1247 
1248 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1249             hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
1250 #else
1251             HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
1252 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1253           }
1254           if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
1255           {
1256             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
1257           }
1258           if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
1259           {
1260             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
1261           }
1262           if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
1263           {
1264             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
1265           }
1266           if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
1267           {
1268             (void)USB_FlushTxFifo(USBx, epnum);
1269 
1270             ep = &hpcd->IN_ep[epnum];
1271 
1272             if (ep->is_iso_incomplete == 1U)
1273             {
1274               ep->is_iso_incomplete = 0U;
1275 
1276 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1277               hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1278 #else
1279               HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
1280 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1281             }
1282 
1283             CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
1284           }
1285           if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
1286           {
1287             (void)PCD_WriteEmptyTxFifo(hpcd, epnum);
1288           }
1289         }
1290         epnum++;
1291         ep_intr >>= 1U;
1292       }
1293     }
1294 
1295     /* Handle Resume Interrupt */
1296     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
1297     {
1298       /* Clear the Remote Wake-up Signaling */
1299       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1300 
1301       if (hpcd->LPM_State == LPM_L1)
1302       {
1303         hpcd->LPM_State = LPM_L0;
1304 
1305 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1306         hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
1307 #else
1308         HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
1309 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1310       }
1311       else
1312       {
1313 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1314         hpcd->ResumeCallback(hpcd);
1315 #else
1316         HAL_PCD_ResumeCallback(hpcd);
1317 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1318       }
1319 
1320       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
1321     }
1322 
1323     /* Handle Suspend Interrupt */
1324     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
1325     {
1326       if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
1327       {
1328 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1329         hpcd->SuspendCallback(hpcd);
1330 #else
1331         HAL_PCD_SuspendCallback(hpcd);
1332 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1333       }
1334       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
1335     }
1336 
1337     /* Handle LPM Interrupt */
1338     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT))
1339     {
1340       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_LPMINT);
1341 
1342       if (hpcd->LPM_State == LPM_L0)
1343       {
1344         hpcd->LPM_State = LPM_L1;
1345         hpcd->BESL = (hpcd->Instance->GLPMCFG & USB_OTG_GLPMCFG_BESL) >> 2U;
1346 
1347 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1348         hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
1349 #else
1350         HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
1351 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1352       }
1353       else
1354       {
1355 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1356         hpcd->SuspendCallback(hpcd);
1357 #else
1358         HAL_PCD_SuspendCallback(hpcd);
1359 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1360       }
1361     }
1362 
1363     /* Handle Reset Interrupt */
1364     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
1365     {
1366       USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
1367       (void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
1368 
1369       for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
1370       {
1371         USBx_INEP(i)->DIEPINT = 0xFB7FU;
1372         USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
1373         USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
1374         USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
1375         USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
1376       }
1377       USBx_DEVICE->DAINTMSK |= 0x10001U;
1378 
1379       if (hpcd->Init.use_dedicated_ep1 != 0U)
1380       {
1381         USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
1382                                    USB_OTG_DOEPMSK_XFRCM |
1383                                    USB_OTG_DOEPMSK_EPDM;
1384 
1385         USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
1386                                   USB_OTG_DIEPMSK_XFRCM |
1387                                   USB_OTG_DIEPMSK_EPDM;
1388       }
1389       else
1390       {
1391         USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
1392                                 USB_OTG_DOEPMSK_XFRCM |
1393                                 USB_OTG_DOEPMSK_EPDM |
1394                                 USB_OTG_DOEPMSK_OTEPSPRM |
1395                                 USB_OTG_DOEPMSK_NAKM;
1396 
1397         USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
1398                                 USB_OTG_DIEPMSK_XFRCM |
1399                                 USB_OTG_DIEPMSK_EPDM;
1400       }
1401 
1402       /* Set Default Address to 0 */
1403       USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
1404 
1405       /* setup EP0 to receive SETUP packets */
1406       (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable,
1407                              (uint8_t *)hpcd->Setup);
1408 
1409       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
1410     }
1411 
1412     /* Handle Enumeration done Interrupt */
1413     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
1414     {
1415       (void)USB_ActivateSetup(hpcd->Instance);
1416       hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
1417 
1418       /* Set USB Turnaround time */
1419       (void)USB_SetTurnaroundTime(hpcd->Instance,
1420                                   HAL_RCC_GetHCLKFreq(),
1421                                   (uint8_t)hpcd->Init.speed);
1422 
1423 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1424       hpcd->ResetCallback(hpcd);
1425 #else
1426       HAL_PCD_ResetCallback(hpcd);
1427 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1428 
1429       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
1430     }
1431 
1432     /* Handle SOF Interrupt */
1433     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
1434     {
1435 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1436       hpcd->SOFCallback(hpcd);
1437 #else
1438       HAL_PCD_SOFCallback(hpcd);
1439 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1440 
1441       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
1442     }
1443 
1444     /* Handle Global OUT NAK effective Interrupt */
1445     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_BOUTNAKEFF))
1446     {
1447       USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM;
1448 
1449       for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
1450       {
1451         if (hpcd->OUT_ep[epnum].is_iso_incomplete == 1U)
1452         {
1453           /* Abort current transaction and disable the EP */
1454           (void)HAL_PCD_EP_Abort(hpcd, (uint8_t)epnum);
1455         }
1456       }
1457     }
1458 
1459     /* Handle Incomplete ISO IN Interrupt */
1460     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
1461     {
1462       for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
1463       {
1464         RegVal = USBx_INEP(epnum)->DIEPCTL;
1465 
1466         if ((hpcd->IN_ep[epnum].type == EP_TYPE_ISOC) &&
1467             ((RegVal & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA))
1468         {
1469           hpcd->IN_ep[epnum].is_iso_incomplete = 1U;
1470 
1471           /* Abort current transaction and disable the EP */
1472           (void)HAL_PCD_EP_Abort(hpcd, (uint8_t)(epnum | 0x80U));
1473         }
1474       }
1475 
1476       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
1477     }
1478 
1479     /* Handle Incomplete ISO OUT Interrupt */
1480     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
1481     {
1482       for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
1483       {
1484         RegVal = USBx_OUTEP(epnum)->DOEPCTL;
1485 
1486         if ((hpcd->OUT_ep[epnum].type == EP_TYPE_ISOC) &&
1487             ((RegVal & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) &&
1488             ((RegVal & (0x1U << 16)) == (hpcd->FrameNumber & 0x1U)))
1489         {
1490           hpcd->OUT_ep[epnum].is_iso_incomplete = 1U;
1491 
1492           USBx->GINTMSK |= USB_OTG_GINTMSK_GONAKEFFM;
1493 
1494           if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == 0U)
1495           {
1496             USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;
1497             break;
1498           }
1499         }
1500       }
1501 
1502       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
1503     }
1504 
1505     /* Handle Connection event Interrupt */
1506     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
1507     {
1508 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1509       hpcd->ConnectCallback(hpcd);
1510 #else
1511       HAL_PCD_ConnectCallback(hpcd);
1512 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1513 
1514       __HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
1515     }
1516 
1517     /* Handle Disconnection event Interrupt */
1518     if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
1519     {
1520       RegVal = hpcd->Instance->GOTGINT;
1521 
1522       if ((RegVal & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
1523       {
1524 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1525         hpcd->DisconnectCallback(hpcd);
1526 #else
1527         HAL_PCD_DisconnectCallback(hpcd);
1528 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1529       }
1530       hpcd->Instance->GOTGINT |= RegVal;
1531     }
1532   }
1533 }
1534 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1535 
1536 #if defined (USB_DRD_FS)
1537 /**
1538   * @brief  This function handles PCD interrupt request.
1539   * @param  hpcd PCD handle
1540   * @retval HAL status
1541   */
HAL_PCD_IRQHandler(PCD_HandleTypeDef * hpcd)1542 void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
1543 {
1544   uint32_t wIstr = USB_ReadInterrupts(hpcd->Instance);
1545 
1546   if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
1547   {
1548     /* servicing of the endpoint correct transfer interrupt */
1549     /* clear of the CTR flag into the sub */
1550     (void)PCD_EP_ISR_Handler(hpcd);
1551 
1552     return;
1553   }
1554 
1555   if ((wIstr & USB_ISTR_RESET) == USB_ISTR_RESET)
1556   {
1557     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
1558 
1559 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1560     hpcd->ResetCallback(hpcd);
1561 #else
1562     HAL_PCD_ResetCallback(hpcd);
1563 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1564 
1565     (void)HAL_PCD_SetAddress(hpcd, 0U);
1566 
1567     return;
1568   }
1569 
1570   if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
1571   {
1572     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
1573 
1574     return;
1575   }
1576 
1577   if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
1578   {
1579     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
1580 
1581     return;
1582   }
1583 
1584   if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
1585   {
1586     hpcd->Instance->CNTR &= ~(USB_CNTR_SUSPRDY);
1587     hpcd->Instance->CNTR &= ~(USB_CNTR_SUSPEN);
1588 
1589     if (hpcd->LPM_State == LPM_L1)
1590     {
1591       hpcd->LPM_State = LPM_L0;
1592 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1593       hpcd->LPMCallback(hpcd, PCD_LPM_L0_ACTIVE);
1594 #else
1595       HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L0_ACTIVE);
1596 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1597     }
1598 
1599 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1600     hpcd->ResumeCallback(hpcd);
1601 #else
1602     HAL_PCD_ResumeCallback(hpcd);
1603 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1604 
1605     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
1606 
1607     return;
1608   }
1609 
1610   if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
1611   {
1612     /* Force low-power mode in the macrocell */
1613     hpcd->Instance->CNTR |= USB_CNTR_SUSPEN;
1614 
1615     /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
1616     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
1617 
1618     hpcd->Instance->CNTR |= USB_CNTR_SUSPRDY;
1619 
1620 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1621     hpcd->SuspendCallback(hpcd);
1622 #else
1623     HAL_PCD_SuspendCallback(hpcd);
1624 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1625 
1626     return;
1627   }
1628 
1629   /* Handle LPM Interrupt */
1630   if ((wIstr & USB_ISTR_L1REQ) == USB_ISTR_L1REQ)
1631   {
1632     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_L1REQ);
1633     if (hpcd->LPM_State == LPM_L0)
1634     {
1635       /* Force suspend and low-power mode before going to L1 state*/
1636       hpcd->Instance->CNTR |= USB_CNTR_SUSPRDY;
1637       hpcd->Instance->CNTR |= USB_CNTR_SUSPEN;
1638 
1639       hpcd->LPM_State = LPM_L1;
1640       hpcd->BESL = ((uint32_t)hpcd->Instance->LPMCSR & USB_LPMCSR_BESL) >> 2;
1641 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1642       hpcd->LPMCallback(hpcd, PCD_LPM_L1_ACTIVE);
1643 #else
1644       HAL_PCDEx_LPM_Callback(hpcd, PCD_LPM_L1_ACTIVE);
1645 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1646     }
1647     else
1648     {
1649 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1650       hpcd->SuspendCallback(hpcd);
1651 #else
1652       HAL_PCD_SuspendCallback(hpcd);
1653 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1654     }
1655 
1656     return;
1657   }
1658 
1659   if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
1660   {
1661     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
1662 
1663 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1664     hpcd->SOFCallback(hpcd);
1665 #else
1666     HAL_PCD_SOFCallback(hpcd);
1667 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1668 
1669     return;
1670   }
1671 
1672   if ((wIstr & USB_ISTR_ESOF) == USB_ISTR_ESOF)
1673   {
1674     /* clear ESOF flag in ISTR */
1675     __HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
1676 
1677     return;
1678   }
1679 }
1680 #endif /* defined (USB_DRD_FS) */
1681 
1682 /**
1683   * @brief  Data OUT stage callback.
1684   * @param  hpcd PCD handle
1685   * @param  epnum endpoint number
1686   * @retval None
1687   */
HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1688 __weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1689 {
1690   /* Prevent unused argument(s) compilation warning */
1691   UNUSED(hpcd);
1692   UNUSED(epnum);
1693 
1694   /* NOTE : This function should not be modified, when the callback is needed,
1695             the HAL_PCD_DataOutStageCallback could be implemented in the user file
1696    */
1697 }
1698 
1699 /**
1700   * @brief  Data IN stage callback
1701   * @param  hpcd PCD handle
1702   * @param  epnum endpoint number
1703   * @retval None
1704   */
HAL_PCD_DataInStageCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1705 __weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1706 {
1707   /* Prevent unused argument(s) compilation warning */
1708   UNUSED(hpcd);
1709   UNUSED(epnum);
1710 
1711   /* NOTE : This function should not be modified, when the callback is needed,
1712             the HAL_PCD_DataInStageCallback could be implemented in the user file
1713    */
1714 }
1715 /**
1716   * @brief  Setup stage callback
1717   * @param  hpcd PCD handle
1718   * @retval None
1719   */
HAL_PCD_SetupStageCallback(PCD_HandleTypeDef * hpcd)1720 __weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
1721 {
1722   /* Prevent unused argument(s) compilation warning */
1723   UNUSED(hpcd);
1724 
1725   /* NOTE : This function should not be modified, when the callback is needed,
1726             the HAL_PCD_SetupStageCallback could be implemented in the user file
1727    */
1728 }
1729 
1730 /**
1731   * @brief  USB Start Of Frame callback.
1732   * @param  hpcd PCD handle
1733   * @retval None
1734   */
HAL_PCD_SOFCallback(PCD_HandleTypeDef * hpcd)1735 __weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
1736 {
1737   /* Prevent unused argument(s) compilation warning */
1738   UNUSED(hpcd);
1739 
1740   /* NOTE : This function should not be modified, when the callback is needed,
1741             the HAL_PCD_SOFCallback could be implemented in the user file
1742    */
1743 }
1744 
1745 /**
1746   * @brief  USB Reset callback.
1747   * @param  hpcd PCD handle
1748   * @retval None
1749   */
HAL_PCD_ResetCallback(PCD_HandleTypeDef * hpcd)1750 __weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
1751 {
1752   /* Prevent unused argument(s) compilation warning */
1753   UNUSED(hpcd);
1754 
1755   /* NOTE : This function should not be modified, when the callback is needed,
1756             the HAL_PCD_ResetCallback could be implemented in the user file
1757    */
1758 }
1759 
1760 /**
1761   * @brief  Suspend event callback.
1762   * @param  hpcd PCD handle
1763   * @retval None
1764   */
HAL_PCD_SuspendCallback(PCD_HandleTypeDef * hpcd)1765 __weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
1766 {
1767   /* Prevent unused argument(s) compilation warning */
1768   UNUSED(hpcd);
1769 
1770   /* NOTE : This function should not be modified, when the callback is needed,
1771             the HAL_PCD_SuspendCallback could be implemented in the user file
1772    */
1773 }
1774 
1775 /**
1776   * @brief  Resume event callback.
1777   * @param  hpcd PCD handle
1778   * @retval None
1779   */
HAL_PCD_ResumeCallback(PCD_HandleTypeDef * hpcd)1780 __weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
1781 {
1782   /* Prevent unused argument(s) compilation warning */
1783   UNUSED(hpcd);
1784 
1785   /* NOTE : This function should not be modified, when the callback is needed,
1786             the HAL_PCD_ResumeCallback could be implemented in the user file
1787    */
1788 }
1789 
1790 /**
1791   * @brief  Incomplete ISO OUT callback.
1792   * @param  hpcd PCD handle
1793   * @param  epnum endpoint number
1794   * @retval None
1795   */
HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1796 __weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1797 {
1798   /* Prevent unused argument(s) compilation warning */
1799   UNUSED(hpcd);
1800   UNUSED(epnum);
1801 
1802   /* NOTE : This function should not be modified, when the callback is needed,
1803             the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
1804    */
1805 }
1806 
1807 /**
1808   * @brief  Incomplete ISO IN callback.
1809   * @param  hpcd PCD handle
1810   * @param  epnum endpoint number
1811   * @retval None
1812   */
HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef * hpcd,uint8_t epnum)1813 __weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
1814 {
1815   /* Prevent unused argument(s) compilation warning */
1816   UNUSED(hpcd);
1817   UNUSED(epnum);
1818 
1819   /* NOTE : This function should not be modified, when the callback is needed,
1820             the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1821    */
1822 }
1823 
1824 /**
1825   * @brief  Connection event callback.
1826   * @param  hpcd PCD handle
1827   * @retval None
1828   */
HAL_PCD_ConnectCallback(PCD_HandleTypeDef * hpcd)1829 __weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
1830 {
1831   /* Prevent unused argument(s) compilation warning */
1832   UNUSED(hpcd);
1833 
1834   /* NOTE : This function should not be modified, when the callback is needed,
1835             the HAL_PCD_ConnectCallback could be implemented in the user file
1836    */
1837 }
1838 
1839 /**
1840   * @brief  Disconnection event callback.
1841   * @param  hpcd PCD handle
1842   * @retval None
1843   */
HAL_PCD_DisconnectCallback(PCD_HandleTypeDef * hpcd)1844 __weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
1845 {
1846   /* Prevent unused argument(s) compilation warning */
1847   UNUSED(hpcd);
1848 
1849   /* NOTE : This function should not be modified, when the callback is needed,
1850             the HAL_PCD_DisconnectCallback could be implemented in the user file
1851    */
1852 }
1853 
1854 /**
1855   * @}
1856   */
1857 
1858 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
1859   *  @brief   management functions
1860   *
1861 @verbatim
1862  ===============================================================================
1863                       ##### Peripheral Control functions #####
1864  ===============================================================================
1865     [..]
1866     This subsection provides a set of functions allowing to control the PCD data
1867     transfers.
1868 
1869 @endverbatim
1870   * @{
1871   */
1872 
1873 /**
1874   * @brief  Connect the USB device
1875   * @param  hpcd PCD handle
1876   * @retval HAL status
1877   */
HAL_PCD_DevConnect(PCD_HandleTypeDef * hpcd)1878 HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
1879 {
1880 #if defined (USB_OTG_FS)
1881   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1882 #endif /* defined (USB_OTG_FS) */
1883 
1884   __HAL_LOCK(hpcd);
1885 
1886 #if defined (USB_OTG_FS)
1887   if (hpcd->Init.battery_charging_enable == 1U)
1888   {
1889     /* Enable USB Transceiver */
1890     USBx->GCCFG |= USB_OTG_GCCFG_PWRDWN;
1891   }
1892 #endif /* defined (USB_OTG_FS) */
1893 
1894   (void)USB_DevConnect(hpcd->Instance);
1895   __HAL_UNLOCK(hpcd);
1896 
1897   return HAL_OK;
1898 }
1899 
1900 /**
1901   * @brief  Disconnect the USB device.
1902   * @param  hpcd PCD handle
1903   * @retval HAL status
1904   */
HAL_PCD_DevDisconnect(PCD_HandleTypeDef * hpcd)1905 HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
1906 {
1907 #if defined (USB_OTG_FS)
1908   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
1909 #endif /* defined (USB_OTG_FS) */
1910 
1911   __HAL_LOCK(hpcd);
1912   (void)USB_DevDisconnect(hpcd->Instance);
1913 
1914 #if defined (USB_OTG_FS)
1915   if (hpcd->Init.battery_charging_enable == 1U)
1916   {
1917     /* Disable USB Transceiver */
1918     USBx->GCCFG &= ~(USB_OTG_GCCFG_PWRDWN);
1919   }
1920 #endif /* defined (USB_OTG_FS) */
1921 
1922   __HAL_UNLOCK(hpcd);
1923 
1924   return HAL_OK;
1925 }
1926 
1927 /**
1928   * @brief  Set the USB Device address.
1929   * @param  hpcd PCD handle
1930   * @param  address new device address
1931   * @retval HAL status
1932   */
HAL_PCD_SetAddress(PCD_HandleTypeDef * hpcd,uint8_t address)1933 HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
1934 {
1935   __HAL_LOCK(hpcd);
1936   hpcd->USB_Address = address;
1937   (void)USB_SetDevAddress(hpcd->Instance, address);
1938   __HAL_UNLOCK(hpcd);
1939 
1940   return HAL_OK;
1941 }
1942 /**
1943   * @brief  Open and configure an endpoint.
1944   * @param  hpcd PCD handle
1945   * @param  ep_addr endpoint address
1946   * @param  ep_mps endpoint max packet size
1947   * @param  ep_type endpoint type
1948   * @retval HAL status
1949   */
HAL_PCD_EP_Open(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint16_t ep_mps,uint8_t ep_type)1950 HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
1951                                   uint16_t ep_mps, uint8_t ep_type)
1952 {
1953   HAL_StatusTypeDef ret = HAL_OK;
1954   PCD_EPTypeDef *ep;
1955 
1956   if ((ep_addr & 0x80U) == 0x80U)
1957   {
1958     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
1959     ep->is_in = 1U;
1960   }
1961   else
1962   {
1963     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
1964     ep->is_in = 0U;
1965   }
1966 
1967   ep->num = ep_addr & EP_ADDR_MSK;
1968   ep->maxpacket = (uint32_t)ep_mps & 0x7FFU;
1969   ep->type = ep_type;
1970 
1971 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1972   if (ep->is_in != 0U)
1973   {
1974     /* Assign a Tx FIFO */
1975     ep->tx_fifo_num = ep->num;
1976   }
1977 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1978 
1979   /* Set initial data PID. */
1980   if (ep_type == EP_TYPE_BULK)
1981   {
1982     ep->data_pid_start = 0U;
1983   }
1984 
1985   __HAL_LOCK(hpcd);
1986   (void)USB_ActivateEndpoint(hpcd->Instance, ep);
1987   __HAL_UNLOCK(hpcd);
1988 
1989   return ret;
1990 }
1991 
1992 /**
1993   * @brief  Deactivate an endpoint.
1994   * @param  hpcd PCD handle
1995   * @param  ep_addr endpoint address
1996   * @retval HAL status
1997   */
HAL_PCD_EP_Close(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)1998 HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
1999 {
2000   PCD_EPTypeDef *ep;
2001 
2002   if ((ep_addr & 0x80U) == 0x80U)
2003   {
2004     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
2005     ep->is_in = 1U;
2006   }
2007   else
2008   {
2009     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
2010     ep->is_in = 0U;
2011   }
2012   ep->num = ep_addr & EP_ADDR_MSK;
2013 
2014   __HAL_LOCK(hpcd);
2015   (void)USB_DeactivateEndpoint(hpcd->Instance, ep);
2016   __HAL_UNLOCK(hpcd);
2017   return HAL_OK;
2018 }
2019 
2020 
2021 /**
2022   * @brief  Receive an amount of data.
2023   * @param  hpcd PCD handle
2024   * @param  ep_addr endpoint address
2025   * @param  pBuf pointer to the reception buffer
2026   * @param  len amount of data to be received
2027   * @retval HAL status
2028   */
HAL_PCD_EP_Receive(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)2029 HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
2030 {
2031   PCD_EPTypeDef *ep;
2032 
2033   ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
2034 
2035   /*setup and start the Xfer */
2036   ep->xfer_buff = pBuf;
2037   ep->xfer_len = len;
2038   ep->xfer_count = 0U;
2039   ep->is_in = 0U;
2040   ep->num = ep_addr & EP_ADDR_MSK;
2041 
2042 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
2043   if (hpcd->Init.dma_enable == 1U)
2044   {
2045     ep->dma_addr = (uint32_t)pBuf;
2046   }
2047 
2048   (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
2049 #else
2050   (void)USB_EPStartXfer(hpcd->Instance, ep);
2051 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2052 
2053   return HAL_OK;
2054 }
2055 
2056 /**
2057   * @brief  Get Received Data Size
2058   * @param  hpcd PCD handle
2059   * @param  ep_addr endpoint address
2060   * @retval Data Size
2061   */
HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const * hpcd,uint8_t ep_addr)2062 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const *hpcd, uint8_t ep_addr)
2063 {
2064   return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
2065 }
2066 /**
2067   * @brief  Send an amount of data
2068   * @param  hpcd PCD handle
2069   * @param  ep_addr endpoint address
2070   * @param  pBuf pointer to the transmission buffer
2071   * @param  len amount of data to be sent
2072   * @retval HAL status
2073   */
HAL_PCD_EP_Transmit(PCD_HandleTypeDef * hpcd,uint8_t ep_addr,uint8_t * pBuf,uint32_t len)2074 HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
2075 {
2076   PCD_EPTypeDef *ep;
2077 
2078   ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
2079 
2080   /*setup and start the Xfer */
2081   ep->xfer_buff = pBuf;
2082   ep->xfer_len = len;
2083 #if defined (USB_DRD_FS)
2084   ep->xfer_fill_db = 1U;
2085   ep->xfer_len_db = len;
2086 #endif /* defined (USB_DRD_FS) */
2087   ep->xfer_count = 0U;
2088   ep->is_in = 1U;
2089   ep->num = ep_addr & EP_ADDR_MSK;
2090 
2091 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
2092   if (hpcd->Init.dma_enable == 1U)
2093   {
2094     ep->dma_addr = (uint32_t)pBuf;
2095   }
2096 
2097   (void)USB_EPStartXfer(hpcd->Instance, ep, (uint8_t)hpcd->Init.dma_enable);
2098 #else
2099   (void)USB_EPStartXfer(hpcd->Instance, ep);
2100 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2101 
2102   return HAL_OK;
2103 }
2104 
2105 /**
2106   * @brief  Set a STALL condition over an endpoint
2107   * @param  hpcd PCD handle
2108   * @param  ep_addr endpoint address
2109   * @retval HAL status
2110   */
HAL_PCD_EP_SetStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)2111 HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
2112 {
2113   PCD_EPTypeDef *ep;
2114 
2115   if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
2116   {
2117     return HAL_ERROR;
2118   }
2119 
2120   if ((0x80U & ep_addr) == 0x80U)
2121   {
2122     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
2123     ep->is_in = 1U;
2124   }
2125   else
2126   {
2127     ep = &hpcd->OUT_ep[ep_addr];
2128     ep->is_in = 0U;
2129   }
2130 
2131   ep->is_stall = 1U;
2132   ep->num = ep_addr & EP_ADDR_MSK;
2133 
2134   __HAL_LOCK(hpcd);
2135 
2136   (void)USB_EPSetStall(hpcd->Instance, ep);
2137 
2138 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
2139   if ((ep_addr & EP_ADDR_MSK) == 0U)
2140   {
2141     (void)USB_EP0_OutStart(hpcd->Instance, (uint8_t)hpcd->Init.dma_enable, (uint8_t *)hpcd->Setup);
2142   }
2143 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2144 
2145   __HAL_UNLOCK(hpcd);
2146 
2147   return HAL_OK;
2148 }
2149 
2150 /**
2151   * @brief  Clear a STALL condition over in an endpoint
2152   * @param  hpcd PCD handle
2153   * @param  ep_addr endpoint address
2154   * @retval HAL status
2155   */
HAL_PCD_EP_ClrStall(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)2156 HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
2157 {
2158   PCD_EPTypeDef *ep;
2159 
2160   if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
2161   {
2162     return HAL_ERROR;
2163   }
2164 
2165   if ((0x80U & ep_addr) == 0x80U)
2166   {
2167     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
2168     ep->is_in = 1U;
2169   }
2170   else
2171   {
2172     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
2173     ep->is_in = 0U;
2174   }
2175 
2176   ep->is_stall = 0U;
2177   ep->num = ep_addr & EP_ADDR_MSK;
2178 
2179   __HAL_LOCK(hpcd);
2180   (void)USB_EPClearStall(hpcd->Instance, ep);
2181   __HAL_UNLOCK(hpcd);
2182 
2183   return HAL_OK;
2184 }
2185 
2186 /**
2187    * @brief  Abort an USB EP transaction.
2188    * @param  hpcd PCD handle
2189    * @param  ep_addr endpoint address
2190    * @retval HAL status
2191    */
HAL_PCD_EP_Abort(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)2192 HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
2193 {
2194   HAL_StatusTypeDef ret;
2195   PCD_EPTypeDef *ep;
2196 
2197   if ((0x80U & ep_addr) == 0x80U)
2198   {
2199     ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
2200   }
2201   else
2202   {
2203     ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
2204   }
2205 
2206   /* Stop Xfer */
2207   ret = USB_EPStopXfer(hpcd->Instance, ep);
2208 
2209   return ret;
2210 }
2211 
2212 /**
2213   * @brief  Flush an endpoint
2214   * @param  hpcd PCD handle
2215   * @param  ep_addr endpoint address
2216   * @retval HAL status
2217   */
HAL_PCD_EP_Flush(PCD_HandleTypeDef * hpcd,uint8_t ep_addr)2218 HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
2219 {
2220   __HAL_LOCK(hpcd);
2221 
2222   if ((ep_addr & 0x80U) == 0x80U)
2223   {
2224     (void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
2225   }
2226   else
2227   {
2228     (void)USB_FlushRxFifo(hpcd->Instance);
2229   }
2230 
2231   __HAL_UNLOCK(hpcd);
2232 
2233   return HAL_OK;
2234 }
2235 
2236 /**
2237   * @brief  Activate remote wakeup signalling
2238   * @param  hpcd PCD handle
2239   * @retval HAL status
2240   */
HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)2241 HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
2242 {
2243   return (USB_ActivateRemoteWakeup(hpcd->Instance));
2244 }
2245 
2246 /**
2247   * @brief  De-activate remote wakeup signalling.
2248   * @param  hpcd PCD handle
2249   * @retval HAL status
2250   */
HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef * hpcd)2251 HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
2252 {
2253   return (USB_DeActivateRemoteWakeup(hpcd->Instance));
2254 }
2255 
2256 /**
2257   * @}
2258   */
2259 
2260 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
2261   *  @brief   Peripheral State functions
2262   *
2263 @verbatim
2264  ===============================================================================
2265                       ##### Peripheral State functions #####
2266  ===============================================================================
2267     [..]
2268     This subsection permits to get in run-time the status of the peripheral
2269     and the data flow.
2270 
2271 @endverbatim
2272   * @{
2273   */
2274 
2275 /**
2276   * @brief  Return the PCD handle state.
2277   * @param  hpcd PCD handle
2278   * @retval HAL state
2279   */
HAL_PCD_GetState(PCD_HandleTypeDef const * hpcd)2280 PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef const *hpcd)
2281 {
2282   return hpcd->State;
2283 }
2284 
2285 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
2286 /**
2287   * @brief  Set the USB Device high speed test mode.
2288   * @param  hpcd PCD handle
2289   * @param  testmode USB Device high speed test mode
2290   * @retval HAL status
2291   */
HAL_PCD_SetTestMode(const PCD_HandleTypeDef * hpcd,uint8_t testmode)2292 HAL_StatusTypeDef HAL_PCD_SetTestMode(const PCD_HandleTypeDef *hpcd, uint8_t testmode)
2293 {
2294   const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2295   uint32_t USBx_BASE = (uint32_t)USBx;
2296 
2297   switch (testmode)
2298   {
2299     case TEST_J:
2300     case TEST_K:
2301     case TEST_SE0_NAK:
2302     case TEST_PACKET:
2303     case TEST_FORCE_EN:
2304       USBx_DEVICE->DCTL |= (uint32_t)testmode << 4;
2305       break;
2306 
2307     default:
2308       break;
2309   }
2310 
2311   return HAL_OK;
2312 }
2313 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2314 /**
2315   * @}
2316   */
2317 
2318 /**
2319   * @}
2320   */
2321 
2322 /* Private functions ---------------------------------------------------------*/
2323 /** @addtogroup PCD_Private_Functions
2324   * @{
2325   */
2326 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
2327 /**
2328   * @brief  Check FIFO for the next packet to be loaded.
2329   * @param  hpcd PCD handle
2330   * @param  epnum endpoint number
2331   * @retval HAL status
2332   */
PCD_WriteEmptyTxFifo(PCD_HandleTypeDef * hpcd,uint32_t epnum)2333 static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2334 {
2335   USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2336   uint32_t USBx_BASE = (uint32_t)USBx;
2337   USB_OTG_EPTypeDef *ep;
2338   uint32_t len;
2339   uint32_t len32b;
2340   uint32_t fifoemptymsk;
2341 
2342   ep = &hpcd->IN_ep[epnum];
2343 
2344   if (ep->xfer_count > ep->xfer_len)
2345   {
2346     return HAL_ERROR;
2347   }
2348 
2349   len = ep->xfer_len - ep->xfer_count;
2350 
2351   if (len > ep->maxpacket)
2352   {
2353     len = ep->maxpacket;
2354   }
2355 
2356   len32b = (len + 3U) / 4U;
2357 
2358   while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
2359          (ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
2360   {
2361     /* Write the FIFO */
2362     len = ep->xfer_len - ep->xfer_count;
2363 
2364     if (len > ep->maxpacket)
2365     {
2366       len = ep->maxpacket;
2367     }
2368     len32b = (len + 3U) / 4U;
2369 
2370     (void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len,
2371                           (uint8_t)hpcd->Init.dma_enable);
2372 
2373     ep->xfer_buff  += len;
2374     ep->xfer_count += len;
2375   }
2376 
2377   if (ep->xfer_len <= ep->xfer_count)
2378   {
2379     fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
2380     USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
2381   }
2382 
2383   return HAL_OK;
2384 }
2385 
2386 
2387 /**
2388   * @brief  process EP OUT transfer complete interrupt.
2389   * @param  hpcd PCD handle
2390   * @param  epnum endpoint number
2391   * @retval HAL status
2392   */
PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef * hpcd,uint32_t epnum)2393 static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2394 {
2395   USB_OTG_EPTypeDef *ep;
2396   const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2397   uint32_t USBx_BASE = (uint32_t)USBx;
2398   uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
2399   uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
2400 
2401   if (hpcd->Init.dma_enable == 1U)
2402   {
2403     if ((DoepintReg & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP) /* Class C */
2404     {
2405       /* StupPktRcvd = 1 this is a setup packet */
2406       if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
2407           ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
2408       {
2409         CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2410       }
2411     }
2412     else if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR) /* Class E */
2413     {
2414       CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
2415     }
2416     else if ((DoepintReg & (USB_OTG_DOEPINT_STUP | USB_OTG_DOEPINT_OTEPSPR)) == 0U)
2417     {
2418       /* StupPktRcvd = 1 this is a setup packet */
2419       if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
2420           ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
2421       {
2422         CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2423       }
2424       else
2425       {
2426         ep = &hpcd->OUT_ep[epnum];
2427 
2428         /* out data packet received over EP */
2429         ep->xfer_count = ep->xfer_size - (USBx_OUTEP(epnum)->DOEPTSIZ & USB_OTG_DOEPTSIZ_XFRSIZ);
2430 
2431         if (epnum == 0U)
2432         {
2433           if (ep->xfer_len == 0U)
2434           {
2435             /* this is ZLP, so prepare EP0 for next setup */
2436             (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
2437           }
2438           else
2439           {
2440             ep->xfer_buff += ep->xfer_count;
2441           }
2442         }
2443 
2444 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2445         hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2446 #else
2447         HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2448 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2449       }
2450     }
2451     else
2452     {
2453       /* ... */
2454     }
2455   }
2456   else
2457   {
2458     if (gSNPSiD == USB_OTG_CORE_ID_310A)
2459     {
2460       /* StupPktRcvd = 1 this is a setup packet */
2461       if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
2462       {
2463         CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2464       }
2465       else
2466       {
2467         if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
2468         {
2469           CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
2470         }
2471 
2472 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2473         hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2474 #else
2475         HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2476 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2477       }
2478     }
2479     else
2480     {
2481       if ((epnum == 0U) && (hpcd->OUT_ep[epnum].xfer_len == 0U))
2482       {
2483         /* this is ZLP, so prepare EP0 for next setup */
2484         (void)USB_EP0_OutStart(hpcd->Instance, 0U, (uint8_t *)hpcd->Setup);
2485       }
2486 
2487 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2488       hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
2489 #else
2490       HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
2491 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2492     }
2493   }
2494 
2495   return HAL_OK;
2496 }
2497 
2498 
2499 /**
2500   * @brief  process EP OUT setup packet received interrupt.
2501   * @param  hpcd PCD handle
2502   * @param  epnum endpoint number
2503   * @retval HAL status
2504   */
PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef * hpcd,uint32_t epnum)2505 static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
2506 {
2507   const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
2508   uint32_t USBx_BASE = (uint32_t)USBx;
2509   uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
2510   uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
2511 
2512   if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
2513       ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
2514   {
2515     CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
2516   }
2517 
2518   /* Inform the upper layer that a setup packet is available */
2519 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2520   hpcd->SetupStageCallback(hpcd);
2521 #else
2522   HAL_PCD_SetupStageCallback(hpcd);
2523 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2524 
2525   if ((gSNPSiD > USB_OTG_CORE_ID_300A) && (hpcd->Init.dma_enable == 1U))
2526   {
2527     (void)USB_EP0_OutStart(hpcd->Instance, 1U, (uint8_t *)hpcd->Setup);
2528   }
2529 
2530   return HAL_OK;
2531 }
2532 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2533 
2534 #if defined (USB_DRD_FS)
2535 /**
2536   * @brief  This function handles PCD Endpoint interrupt request.
2537   * @param  hpcd PCD handle
2538   * @retval HAL status
2539   */
PCD_EP_ISR_Handler(PCD_HandleTypeDef * hpcd)2540 static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
2541 {
2542   PCD_EPTypeDef *ep;
2543   uint16_t count;
2544   uint16_t wIstr;
2545   uint16_t wEPVal;
2546   uint16_t TxPctSize;
2547   uint8_t epindex;
2548 
2549 #if (USE_USB_DOUBLE_BUFFER != 1U)
2550   count = 0U;
2551 #endif /* USE_USB_DOUBLE_BUFFER */
2552 
2553   /* stay in loop while pending interrupts */
2554   while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
2555   {
2556     wIstr = (uint16_t)hpcd->Instance->ISTR;
2557 
2558     /* extract highest priority endpoint number */
2559     epindex = (uint8_t)(wIstr & USB_ISTR_IDN);
2560 
2561     if (epindex == 0U)
2562     {
2563       /* Decode and service control endpoint interrupt */
2564 
2565       /* DIR bit = origin of the interrupt */
2566       if ((wIstr & USB_ISTR_DIR) == 0U)
2567       {
2568         /* DIR = 0 */
2569 
2570         /* DIR = 0 => IN  int */
2571         /* DIR = 0 implies that (EP_CTR_TX = 1) always */
2572         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
2573         ep = &hpcd->IN_ep[0];
2574 
2575         ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
2576         ep->xfer_buff += ep->xfer_count;
2577 
2578         /* TX COMPLETE */
2579 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2580         hpcd->DataInStageCallback(hpcd, 0U);
2581 #else
2582         HAL_PCD_DataInStageCallback(hpcd, 0U);
2583 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2584 
2585         if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
2586         {
2587           hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
2588           hpcd->USB_Address = 0U;
2589         }
2590       }
2591       else
2592       {
2593         /* DIR = 1 */
2594 
2595         /* DIR = 1 & CTR_RX => SETUP or OUT int */
2596         /* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
2597         ep = &hpcd->OUT_ep[0];
2598         wEPVal = (uint16_t)PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
2599 
2600         if ((wEPVal & USB_EP_SETUP) != 0U)
2601         {
2602           /* Get SETUP Packet */
2603           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
2604 
2605           USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
2606                       ep->pmaadress, (uint16_t)ep->xfer_count);
2607 
2608           /* SETUP bit kept frozen while CTR_RX = 1 */
2609           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
2610 
2611           /* Process SETUP Packet*/
2612 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2613           hpcd->SetupStageCallback(hpcd);
2614 #else
2615           HAL_PCD_SetupStageCallback(hpcd);
2616 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2617         }
2618         else if ((wEPVal & USB_EP_VTRX) != 0U)
2619         {
2620           PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
2621 
2622           /* Get Control Data OUT Packet */
2623           ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
2624 
2625           if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
2626           {
2627             USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
2628                         ep->pmaadress, (uint16_t)ep->xfer_count);
2629 
2630             ep->xfer_buff += ep->xfer_count;
2631 
2632             /* Process Control Data OUT Packet */
2633 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2634             hpcd->DataOutStageCallback(hpcd, 0U);
2635 #else
2636             HAL_PCD_DataOutStageCallback(hpcd, 0U);
2637 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2638           }
2639 
2640           wEPVal = (uint16_t)PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
2641 
2642           if (((wEPVal & USB_EP_SETUP) == 0U) && ((wEPVal & USB_EP_RX_STRX) != USB_EP_RX_VALID))
2643           {
2644             PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
2645             PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
2646           }
2647         }
2648       }
2649     }
2650     else
2651     {
2652       /* Decode and service non control endpoints interrupt */
2653       /* process related endpoint register */
2654       wEPVal = (uint16_t)PCD_GET_ENDPOINT(hpcd->Instance, epindex);
2655 
2656       if ((wEPVal & USB_EP_VTRX) != 0U)
2657       {
2658         /* clear int flag */
2659         PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
2660         ep = &hpcd->OUT_ep[epindex];
2661 
2662         /* OUT Single Buffering */
2663         if (ep->doublebuffer == 0U)
2664         {
2665           count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
2666 
2667           if (count != 0U)
2668           {
2669             USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
2670           }
2671         }
2672 #if (USE_USB_DOUBLE_BUFFER == 1U)
2673         else
2674         {
2675           /* manage double buffer bulk out */
2676           if (ep->type == EP_TYPE_BULK)
2677           {
2678             count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
2679           }
2680           else /* manage double buffer iso out */
2681           {
2682             /* free EP OUT Buffer */
2683             PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2684 
2685             if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
2686             {
2687               /* read from endpoint BUF0Addr buffer */
2688               count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2689 
2690               if (count != 0U)
2691               {
2692                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2693               }
2694             }
2695             else
2696             {
2697               /* read from endpoint BUF1Addr buffer */
2698               count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2699 
2700               if (count != 0U)
2701               {
2702                 USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2703               }
2704             }
2705           }
2706         }
2707 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2708 
2709         /* multi-packet on the NON control OUT endpoint */
2710         ep->xfer_count += count;
2711         ep->xfer_buff += count;
2712 
2713         if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
2714         {
2715           /* RX COMPLETE */
2716 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2717           hpcd->DataOutStageCallback(hpcd, ep->num);
2718 #else
2719           HAL_PCD_DataOutStageCallback(hpcd, ep->num);
2720 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2721         }
2722         else
2723         {
2724           (void)USB_EPStartXfer(hpcd->Instance, ep);
2725         }
2726       }
2727 
2728       if ((wEPVal & USB_EP_VTTX) != 0U)
2729       {
2730         ep = &hpcd->IN_ep[epindex];
2731 
2732         /* clear int flag */
2733         PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
2734 
2735         if (ep->type == EP_TYPE_ISOC)
2736         {
2737           ep->xfer_len = 0U;
2738 
2739 #if (USE_USB_DOUBLE_BUFFER == 1U)
2740           if (ep->doublebuffer != 0U)
2741           {
2742             if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2743             {
2744               PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2745             }
2746             else
2747             {
2748               PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2749             }
2750           }
2751 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2752 
2753           /* TX COMPLETE */
2754 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2755           hpcd->DataInStageCallback(hpcd, ep->num);
2756 #else
2757           HAL_PCD_DataInStageCallback(hpcd, ep->num);
2758 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2759         }
2760         else
2761         {
2762           /* Manage Single Buffer Transaction */
2763           if ((wEPVal & USB_EP_KIND) == 0U)
2764           {
2765             /* multi-packet on the NON control IN endpoint */
2766             TxPctSize = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
2767 
2768             if (ep->xfer_len > TxPctSize)
2769             {
2770               ep->xfer_len -= TxPctSize;
2771             }
2772             else
2773             {
2774               ep->xfer_len = 0U;
2775             }
2776 
2777             /* Zero Length Packet? */
2778             if (ep->xfer_len == 0U)
2779             {
2780               /* TX COMPLETE */
2781 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2782               hpcd->DataInStageCallback(hpcd, ep->num);
2783 #else
2784               HAL_PCD_DataInStageCallback(hpcd, ep->num);
2785 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2786             }
2787             else
2788             {
2789               /* Transfer is not yet Done */
2790               ep->xfer_buff += TxPctSize;
2791               ep->xfer_count += TxPctSize;
2792               (void)USB_EPStartXfer(hpcd->Instance, ep);
2793             }
2794           }
2795 #if (USE_USB_DOUBLE_BUFFER == 1U)
2796           /* Double Buffer bulk IN (bulk transfer Len > Ep_Mps) */
2797           else
2798           {
2799             (void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
2800           }
2801 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
2802         }
2803       }
2804     }
2805   }
2806 
2807   return HAL_OK;
2808 }
2809 
2810 
2811 #if (USE_USB_DOUBLE_BUFFER == 1U)
2812 /**
2813   * @brief  Manage double buffer bulk out transaction from ISR
2814   * @param  hpcd PCD handle
2815   * @param  ep current endpoint handle
2816   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
2817   * @retval HAL status
2818   */
HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)2819 static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
2820                                       PCD_EPTypeDef *ep, uint16_t wEPVal)
2821 {
2822   uint16_t count;
2823 
2824   /* Manage Buffer0 OUT */
2825   if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2826   {
2827     /* Get count of received Data on buffer0 */
2828     count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2829 
2830     if (ep->xfer_len >= count)
2831     {
2832       ep->xfer_len -= count;
2833     }
2834     else
2835     {
2836       ep->xfer_len = 0U;
2837     }
2838 
2839     if (ep->xfer_len == 0U)
2840     {
2841       /* set NAK to OUT endpoint since double buffer is enabled */
2842       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2843     }
2844 
2845     /* Check if Buffer1 is in blocked state which requires to toggle */
2846     if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2847     {
2848       PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2849     }
2850 
2851     if (count != 0U)
2852     {
2853       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
2854     }
2855   }
2856   /* Manage Buffer 1 DTOG_RX=0 */
2857   else
2858   {
2859     /* Get count of received data */
2860     count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2861 
2862     if (ep->xfer_len >= count)
2863     {
2864       ep->xfer_len -= count;
2865     }
2866     else
2867     {
2868       ep->xfer_len = 0U;
2869     }
2870 
2871     if (ep->xfer_len == 0U)
2872     {
2873       /* set NAK on the current endpoint */
2874       PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
2875     }
2876 
2877     /*Need to FreeUser Buffer*/
2878     if ((wEPVal & USB_EP_DTOG_TX) == 0U)
2879     {
2880       PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
2881     }
2882 
2883     if (count != 0U)
2884     {
2885       USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
2886     }
2887   }
2888 
2889   return count;
2890 }
2891 
2892 
2893 /**
2894   * @brief  Manage double buffer bulk IN transaction from ISR
2895   * @param  hpcd PCD handle
2896   * @param  ep current endpoint handle
2897   * @param  wEPVal Last snapshot of EPRx register value taken in ISR
2898   * @retval HAL status
2899   */
HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef * hpcd,PCD_EPTypeDef * ep,uint16_t wEPVal)2900 static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
2901                                                 PCD_EPTypeDef *ep, uint16_t wEPVal)
2902 {
2903   uint32_t len;
2904   uint16_t TxPctSize;
2905 
2906   /* Data Buffer0 ACK received */
2907   if ((wEPVal & USB_EP_DTOG_TX) != 0U)
2908   {
2909     /* multi-packet on the NON control IN endpoint */
2910     TxPctSize = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
2911 
2912     if (ep->xfer_len > TxPctSize)
2913     {
2914       ep->xfer_len -= TxPctSize;
2915     }
2916     else
2917     {
2918       ep->xfer_len = 0U;
2919     }
2920 
2921     /* Transfer is completed */
2922     if (ep->xfer_len == 0U)
2923     {
2924       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2925       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2926 
2927       /* TX COMPLETE */
2928 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2929       hpcd->DataInStageCallback(hpcd, ep->num);
2930 #else
2931       HAL_PCD_DataInStageCallback(hpcd, ep->num);
2932 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2933 
2934       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2935       {
2936         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2937       }
2938     }
2939     else /* Transfer is not yet Done */
2940     {
2941       /* need to Free USB Buff */
2942       if ((wEPVal & USB_EP_DTOG_RX) != 0U)
2943       {
2944         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
2945       }
2946 
2947       /* Still there is data to Fill in the next Buffer */
2948       if (ep->xfer_fill_db == 1U)
2949       {
2950         ep->xfer_buff += TxPctSize;
2951         ep->xfer_count += TxPctSize;
2952 
2953         /* Calculate the len of the new buffer to fill */
2954         if (ep->xfer_len_db >= ep->maxpacket)
2955         {
2956           len = ep->maxpacket;
2957           ep->xfer_len_db -= len;
2958         }
2959         else if (ep->xfer_len_db == 0U)
2960         {
2961           len = TxPctSize;
2962           ep->xfer_fill_db = 0U;
2963         }
2964         else
2965         {
2966           ep->xfer_fill_db = 0U;
2967           len = ep->xfer_len_db;
2968           ep->xfer_len_db = 0U;
2969         }
2970 
2971         /* Write remaining Data to Buffer */
2972         /* Set the Double buffer counter for pma buffer1 */
2973         PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
2974 
2975         /* Copy user buffer to USB PMA */
2976         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr0, (uint16_t)len);
2977       }
2978     }
2979   }
2980   else /* Data Buffer1 ACK received */
2981   {
2982     /* multi-packet on the NON control IN endpoint */
2983     TxPctSize = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
2984 
2985     if (ep->xfer_len >= TxPctSize)
2986     {
2987       ep->xfer_len -= TxPctSize;
2988     }
2989     else
2990     {
2991       ep->xfer_len = 0U;
2992     }
2993 
2994     /* Transfer is completed */
2995     if (ep->xfer_len == 0U)
2996     {
2997       PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2998       PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
2999 
3000       /* TX COMPLETE */
3001 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
3002       hpcd->DataInStageCallback(hpcd, ep->num);
3003 #else
3004       HAL_PCD_DataInStageCallback(hpcd, ep->num);
3005 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
3006 
3007       /* need to Free USB Buff */
3008       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
3009       {
3010         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
3011       }
3012     }
3013     else /* Transfer is not yet Done */
3014     {
3015       /* need to Free USB Buff */
3016       if ((wEPVal & USB_EP_DTOG_RX) == 0U)
3017       {
3018         PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
3019       }
3020 
3021       /* Still there is data to Fill in the next Buffer */
3022       if (ep->xfer_fill_db == 1U)
3023       {
3024         ep->xfer_buff += TxPctSize;
3025         ep->xfer_count += TxPctSize;
3026 
3027         /* Calculate the len of the new buffer to fill */
3028         if (ep->xfer_len_db >= ep->maxpacket)
3029         {
3030           len = ep->maxpacket;
3031           ep->xfer_len_db -= len;
3032         }
3033         else if (ep->xfer_len_db == 0U)
3034         {
3035           len = TxPctSize;
3036           ep->xfer_fill_db = 0U;
3037         }
3038         else
3039         {
3040           len = ep->xfer_len_db;
3041           ep->xfer_len_db = 0U;
3042           ep->xfer_fill_db = 0;
3043         }
3044 
3045         /* Set the Double buffer counter for pmabuffer1 */
3046         PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
3047 
3048         /* Copy the user buffer to USB PMA */
3049         USB_WritePMA(hpcd->Instance, ep->xfer_buff,  ep->pmaaddr1, (uint16_t)len);
3050       }
3051     }
3052   }
3053 
3054   /*enable endpoint IN*/
3055   PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
3056 
3057   return HAL_OK;
3058 }
3059 #endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
3060 #endif /* defined (USB_DRD_FS) */
3061 
3062 /**
3063   * @}
3064   */
3065 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) || defined (USB_DRD_FS) */
3066 #endif /* HAL_PCD_MODULE_ENABLED */
3067 /**
3068   * @}
3069   */
3070 
3071 /**
3072   * @}
3073   */
3074