2 ******************************************************************************
3 * @file stm32h7xx_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
14 ==============================================================================
15 ##### How to use this driver #####
16 ==============================================================================
18 The PCD HAL driver can be used as follows:
20 (#) Declare a PCD_HandleTypeDef handle structure, for example:
21 PCD_HandleTypeDef hpcd;
23 (#) Fill parameters of Init structure in HCD handle
25 (#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
27 (#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
28 (##) Enable the PCD/USB Low Level interface clock using
29 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
30 (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
32 (##) Initialize the related GPIO clocks
33 (##) Configure PCD pin-out
34 (##) Configure PCD NVIC interrupt
36 (#)Associate the Upper USB device stack to the HAL PCD Driver:
37 (##) hpcd.pData = pdev;
39 (#)Enable PCD transmission and reception:
43 ******************************************************************************
46 * <h2><center>© Copyright (c) 2017 STMicroelectronics.
47 * All rights reserved.</center></h2>
49 * This software component is licensed by ST under BSD 3-Clause license,
50 * the "License"; You may not use this file except in compliance with the
51 * License. You may obtain a copy of the License at:
52 * opensource.org/licenses/BSD-3-Clause
54 ******************************************************************************
57 /* Includes ------------------------------------------------------------------*/
58 #include "stm32h7xx_hal.h"
60 /** @addtogroup STM32H7xx_HAL_Driver
65 * @brief PCD HAL module driver
69 #ifdef HAL_PCD_MODULE_ENABLED
71 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
73 /* Private types -------------------------------------------------------------*/
74 /* Private variables ---------------------------------------------------------*/
75 /* Private constants ---------------------------------------------------------*/
76 /* Private macros ------------------------------------------------------------*/
77 /** @defgroup PCD_Private_Macros PCD Private Macros
80 #define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b))
81 #define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b))
86 /* Private functions prototypes ----------------------------------------------*/
87 /** @defgroup PCD_Private_Functions PCD Private Functions
90 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
91 static HAL_StatusTypeDef
PCD_WriteEmptyTxFifo(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
);
92 static HAL_StatusTypeDef
PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
);
93 static HAL_StatusTypeDef
PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
);
94 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
99 /* Exported functions --------------------------------------------------------*/
100 /** @defgroup PCD_Exported_Functions PCD Exported Functions
104 /** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
105 * @brief Initialization and Configuration functions
108 ===============================================================================
109 ##### Initialization and de-initialization functions #####
110 ===============================================================================
111 [..] This section provides functions allowing to:
118 * @brief Initializes the PCD according to the specified
119 * parameters in the PCD_InitTypeDef and initialize the associated handle.
120 * @param hpcd PCD handle
123 HAL_StatusTypeDef
HAL_PCD_Init(PCD_HandleTypeDef
*hpcd
)
125 USB_OTG_GlobalTypeDef
*USBx
;
128 /* Check the PCD handle allocation */
134 /* Check the parameters */
135 assert_param(IS_PCD_ALL_INSTANCE(hpcd
->Instance
));
137 USBx
= hpcd
->Instance
;
139 if (hpcd
->State
== HAL_PCD_STATE_RESET
)
141 /* Allocate lock resource and initialize it */
142 hpcd
->Lock
= HAL_UNLOCKED
;
144 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
145 hpcd
->SOFCallback
= HAL_PCD_SOFCallback
;
146 hpcd
->SetupStageCallback
= HAL_PCD_SetupStageCallback
;
147 hpcd
->ResetCallback
= HAL_PCD_ResetCallback
;
148 hpcd
->SuspendCallback
= HAL_PCD_SuspendCallback
;
149 hpcd
->ResumeCallback
= HAL_PCD_ResumeCallback
;
150 hpcd
->ConnectCallback
= HAL_PCD_ConnectCallback
;
151 hpcd
->DisconnectCallback
= HAL_PCD_DisconnectCallback
;
152 hpcd
->DataOutStageCallback
= HAL_PCD_DataOutStageCallback
;
153 hpcd
->DataInStageCallback
= HAL_PCD_DataInStageCallback
;
154 hpcd
->ISOOUTIncompleteCallback
= HAL_PCD_ISOOUTIncompleteCallback
;
155 hpcd
->ISOINIncompleteCallback
= HAL_PCD_ISOINIncompleteCallback
;
156 hpcd
->LPMCallback
= HAL_PCDEx_LPM_Callback
;
157 hpcd
->BCDCallback
= HAL_PCDEx_BCD_Callback
;
159 if (hpcd
->MspInitCallback
== NULL
)
161 hpcd
->MspInitCallback
= HAL_PCD_MspInit
;
164 /* Init the low level hardware */
165 hpcd
->MspInitCallback(hpcd
);
167 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
168 HAL_PCD_MspInit(hpcd
);
169 #endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
172 hpcd
->State
= HAL_PCD_STATE_BUSY
;
174 /* Disable DMA mode for FS instance */
175 if ((USBx
->CID
& (0x1U
<< 8)) == 0U)
177 hpcd
->Init
.dma_enable
= 0U;
180 /* Disable the Interrupts */
181 __HAL_PCD_DISABLE(hpcd
);
183 /*Init the Core (common init.) */
184 if (USB_CoreInit(hpcd
->Instance
, hpcd
->Init
) != HAL_OK
)
186 hpcd
->State
= HAL_PCD_STATE_ERROR
;
190 /* Force Device Mode*/
191 (void)USB_SetCurrentMode(hpcd
->Instance
, USB_DEVICE_MODE
);
193 /* Init endpoints structures */
194 for (i
= 0U; i
< hpcd
->Init
.dev_endpoints
; i
++)
196 /* Init ep structure */
197 hpcd
->IN_ep
[i
].is_in
= 1U;
198 hpcd
->IN_ep
[i
].num
= i
;
199 hpcd
->IN_ep
[i
].tx_fifo_num
= i
;
200 /* Control until ep is activated */
201 hpcd
->IN_ep
[i
].type
= EP_TYPE_CTRL
;
202 hpcd
->IN_ep
[i
].maxpacket
= 0U;
203 hpcd
->IN_ep
[i
].xfer_buff
= 0U;
204 hpcd
->IN_ep
[i
].xfer_len
= 0U;
207 for (i
= 0U; i
< hpcd
->Init
.dev_endpoints
; i
++)
209 hpcd
->OUT_ep
[i
].is_in
= 0U;
210 hpcd
->OUT_ep
[i
].num
= i
;
211 /* Control until ep is activated */
212 hpcd
->OUT_ep
[i
].type
= EP_TYPE_CTRL
;
213 hpcd
->OUT_ep
[i
].maxpacket
= 0U;
214 hpcd
->OUT_ep
[i
].xfer_buff
= 0U;
215 hpcd
->OUT_ep
[i
].xfer_len
= 0U;
219 if (USB_DevInit(hpcd
->Instance
, hpcd
->Init
) != HAL_OK
)
221 hpcd
->State
= HAL_PCD_STATE_ERROR
;
225 hpcd
->USB_Address
= 0U;
226 hpcd
->State
= HAL_PCD_STATE_READY
;
229 if (hpcd
->Init
.lpm_enable
== 1U)
231 (void)HAL_PCDEx_ActivateLPM(hpcd
);
234 (void)USB_DevDisconnect(hpcd
->Instance
);
240 * @brief DeInitializes the PCD peripheral.
241 * @param hpcd PCD handle
244 HAL_StatusTypeDef
HAL_PCD_DeInit(PCD_HandleTypeDef
*hpcd
)
246 /* Check the PCD handle allocation */
252 hpcd
->State
= HAL_PCD_STATE_BUSY
;
255 (void)HAL_PCD_Stop(hpcd
);
257 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
258 if (hpcd
->MspDeInitCallback
== NULL
)
260 hpcd
->MspDeInitCallback
= HAL_PCD_MspDeInit
; /* Legacy weak MspDeInit */
263 /* DeInit the low level hardware */
264 hpcd
->MspDeInitCallback(hpcd
);
266 /* DeInit the low level hardware: CLOCK, NVIC.*/
267 HAL_PCD_MspDeInit(hpcd
);
268 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
270 hpcd
->State
= HAL_PCD_STATE_RESET
;
276 * @brief Initializes the PCD MSP.
277 * @param hpcd PCD handle
280 __weak
void HAL_PCD_MspInit(PCD_HandleTypeDef
*hpcd
)
282 /* Prevent unused argument(s) compilation warning */
285 /* NOTE : This function should not be modified, when the callback is needed,
286 the HAL_PCD_MspInit could be implemented in the user file
291 * @brief DeInitializes PCD MSP.
292 * @param hpcd PCD handle
295 __weak
void HAL_PCD_MspDeInit(PCD_HandleTypeDef
*hpcd
)
297 /* Prevent unused argument(s) compilation warning */
300 /* NOTE : This function should not be modified, when the callback is needed,
301 the HAL_PCD_MspDeInit could be implemented in the user file
305 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
307 * @brief Register a User USB PCD Callback
308 * To be used instead of the weak predefined callback
309 * @param hpcd USB PCD handle
310 * @param CallbackID ID of the callback to be registered
311 * This parameter can be one of the following values:
312 * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
313 * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
314 * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
315 * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
316 * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
317 * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
318 * @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
319 * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
320 * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
321 * @param pCallback pointer to the Callback function
324 HAL_StatusTypeDef
HAL_PCD_RegisterCallback(PCD_HandleTypeDef
*hpcd
, HAL_PCD_CallbackIDTypeDef CallbackID
, pPCD_CallbackTypeDef pCallback
)
326 HAL_StatusTypeDef status
= HAL_OK
;
328 if (pCallback
== NULL
)
330 /* Update the error code */
331 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
337 if (hpcd
->State
== HAL_PCD_STATE_READY
)
341 case HAL_PCD_SOF_CB_ID
:
342 hpcd
->SOFCallback
= pCallback
;
345 case HAL_PCD_SETUPSTAGE_CB_ID
:
346 hpcd
->SetupStageCallback
= pCallback
;
349 case HAL_PCD_RESET_CB_ID
:
350 hpcd
->ResetCallback
= pCallback
;
353 case HAL_PCD_SUSPEND_CB_ID
:
354 hpcd
->SuspendCallback
= pCallback
;
357 case HAL_PCD_RESUME_CB_ID
:
358 hpcd
->ResumeCallback
= pCallback
;
361 case HAL_PCD_CONNECT_CB_ID
:
362 hpcd
->ConnectCallback
= pCallback
;
365 case HAL_PCD_DISCONNECT_CB_ID
:
366 hpcd
->DisconnectCallback
= pCallback
;
369 case HAL_PCD_MSPINIT_CB_ID
:
370 hpcd
->MspInitCallback
= pCallback
;
373 case HAL_PCD_MSPDEINIT_CB_ID
:
374 hpcd
->MspDeInitCallback
= pCallback
;
378 /* Update the error code */
379 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
380 /* Return error status */
385 else if (hpcd
->State
== HAL_PCD_STATE_RESET
)
389 case HAL_PCD_MSPINIT_CB_ID
:
390 hpcd
->MspInitCallback
= pCallback
;
393 case HAL_PCD_MSPDEINIT_CB_ID
:
394 hpcd
->MspDeInitCallback
= pCallback
;
398 /* Update the error code */
399 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
400 /* Return error status */
407 /* Update the error code */
408 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
409 /* Return error status */
419 * @brief Unregister an USB PCD Callback
420 * USB PCD callabck is redirected to the weak predefined callback
421 * @param hpcd USB PCD handle
422 * @param CallbackID ID of the callback to be unregistered
423 * This parameter can be one of the following values:
424 * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
425 * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
426 * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
427 * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
428 * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
429 * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
430 * @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
431 * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
432 * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
435 HAL_StatusTypeDef
HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef
*hpcd
, HAL_PCD_CallbackIDTypeDef CallbackID
)
437 HAL_StatusTypeDef status
= HAL_OK
;
442 /* Setup Legacy weak Callbacks */
443 if (hpcd
->State
== HAL_PCD_STATE_READY
)
447 case HAL_PCD_SOF_CB_ID
:
448 hpcd
->SOFCallback
= HAL_PCD_SOFCallback
;
451 case HAL_PCD_SETUPSTAGE_CB_ID
:
452 hpcd
->SetupStageCallback
= HAL_PCD_SetupStageCallback
;
455 case HAL_PCD_RESET_CB_ID
:
456 hpcd
->ResetCallback
= HAL_PCD_ResetCallback
;
459 case HAL_PCD_SUSPEND_CB_ID
:
460 hpcd
->SuspendCallback
= HAL_PCD_SuspendCallback
;
463 case HAL_PCD_RESUME_CB_ID
:
464 hpcd
->ResumeCallback
= HAL_PCD_ResumeCallback
;
467 case HAL_PCD_CONNECT_CB_ID
:
468 hpcd
->ConnectCallback
= HAL_PCD_ConnectCallback
;
471 case HAL_PCD_DISCONNECT_CB_ID
:
472 hpcd
->DisconnectCallback
= HAL_PCD_DisconnectCallback
;
475 case HAL_PCD_MSPINIT_CB_ID
:
476 hpcd
->MspInitCallback
= HAL_PCD_MspInit
;
479 case HAL_PCD_MSPDEINIT_CB_ID
:
480 hpcd
->MspDeInitCallback
= HAL_PCD_MspDeInit
;
484 /* Update the error code */
485 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
487 /* Return error status */
492 else if (hpcd
->State
== HAL_PCD_STATE_RESET
)
496 case HAL_PCD_MSPINIT_CB_ID
:
497 hpcd
->MspInitCallback
= HAL_PCD_MspInit
;
500 case HAL_PCD_MSPDEINIT_CB_ID
:
501 hpcd
->MspDeInitCallback
= HAL_PCD_MspDeInit
;
505 /* Update the error code */
506 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
508 /* Return error status */
515 /* Update the error code */
516 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
518 /* Return error status */
528 * @brief Register USB PCD Data OUT Stage Callback
529 * To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
530 * @param hpcd PCD handle
531 * @param pCallback pointer to the USB PCD Data OUT Stage Callback function
534 HAL_StatusTypeDef
HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef
*hpcd
, pPCD_DataOutStageCallbackTypeDef pCallback
)
536 HAL_StatusTypeDef status
= HAL_OK
;
538 if (pCallback
== NULL
)
540 /* Update the error code */
541 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
549 if (hpcd
->State
== HAL_PCD_STATE_READY
)
551 hpcd
->DataOutStageCallback
= pCallback
;
555 /* Update the error code */
556 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
558 /* Return error status */
569 * @brief UnRegister the USB PCD Data OUT Stage Callback
570 * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
571 * @param hpcd PCD handle
574 HAL_StatusTypeDef
HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef
*hpcd
)
576 HAL_StatusTypeDef status
= HAL_OK
;
581 if (hpcd
->State
== HAL_PCD_STATE_READY
)
583 hpcd
->DataOutStageCallback
= HAL_PCD_DataOutStageCallback
; /* Legacy weak DataOutStageCallback */
587 /* Update the error code */
588 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
590 /* Return error status */
601 * @brief Register USB PCD Data IN Stage Callback
602 * To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
603 * @param hpcd PCD handle
604 * @param pCallback pointer to the USB PCD Data IN Stage Callback function
607 HAL_StatusTypeDef
HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef
*hpcd
, pPCD_DataInStageCallbackTypeDef pCallback
)
609 HAL_StatusTypeDef status
= HAL_OK
;
611 if (pCallback
== NULL
)
613 /* Update the error code */
614 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
622 if (hpcd
->State
== HAL_PCD_STATE_READY
)
624 hpcd
->DataInStageCallback
= pCallback
;
628 /* Update the error code */
629 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
631 /* Return error status */
642 * @brief UnRegister the USB PCD Data IN Stage Callback
643 * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
644 * @param hpcd PCD handle
647 HAL_StatusTypeDef
HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef
*hpcd
)
649 HAL_StatusTypeDef status
= HAL_OK
;
654 if (hpcd
->State
== HAL_PCD_STATE_READY
)
656 hpcd
->DataInStageCallback
= HAL_PCD_DataInStageCallback
; /* Legacy weak DataInStageCallback */
660 /* Update the error code */
661 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
663 /* Return error status */
674 * @brief Register USB PCD Iso OUT incomplete Callback
675 * To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
676 * @param hpcd PCD handle
677 * @param pCallback pointer to the USB PCD Iso OUT incomplete Callback function
680 HAL_StatusTypeDef
HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef
*hpcd
, pPCD_IsoOutIncpltCallbackTypeDef pCallback
)
682 HAL_StatusTypeDef status
= HAL_OK
;
684 if (pCallback
== NULL
)
686 /* Update the error code */
687 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
695 if (hpcd
->State
== HAL_PCD_STATE_READY
)
697 hpcd
->ISOOUTIncompleteCallback
= pCallback
;
701 /* Update the error code */
702 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
704 /* Return error status */
715 * @brief UnRegister the USB PCD Iso OUT incomplete Callback
716 * USB PCD Iso OUT incomplete Callback is redirected to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
717 * @param hpcd PCD handle
720 HAL_StatusTypeDef
HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef
*hpcd
)
722 HAL_StatusTypeDef status
= HAL_OK
;
727 if (hpcd
->State
== HAL_PCD_STATE_READY
)
729 hpcd
->ISOOUTIncompleteCallback
= HAL_PCD_ISOOUTIncompleteCallback
; /* Legacy weak ISOOUTIncompleteCallback */
733 /* Update the error code */
734 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
736 /* Return error status */
747 * @brief Register USB PCD Iso IN incomplete Callback
748 * To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
749 * @param hpcd PCD handle
750 * @param pCallback pointer to the USB PCD Iso IN incomplete Callback function
753 HAL_StatusTypeDef
HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef
*hpcd
, pPCD_IsoInIncpltCallbackTypeDef pCallback
)
755 HAL_StatusTypeDef status
= HAL_OK
;
757 if (pCallback
== NULL
)
759 /* Update the error code */
760 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
768 if (hpcd
->State
== HAL_PCD_STATE_READY
)
770 hpcd
->ISOINIncompleteCallback
= pCallback
;
774 /* Update the error code */
775 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
777 /* Return error status */
788 * @brief UnRegister the USB PCD Iso IN incomplete Callback
789 * USB PCD Iso IN incomplete Callback is redirected to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
790 * @param hpcd PCD handle
793 HAL_StatusTypeDef
HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef
*hpcd
)
795 HAL_StatusTypeDef status
= HAL_OK
;
800 if (hpcd
->State
== HAL_PCD_STATE_READY
)
802 hpcd
->ISOINIncompleteCallback
= HAL_PCD_ISOINIncompleteCallback
; /* Legacy weak ISOINIncompleteCallback */
806 /* Update the error code */
807 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
809 /* Return error status */
820 * @brief Register USB PCD BCD Callback
821 * To be used instead of the weak HAL_PCDEx_BCD_Callback() predefined callback
822 * @param hpcd PCD handle
823 * @param pCallback pointer to the USB PCD BCD Callback function
826 HAL_StatusTypeDef
HAL_PCD_RegisterBcdCallback(PCD_HandleTypeDef
*hpcd
, pPCD_BcdCallbackTypeDef pCallback
)
828 HAL_StatusTypeDef status
= HAL_OK
;
830 if (pCallback
== NULL
)
832 /* Update the error code */
833 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
841 if (hpcd
->State
== HAL_PCD_STATE_READY
)
843 hpcd
->BCDCallback
= pCallback
;
847 /* Update the error code */
848 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
850 /* Return error status */
861 * @brief UnRegister the USB PCD BCD Callback
862 * USB BCD Callback is redirected to the weak HAL_PCDEx_BCD_Callback() predefined callback
863 * @param hpcd PCD handle
866 HAL_StatusTypeDef
HAL_PCD_UnRegisterBcdCallback(PCD_HandleTypeDef
*hpcd
)
868 HAL_StatusTypeDef status
= HAL_OK
;
873 if (hpcd
->State
== HAL_PCD_STATE_READY
)
875 hpcd
->BCDCallback
= HAL_PCDEx_BCD_Callback
; /* Legacy weak HAL_PCDEx_BCD_Callback */
879 /* Update the error code */
880 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
882 /* Return error status */
893 * @brief Register USB PCD LPM Callback
894 * To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
895 * @param hpcd PCD handle
896 * @param pCallback pointer to the USB PCD LPM Callback function
899 HAL_StatusTypeDef
HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef
*hpcd
, pPCD_LpmCallbackTypeDef pCallback
)
901 HAL_StatusTypeDef status
= HAL_OK
;
903 if (pCallback
== NULL
)
905 /* Update the error code */
906 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
914 if (hpcd
->State
== HAL_PCD_STATE_READY
)
916 hpcd
->LPMCallback
= pCallback
;
920 /* Update the error code */
921 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
923 /* Return error status */
934 * @brief UnRegister the USB PCD LPM Callback
935 * USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
936 * @param hpcd PCD handle
939 HAL_StatusTypeDef
HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef
*hpcd
)
941 HAL_StatusTypeDef status
= HAL_OK
;
946 if (hpcd
->State
== HAL_PCD_STATE_READY
)
948 hpcd
->LPMCallback
= HAL_PCDEx_LPM_Callback
; /* Legacy weak HAL_PCDEx_LPM_Callback */
952 /* Update the error code */
953 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
955 /* Return error status */
964 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
970 /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
971 * @brief Data transfers functions
974 ===============================================================================
975 ##### IO operation functions #####
976 ===============================================================================
978 This subsection provides a set of functions allowing to manage the PCD data
986 * @brief Start the USB device
987 * @param hpcd PCD handle
990 HAL_StatusTypeDef
HAL_PCD_Start(PCD_HandleTypeDef
*hpcd
)
992 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
993 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
994 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
997 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
998 if ((hpcd
->Init
.battery_charging_enable
== 1U) &&
999 (hpcd
->Init
.phy_itface
!= USB_OTG_ULPI_PHY
))
1001 /* Enable USB Transceiver */
1002 USBx
->GCCFG
|= USB_OTG_GCCFG_PWRDWN
;
1004 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1005 (void)USB_DevConnect(hpcd
->Instance
);
1006 __HAL_PCD_ENABLE(hpcd
);
1012 * @brief Stop the USB device.
1013 * @param hpcd PCD handle
1014 * @retval HAL status
1016 HAL_StatusTypeDef
HAL_PCD_Stop(PCD_HandleTypeDef
*hpcd
)
1019 __HAL_PCD_DISABLE(hpcd
);
1021 if (USB_StopDevice(hpcd
->Instance
) != HAL_OK
)
1027 (void)USB_DevDisconnect(hpcd
->Instance
);
1032 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1034 * @brief Handles PCD interrupt request.
1035 * @param hpcd PCD handle
1036 * @retval HAL status
1038 void HAL_PCD_IRQHandler(PCD_HandleTypeDef
*hpcd
)
1040 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
1041 uint32_t USBx_BASE
= (uint32_t)USBx
;
1042 uint32_t i
, ep_intr
, epint
, epnum
;
1043 uint32_t fifoemptymsk
, temp
;
1044 USB_OTG_EPTypeDef
*ep
;
1046 /* ensure that we are in device mode */
1047 if (USB_GetMode(hpcd
->Instance
) == USB_OTG_MODE_DEVICE
)
1049 /* avoid spurious interrupt */
1050 if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd
))
1055 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_MMIS
))
1057 /* incorrect mode, acknowledge the interrupt */
1058 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_MMIS
);
1061 /* Handle RxQLevel Interrupt */
1062 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_RXFLVL
))
1064 USB_MASK_INTERRUPT(hpcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
1066 temp
= USBx
->GRXSTSP
;
1068 ep
= &hpcd
->OUT_ep
[temp
& USB_OTG_GRXSTSP_EPNUM
];
1070 if (((temp
& USB_OTG_GRXSTSP_PKTSTS
) >> 17) == STS_DATA_UPDT
)
1072 if ((temp
& USB_OTG_GRXSTSP_BCNT
) != 0U)
1074 (void)USB_ReadPacket(USBx
, ep
->xfer_buff
,
1075 (uint16_t)((temp
& USB_OTG_GRXSTSP_BCNT
) >> 4));
1077 ep
->xfer_buff
+= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1078 ep
->xfer_count
+= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1081 else if (((temp
& USB_OTG_GRXSTSP_PKTSTS
) >> 17) == STS_SETUP_UPDT
)
1083 (void)USB_ReadPacket(USBx
, (uint8_t *)hpcd
->Setup
, 8U);
1084 ep
->xfer_count
+= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1090 USB_UNMASK_INTERRUPT(hpcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
1093 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_OEPINT
))
1097 /* Read in the device interrupt bits */
1098 ep_intr
= USB_ReadDevAllOutEpInterrupt(hpcd
->Instance
);
1100 while (ep_intr
!= 0U)
1102 if ((ep_intr
& 0x1U
) != 0U)
1104 epint
= USB_ReadDevOutEPInterrupt(hpcd
->Instance
, (uint8_t)epnum
);
1106 if ((epint
& USB_OTG_DOEPINT_XFRC
) == USB_OTG_DOEPINT_XFRC
)
1108 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_XFRC
);
1109 (void)PCD_EP_OutXfrComplete_int(hpcd
, epnum
);
1112 if ((epint
& USB_OTG_DOEPINT_STUP
) == USB_OTG_DOEPINT_STUP
)
1114 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STUP
);
1115 /* Class B setup phase done for previous decoded setup */
1116 (void)PCD_EP_OutSetupPacket_int(hpcd
, epnum
);
1119 if ((epint
& USB_OTG_DOEPINT_OTEPDIS
) == USB_OTG_DOEPINT_OTEPDIS
)
1121 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_OTEPDIS
);
1124 /* Clear Status Phase Received interrupt */
1125 if ((epint
& USB_OTG_DOEPINT_OTEPSPR
) == USB_OTG_DOEPINT_OTEPSPR
)
1127 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_OTEPSPR
);
1130 /* Clear OUT NAK interrupt */
1131 if ((epint
& USB_OTG_DOEPINT_NAK
) == USB_OTG_DOEPINT_NAK
)
1133 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_NAK
);
1141 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_IEPINT
))
1143 /* Read in the device interrupt bits */
1144 ep_intr
= USB_ReadDevAllInEpInterrupt(hpcd
->Instance
);
1148 while (ep_intr
!= 0U)
1150 if ((ep_intr
& 0x1U
) != 0U) /* In ITR */
1152 epint
= USB_ReadDevInEPInterrupt(hpcd
->Instance
, (uint8_t)epnum
);
1154 if ((epint
& USB_OTG_DIEPINT_XFRC
) == USB_OTG_DIEPINT_XFRC
)
1156 fifoemptymsk
= (uint32_t)(0x1UL
<< (epnum
& EP_ADDR_MSK
));
1157 USBx_DEVICE
->DIEPEMPMSK
&= ~fifoemptymsk
;
1159 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_XFRC
);
1161 if (hpcd
->Init
.dma_enable
== 1U)
1163 hpcd
->IN_ep
[epnum
].xfer_buff
+= hpcd
->IN_ep
[epnum
].maxpacket
;
1165 /* this is ZLP, so prepare EP0 for next setup */
1166 if ((epnum
== 0U) && (hpcd
->IN_ep
[epnum
].xfer_len
== 0U))
1168 /* prepare to rx more setup packets */
1169 (void)USB_EP0_OutStart(hpcd
->Instance
, 1U, (uint8_t *)hpcd
->Setup
);
1173 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1174 hpcd
->DataInStageCallback(hpcd
, (uint8_t)epnum
);
1176 HAL_PCD_DataInStageCallback(hpcd
, (uint8_t)epnum
);
1177 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1179 if ((epint
& USB_OTG_DIEPINT_TOC
) == USB_OTG_DIEPINT_TOC
)
1181 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_TOC
);
1183 if ((epint
& USB_OTG_DIEPINT_ITTXFE
) == USB_OTG_DIEPINT_ITTXFE
)
1185 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_ITTXFE
);
1187 if ((epint
& USB_OTG_DIEPINT_INEPNE
) == USB_OTG_DIEPINT_INEPNE
)
1189 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_INEPNE
);
1191 if ((epint
& USB_OTG_DIEPINT_EPDISD
) == USB_OTG_DIEPINT_EPDISD
)
1193 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_EPDISD
);
1195 if ((epint
& USB_OTG_DIEPINT_TXFE
) == USB_OTG_DIEPINT_TXFE
)
1197 (void)PCD_WriteEmptyTxFifo(hpcd
, epnum
);
1205 /* Handle Resume Interrupt */
1206 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_WKUINT
))
1208 /* Clear the Remote Wake-up Signaling */
1209 USBx_DEVICE
->DCTL
&= ~USB_OTG_DCTL_RWUSIG
;
1211 if (hpcd
->LPM_State
== LPM_L1
)
1213 hpcd
->LPM_State
= LPM_L0
;
1215 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1216 hpcd
->LPMCallback(hpcd
, PCD_LPM_L0_ACTIVE
);
1218 HAL_PCDEx_LPM_Callback(hpcd
, PCD_LPM_L0_ACTIVE
);
1219 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1223 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1224 hpcd
->ResumeCallback(hpcd
);
1226 HAL_PCD_ResumeCallback(hpcd
);
1227 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1230 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_WKUINT
);
1233 /* Handle Suspend Interrupt */
1234 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_USBSUSP
))
1236 if ((USBx_DEVICE
->DSTS
& USB_OTG_DSTS_SUSPSTS
) == USB_OTG_DSTS_SUSPSTS
)
1238 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1239 hpcd
->SuspendCallback(hpcd
);
1241 HAL_PCD_SuspendCallback(hpcd
);
1242 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1244 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_USBSUSP
);
1247 /* Handle LPM Interrupt */
1248 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_LPMINT
))
1250 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_LPMINT
);
1252 if (hpcd
->LPM_State
== LPM_L0
)
1254 hpcd
->LPM_State
= LPM_L1
;
1255 hpcd
->BESL
= (hpcd
->Instance
->GLPMCFG
& USB_OTG_GLPMCFG_BESL
) >> 2U;
1257 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1258 hpcd
->LPMCallback(hpcd
, PCD_LPM_L1_ACTIVE
);
1260 HAL_PCDEx_LPM_Callback(hpcd
, PCD_LPM_L1_ACTIVE
);
1261 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1265 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1266 hpcd
->SuspendCallback(hpcd
);
1268 HAL_PCD_SuspendCallback(hpcd
);
1269 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1273 /* Handle Reset Interrupt */
1274 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_USBRST
))
1276 USBx_DEVICE
->DCTL
&= ~USB_OTG_DCTL_RWUSIG
;
1277 (void)USB_FlushTxFifo(hpcd
->Instance
, 0x10U
);
1279 for (i
= 0U; i
< hpcd
->Init
.dev_endpoints
; i
++)
1281 USBx_INEP(i
)->DIEPINT
= 0xFB7FU
;
1282 USBx_INEP(i
)->DIEPCTL
&= ~USB_OTG_DIEPCTL_STALL
;
1283 USBx_INEP(i
)->DIEPCTL
|= USB_OTG_DIEPCTL_SNAK
;
1284 USBx_OUTEP(i
)->DOEPINT
= 0xFB7FU
;
1285 USBx_OUTEP(i
)->DOEPCTL
&= ~USB_OTG_DOEPCTL_STALL
;
1286 USBx_OUTEP(i
)->DOEPCTL
|= USB_OTG_DOEPCTL_SNAK
;
1288 USBx_DEVICE
->DAINTMSK
|= 0x10001U
;
1290 if (hpcd
->Init
.use_dedicated_ep1
!= 0U)
1292 USBx_DEVICE
->DOUTEP1MSK
|= USB_OTG_DOEPMSK_STUPM
|
1293 USB_OTG_DOEPMSK_XFRCM
|
1294 USB_OTG_DOEPMSK_EPDM
;
1296 USBx_DEVICE
->DINEP1MSK
|= USB_OTG_DIEPMSK_TOM
|
1297 USB_OTG_DIEPMSK_XFRCM
|
1298 USB_OTG_DIEPMSK_EPDM
;
1302 USBx_DEVICE
->DOEPMSK
|= USB_OTG_DOEPMSK_STUPM
|
1303 USB_OTG_DOEPMSK_XFRCM
|
1304 USB_OTG_DOEPMSK_EPDM
|
1305 USB_OTG_DOEPMSK_OTEPSPRM
|
1306 USB_OTG_DOEPMSK_NAKM
;
1308 USBx_DEVICE
->DIEPMSK
|= USB_OTG_DIEPMSK_TOM
|
1309 USB_OTG_DIEPMSK_XFRCM
|
1310 USB_OTG_DIEPMSK_EPDM
;
1313 /* Set Default Address to 0 */
1314 USBx_DEVICE
->DCFG
&= ~USB_OTG_DCFG_DAD
;
1316 /* setup EP0 to receive SETUP packets */
1317 (void)USB_EP0_OutStart(hpcd
->Instance
, (uint8_t)hpcd
->Init
.dma_enable
,
1318 (uint8_t *)hpcd
->Setup
);
1320 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_USBRST
);
1323 /* Handle Enumeration done Interrupt */
1324 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_ENUMDNE
))
1326 (void)USB_ActivateSetup(hpcd
->Instance
);
1327 hpcd
->Init
.speed
= USB_GetDevSpeed(hpcd
->Instance
);
1329 /* Set USB Turnaround time */
1330 (void)USB_SetTurnaroundTime(hpcd
->Instance
,
1331 HAL_RCC_GetHCLKFreq(),
1332 (uint8_t)hpcd
->Init
.speed
);
1334 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1335 hpcd
->ResetCallback(hpcd
);
1337 HAL_PCD_ResetCallback(hpcd
);
1338 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1340 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_ENUMDNE
);
1343 /* Handle SOF Interrupt */
1344 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_SOF
))
1346 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1347 hpcd
->SOFCallback(hpcd
);
1349 HAL_PCD_SOFCallback(hpcd
);
1350 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1352 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_SOF
);
1355 /* Handle Incomplete ISO IN Interrupt */
1356 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_IISOIXFR
))
1358 /* Keep application checking the corresponding Iso IN endpoint
1359 causing the incomplete Interrupt */
1362 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1363 hpcd
->ISOINIncompleteCallback(hpcd
, (uint8_t)epnum
);
1365 HAL_PCD_ISOINIncompleteCallback(hpcd
, (uint8_t)epnum
);
1366 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1368 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_IISOIXFR
);
1371 /* Handle Incomplete ISO OUT Interrupt */
1372 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
))
1374 /* Keep application checking the corresponding Iso OUT endpoint
1375 causing the incomplete Interrupt */
1378 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1379 hpcd
->ISOOUTIncompleteCallback(hpcd
, (uint8_t)epnum
);
1381 HAL_PCD_ISOOUTIncompleteCallback(hpcd
, (uint8_t)epnum
);
1382 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1384 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
);
1387 /* Handle Connection event Interrupt */
1388 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_SRQINT
))
1390 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1391 hpcd
->ConnectCallback(hpcd
);
1393 HAL_PCD_ConnectCallback(hpcd
);
1394 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1396 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_SRQINT
);
1399 /* Handle Disconnection event Interrupt */
1400 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_OTGINT
))
1402 temp
= hpcd
->Instance
->GOTGINT
;
1404 if ((temp
& USB_OTG_GOTGINT_SEDET
) == USB_OTG_GOTGINT_SEDET
)
1406 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1407 hpcd
->DisconnectCallback(hpcd
);
1409 HAL_PCD_DisconnectCallback(hpcd
);
1410 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1412 hpcd
->Instance
->GOTGINT
|= temp
;
1416 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1420 * @brief Data OUT stage callback.
1421 * @param hpcd PCD handle
1422 * @param epnum endpoint number
1425 __weak
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef
*hpcd
, uint8_t epnum
)
1427 /* Prevent unused argument(s) compilation warning */
1431 /* NOTE : This function should not be modified, when the callback is needed,
1432 the HAL_PCD_DataOutStageCallback could be implemented in the user file
1437 * @brief Data IN stage callback
1438 * @param hpcd PCD handle
1439 * @param epnum endpoint number
1442 __weak
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef
*hpcd
, uint8_t epnum
)
1444 /* Prevent unused argument(s) compilation warning */
1448 /* NOTE : This function should not be modified, when the callback is needed,
1449 the HAL_PCD_DataInStageCallback could be implemented in the user file
1453 * @brief Setup stage callback
1454 * @param hpcd PCD handle
1457 __weak
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef
*hpcd
)
1459 /* Prevent unused argument(s) compilation warning */
1462 /* NOTE : This function should not be modified, when the callback is needed,
1463 the HAL_PCD_SetupStageCallback could be implemented in the user file
1468 * @brief USB Start Of Frame callback.
1469 * @param hpcd PCD handle
1472 __weak
void HAL_PCD_SOFCallback(PCD_HandleTypeDef
*hpcd
)
1474 /* Prevent unused argument(s) compilation warning */
1477 /* NOTE : This function should not be modified, when the callback is needed,
1478 the HAL_PCD_SOFCallback could be implemented in the user file
1483 * @brief USB Reset callback.
1484 * @param hpcd PCD handle
1487 __weak
void HAL_PCD_ResetCallback(PCD_HandleTypeDef
*hpcd
)
1489 /* Prevent unused argument(s) compilation warning */
1492 /* NOTE : This function should not be modified, when the callback is needed,
1493 the HAL_PCD_ResetCallback could be implemented in the user file
1498 * @brief Suspend event callback.
1499 * @param hpcd PCD handle
1502 __weak
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef
*hpcd
)
1504 /* Prevent unused argument(s) compilation warning */
1507 /* NOTE : This function should not be modified, when the callback is needed,
1508 the HAL_PCD_SuspendCallback could be implemented in the user file
1513 * @brief Resume event callback.
1514 * @param hpcd PCD handle
1517 __weak
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef
*hpcd
)
1519 /* Prevent unused argument(s) compilation warning */
1522 /* NOTE : This function should not be modified, when the callback is needed,
1523 the HAL_PCD_ResumeCallback could be implemented in the user file
1528 * @brief Incomplete ISO OUT callback.
1529 * @param hpcd PCD handle
1530 * @param epnum endpoint number
1533 __weak
void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef
*hpcd
, uint8_t epnum
)
1535 /* Prevent unused argument(s) compilation warning */
1539 /* NOTE : This function should not be modified, when the callback is needed,
1540 the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
1545 * @brief Incomplete ISO IN callback.
1546 * @param hpcd PCD handle
1547 * @param epnum endpoint number
1550 __weak
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef
*hpcd
, uint8_t epnum
)
1552 /* Prevent unused argument(s) compilation warning */
1556 /* NOTE : This function should not be modified, when the callback is needed,
1557 the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1562 * @brief Connection event callback.
1563 * @param hpcd PCD handle
1566 __weak
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef
*hpcd
)
1568 /* Prevent unused argument(s) compilation warning */
1571 /* NOTE : This function should not be modified, when the callback is needed,
1572 the HAL_PCD_ConnectCallback could be implemented in the user file
1577 * @brief Disconnection event callback.
1578 * @param hpcd PCD handle
1581 __weak
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef
*hpcd
)
1583 /* Prevent unused argument(s) compilation warning */
1586 /* NOTE : This function should not be modified, when the callback is needed,
1587 the HAL_PCD_DisconnectCallback could be implemented in the user file
1595 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
1596 * @brief management functions
1599 ===============================================================================
1600 ##### Peripheral Control functions #####
1601 ===============================================================================
1603 This subsection provides a set of functions allowing to control the PCD data
1611 * @brief Connect the USB device
1612 * @param hpcd PCD handle
1613 * @retval HAL status
1615 HAL_StatusTypeDef
HAL_PCD_DevConnect(PCD_HandleTypeDef
*hpcd
)
1617 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1618 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
1619 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1622 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1623 if ((hpcd
->Init
.battery_charging_enable
== 1U) &&
1624 (hpcd
->Init
.phy_itface
!= USB_OTG_ULPI_PHY
))
1626 /* Enable USB Transceiver */
1627 USBx
->GCCFG
|= USB_OTG_GCCFG_PWRDWN
;
1629 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1630 (void)USB_DevConnect(hpcd
->Instance
);
1636 * @brief Disconnect the USB device.
1637 * @param hpcd PCD handle
1638 * @retval HAL status
1640 HAL_StatusTypeDef
HAL_PCD_DevDisconnect(PCD_HandleTypeDef
*hpcd
)
1643 (void)USB_DevDisconnect(hpcd
->Instance
);
1649 * @brief Set the USB Device address.
1650 * @param hpcd PCD handle
1651 * @param address new device address
1652 * @retval HAL status
1654 HAL_StatusTypeDef
HAL_PCD_SetAddress(PCD_HandleTypeDef
*hpcd
, uint8_t address
)
1657 hpcd
->USB_Address
= address
;
1658 (void)USB_SetDevAddress(hpcd
->Instance
, address
);
1663 * @brief Open and configure an endpoint.
1664 * @param hpcd PCD handle
1665 * @param ep_addr endpoint address
1666 * @param ep_mps endpoint max packet size
1667 * @param ep_type endpoint type
1668 * @retval HAL status
1670 HAL_StatusTypeDef
HAL_PCD_EP_Open(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
, uint16_t ep_mps
, uint8_t ep_type
)
1672 HAL_StatusTypeDef ret
= HAL_OK
;
1675 if ((ep_addr
& 0x80U
) == 0x80U
)
1677 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1682 ep
= &hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
];
1686 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1687 ep
->maxpacket
= ep_mps
;
1690 if (ep
->is_in
!= 0U)
1692 /* Assign a Tx FIFO */
1693 ep
->tx_fifo_num
= ep
->num
;
1695 /* Set initial data PID. */
1696 if (ep_type
== EP_TYPE_BULK
)
1698 ep
->data_pid_start
= 0U;
1702 (void)USB_ActivateEndpoint(hpcd
->Instance
, ep
);
1709 * @brief Deactivate an endpoint.
1710 * @param hpcd PCD handle
1711 * @param ep_addr endpoint address
1712 * @retval HAL status
1714 HAL_StatusTypeDef
HAL_PCD_EP_Close(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1718 if ((ep_addr
& 0x80U
) == 0x80U
)
1720 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1725 ep
= &hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
];
1728 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1731 (void)USB_DeactivateEndpoint(hpcd
->Instance
, ep
);
1738 * @brief Receive an amount of data.
1739 * @param hpcd PCD handle
1740 * @param ep_addr endpoint address
1741 * @param pBuf pointer to the reception buffer
1742 * @param len amount of data to be received
1743 * @retval HAL status
1745 HAL_StatusTypeDef
HAL_PCD_EP_Receive(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
, uint8_t *pBuf
, uint32_t len
)
1749 ep
= &hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
];
1751 /*setup and start the Xfer */
1752 ep
->xfer_buff
= pBuf
;
1754 ep
->xfer_count
= 0U;
1756 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1758 if (hpcd
->Init
.dma_enable
== 1U)
1760 ep
->dma_addr
= (uint32_t)pBuf
;
1763 if ((ep_addr
& EP_ADDR_MSK
) == 0U)
1765 (void)USB_EP0StartXfer(hpcd
->Instance
, ep
, (uint8_t)hpcd
->Init
.dma_enable
);
1769 (void)USB_EPStartXfer(hpcd
->Instance
, ep
, (uint8_t)hpcd
->Init
.dma_enable
);
1776 * @brief Get Received Data Size
1777 * @param hpcd PCD handle
1778 * @param ep_addr endpoint address
1781 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1783 return hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
].xfer_count
;
1786 * @brief Send an amount of data
1787 * @param hpcd PCD handle
1788 * @param ep_addr endpoint address
1789 * @param pBuf pointer to the transmission buffer
1790 * @param len amount of data to be sent
1791 * @retval HAL status
1793 HAL_StatusTypeDef
HAL_PCD_EP_Transmit(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
, uint8_t *pBuf
, uint32_t len
)
1797 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1799 /*setup and start the Xfer */
1800 ep
->xfer_buff
= pBuf
;
1802 ep
->xfer_count
= 0U;
1804 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1806 if (hpcd
->Init
.dma_enable
== 1U)
1808 ep
->dma_addr
= (uint32_t)pBuf
;
1811 if ((ep_addr
& EP_ADDR_MSK
) == 0U)
1813 (void)USB_EP0StartXfer(hpcd
->Instance
, ep
, (uint8_t)hpcd
->Init
.dma_enable
);
1817 (void)USB_EPStartXfer(hpcd
->Instance
, ep
, (uint8_t)hpcd
->Init
.dma_enable
);
1824 * @brief Set a STALL condition over an endpoint
1825 * @param hpcd PCD handle
1826 * @param ep_addr endpoint address
1827 * @retval HAL status
1829 HAL_StatusTypeDef
HAL_PCD_EP_SetStall(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1833 if (((uint32_t)ep_addr
& EP_ADDR_MSK
) > hpcd
->Init
.dev_endpoints
)
1838 if ((0x80U
& ep_addr
) == 0x80U
)
1840 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1845 ep
= &hpcd
->OUT_ep
[ep_addr
];
1850 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1854 (void)USB_EPSetStall(hpcd
->Instance
, ep
);
1855 if ((ep_addr
& EP_ADDR_MSK
) == 0U)
1857 (void)USB_EP0_OutStart(hpcd
->Instance
, (uint8_t)hpcd
->Init
.dma_enable
, (uint8_t *)hpcd
->Setup
);
1865 * @brief Clear a STALL condition over in an endpoint
1866 * @param hpcd PCD handle
1867 * @param ep_addr endpoint address
1868 * @retval HAL status
1870 HAL_StatusTypeDef
HAL_PCD_EP_ClrStall(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1874 if (((uint32_t)ep_addr
& 0x0FU
) > hpcd
->Init
.dev_endpoints
)
1879 if ((0x80U
& ep_addr
) == 0x80U
)
1881 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1886 ep
= &hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
];
1891 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1894 (void)USB_EPClearStall(hpcd
->Instance
, ep
);
1901 * @brief Flush an endpoint
1902 * @param hpcd PCD handle
1903 * @param ep_addr endpoint address
1904 * @retval HAL status
1906 HAL_StatusTypeDef
HAL_PCD_EP_Flush(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1910 if ((ep_addr
& 0x80U
) == 0x80U
)
1912 (void)USB_FlushTxFifo(hpcd
->Instance
, (uint32_t)ep_addr
& EP_ADDR_MSK
);
1916 (void)USB_FlushRxFifo(hpcd
->Instance
);
1925 * @brief Activate remote wakeup signalling
1926 * @param hpcd PCD handle
1927 * @retval HAL status
1929 HAL_StatusTypeDef
HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef
*hpcd
)
1931 return (USB_ActivateRemoteWakeup(hpcd
->Instance
));
1935 * @brief De-activate remote wakeup signalling.
1936 * @param hpcd PCD handle
1937 * @retval HAL status
1939 HAL_StatusTypeDef
HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef
*hpcd
)
1941 return (USB_DeActivateRemoteWakeup(hpcd
->Instance
));
1948 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1949 * @brief Peripheral State functions
1952 ===============================================================================
1953 ##### Peripheral State functions #####
1954 ===============================================================================
1956 This subsection permits to get in run-time the status of the peripheral
1964 * @brief Return the PCD handle state.
1965 * @param hpcd PCD handle
1968 PCD_StateTypeDef
HAL_PCD_GetState(PCD_HandleTypeDef
*hpcd
)
1981 /* Private functions ---------------------------------------------------------*/
1982 /** @addtogroup PCD_Private_Functions
1985 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1987 * @brief Check FIFO for the next packet to be loaded.
1988 * @param hpcd PCD handle
1989 * @param epnum endpoint number
1990 * @retval HAL status
1992 static HAL_StatusTypeDef
PCD_WriteEmptyTxFifo(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
)
1994 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
1995 uint32_t USBx_BASE
= (uint32_t)USBx
;
1996 USB_OTG_EPTypeDef
*ep
;
1999 uint32_t fifoemptymsk
;
2001 ep
= &hpcd
->IN_ep
[epnum
];
2003 if (ep
->xfer_count
> ep
->xfer_len
)
2008 len
= ep
->xfer_len
- ep
->xfer_count
;
2010 if (len
> ep
->maxpacket
)
2012 len
= ep
->maxpacket
;
2015 len32b
= (len
+ 3U) / 4U;
2017 while (((USBx_INEP(epnum
)->DTXFSTS
& USB_OTG_DTXFSTS_INEPTFSAV
) >= len32b
) &&
2018 (ep
->xfer_count
< ep
->xfer_len
) && (ep
->xfer_len
!= 0U))
2020 /* Write the FIFO */
2021 len
= ep
->xfer_len
- ep
->xfer_count
;
2023 if (len
> ep
->maxpacket
)
2025 len
= ep
->maxpacket
;
2027 len32b
= (len
+ 3U) / 4U;
2029 (void)USB_WritePacket(USBx
, ep
->xfer_buff
, (uint8_t)epnum
, (uint16_t)len
,
2030 (uint8_t)hpcd
->Init
.dma_enable
);
2032 ep
->xfer_buff
+= len
;
2033 ep
->xfer_count
+= len
;
2036 if (ep
->xfer_len
<= ep
->xfer_count
)
2038 fifoemptymsk
= (uint32_t)(0x1UL
<< (epnum
& EP_ADDR_MSK
));
2039 USBx_DEVICE
->DIEPEMPMSK
&= ~fifoemptymsk
;
2047 * @brief process EP OUT transfer complete interrupt.
2048 * @param hpcd PCD handle
2049 * @param epnum endpoint number
2050 * @retval HAL status
2052 static HAL_StatusTypeDef
PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
)
2054 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
2055 uint32_t USBx_BASE
= (uint32_t)USBx
;
2056 uint32_t gSNPSiD
= *(__IO
uint32_t *)(&USBx
->CID
+ 0x1U
);
2057 uint32_t DoepintReg
= USBx_OUTEP(epnum
)->DOEPINT
;
2059 if (hpcd
->Init
.dma_enable
== 1U)
2061 if ((DoepintReg
& USB_OTG_DOEPINT_STUP
) == USB_OTG_DOEPINT_STUP
) /* Class C */
2063 /* StupPktRcvd = 1 this is a setup packet */
2064 if ((gSNPSiD
> USB_OTG_CORE_ID_300A
) &&
2065 ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
))
2067 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
2070 else if ((DoepintReg
& USB_OTG_DOEPINT_OTEPSPR
) == USB_OTG_DOEPINT_OTEPSPR
) /* Class E */
2072 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_OTEPSPR
);
2074 else if ((DoepintReg
& (USB_OTG_DOEPINT_STUP
| USB_OTG_DOEPINT_OTEPSPR
)) == 0U)
2076 /* StupPktRcvd = 1 this is a setup packet */
2077 if ((gSNPSiD
> USB_OTG_CORE_ID_300A
) &&
2078 ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
))
2080 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
2084 /* out data packet received over EP0 */
2085 hpcd
->OUT_ep
[epnum
].xfer_count
=
2086 hpcd
->OUT_ep
[epnum
].maxpacket
-
2087 (USBx_OUTEP(epnum
)->DOEPTSIZ
& USB_OTG_DOEPTSIZ_XFRSIZ
);
2089 hpcd
->OUT_ep
[epnum
].xfer_buff
+= hpcd
->OUT_ep
[epnum
].maxpacket
;
2091 if ((epnum
== 0U) && (hpcd
->OUT_ep
[epnum
].xfer_len
== 0U))
2093 /* this is ZLP, so prepare EP0 for next setup */
2094 (void)USB_EP0_OutStart(hpcd
->Instance
, 1U, (uint8_t *)hpcd
->Setup
);
2096 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2097 hpcd
->DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2099 HAL_PCD_DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2100 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2110 if (gSNPSiD
== USB_OTG_CORE_ID_310A
)
2112 /* StupPktRcvd = 1 this is a setup packet */
2113 if ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
)
2115 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
2119 if ((DoepintReg
& USB_OTG_DOEPINT_OTEPSPR
) == USB_OTG_DOEPINT_OTEPSPR
)
2121 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_OTEPSPR
);
2124 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2125 hpcd
->DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2127 HAL_PCD_DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2128 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2133 if ((epnum
== 0U) && (hpcd
->OUT_ep
[epnum
].xfer_len
== 0U))
2135 /* this is ZLP, so prepare EP0 for next setup */
2136 (void)USB_EP0_OutStart(hpcd
->Instance
, 0U, (uint8_t *)hpcd
->Setup
);
2139 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2140 hpcd
->DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2142 HAL_PCD_DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2143 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2152 * @brief process EP OUT setup packet received interrupt.
2153 * @param hpcd PCD handle
2154 * @param epnum endpoint number
2155 * @retval HAL status
2157 static HAL_StatusTypeDef
PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
)
2159 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
2160 uint32_t USBx_BASE
= (uint32_t)USBx
;
2161 uint32_t gSNPSiD
= *(__IO
uint32_t *)(&USBx
->CID
+ 0x1U
);
2162 uint32_t DoepintReg
= USBx_OUTEP(epnum
)->DOEPINT
;
2164 if ((gSNPSiD
> USB_OTG_CORE_ID_300A
) &&
2165 ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
))
2167 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
2170 /* Inform the upper layer that a setup packet is available */
2171 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2172 hpcd
->SetupStageCallback(hpcd
);
2174 HAL_PCD_SetupStageCallback(hpcd
);
2175 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2177 if ((gSNPSiD
> USB_OTG_CORE_ID_300A
) && (hpcd
->Init
.dma_enable
== 1U))
2179 (void)USB_EP0_OutStart(hpcd
->Instance
, 1U, (uint8_t *)hpcd
->Setup
);
2184 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2190 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2191 #endif /* HAL_PCD_MODULE_ENABLED */
2201 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/