2 ******************************************************************************
3 * @file stm32f7xx_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 "stm32f7xx_hal.h"
60 /** @addtogroup STM32F7xx_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
)
127 /* Check the PCD handle allocation */
133 /* Check the parameters */
134 assert_param(IS_PCD_ALL_INSTANCE(hpcd
->Instance
));
136 if (hpcd
->State
== HAL_PCD_STATE_RESET
)
138 /* Allocate lock resource and initialize it */
139 hpcd
->Lock
= HAL_UNLOCKED
;
141 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
142 hpcd
->SOFCallback
= HAL_PCD_SOFCallback
;
143 hpcd
->SetupStageCallback
= HAL_PCD_SetupStageCallback
;
144 hpcd
->ResetCallback
= HAL_PCD_ResetCallback
;
145 hpcd
->SuspendCallback
= HAL_PCD_SuspendCallback
;
146 hpcd
->ResumeCallback
= HAL_PCD_ResumeCallback
;
147 hpcd
->ConnectCallback
= HAL_PCD_ConnectCallback
;
148 hpcd
->DisconnectCallback
= HAL_PCD_DisconnectCallback
;
149 hpcd
->DataOutStageCallback
= HAL_PCD_DataOutStageCallback
;
150 hpcd
->DataInStageCallback
= HAL_PCD_DataInStageCallback
;
151 hpcd
->ISOOUTIncompleteCallback
= HAL_PCD_ISOOUTIncompleteCallback
;
152 hpcd
->ISOINIncompleteCallback
= HAL_PCD_ISOINIncompleteCallback
;
154 if (hpcd
->MspInitCallback
== NULL
)
156 hpcd
->MspInitCallback
= HAL_PCD_MspInit
;
159 /* Init the low level hardware */
160 hpcd
->MspInitCallback(hpcd
);
162 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
163 HAL_PCD_MspInit(hpcd
);
164 #endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
167 hpcd
->State
= HAL_PCD_STATE_BUSY
;
169 /* Disable the Interrupts */
170 __HAL_PCD_DISABLE(hpcd
);
172 /*Init the Core (common init.) */
173 if (USB_CoreInit(hpcd
->Instance
, hpcd
->Init
) != HAL_OK
)
175 hpcd
->State
= HAL_PCD_STATE_ERROR
;
179 /* Force Device Mode*/
180 (void)USB_SetCurrentMode(hpcd
->Instance
, USB_DEVICE_MODE
);
182 /* Init endpoints structures */
183 for (i
= 0U; i
< hpcd
->Init
.dev_endpoints
; i
++)
185 /* Init ep structure */
186 hpcd
->IN_ep
[i
].is_in
= 1U;
187 hpcd
->IN_ep
[i
].num
= i
;
188 hpcd
->IN_ep
[i
].tx_fifo_num
= i
;
189 /* Control until ep is activated */
190 hpcd
->IN_ep
[i
].type
= EP_TYPE_CTRL
;
191 hpcd
->IN_ep
[i
].maxpacket
= 0U;
192 hpcd
->IN_ep
[i
].xfer_buff
= 0U;
193 hpcd
->IN_ep
[i
].xfer_len
= 0U;
196 for (i
= 0U; i
< hpcd
->Init
.dev_endpoints
; i
++)
198 hpcd
->OUT_ep
[i
].is_in
= 0U;
199 hpcd
->OUT_ep
[i
].num
= i
;
200 /* Control until ep is activated */
201 hpcd
->OUT_ep
[i
].type
= EP_TYPE_CTRL
;
202 hpcd
->OUT_ep
[i
].maxpacket
= 0U;
203 hpcd
->OUT_ep
[i
].xfer_buff
= 0U;
204 hpcd
->OUT_ep
[i
].xfer_len
= 0U;
208 if (USB_DevInit(hpcd
->Instance
, hpcd
->Init
) != HAL_OK
)
210 hpcd
->State
= HAL_PCD_STATE_ERROR
;
214 hpcd
->USB_Address
= 0U;
215 hpcd
->State
= HAL_PCD_STATE_READY
;
218 if (hpcd
->Init
.lpm_enable
== 1U)
220 (void)HAL_PCDEx_ActivateLPM(hpcd
);
223 (void)USB_DevDisconnect(hpcd
->Instance
);
229 * @brief DeInitializes the PCD peripheral.
230 * @param hpcd PCD handle
233 HAL_StatusTypeDef
HAL_PCD_DeInit(PCD_HandleTypeDef
*hpcd
)
235 /* Check the PCD handle allocation */
241 hpcd
->State
= HAL_PCD_STATE_BUSY
;
244 (void)HAL_PCD_Stop(hpcd
);
246 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
247 if (hpcd
->MspDeInitCallback
== NULL
)
249 hpcd
->MspDeInitCallback
= HAL_PCD_MspDeInit
; /* Legacy weak MspDeInit */
252 /* DeInit the low level hardware */
253 hpcd
->MspDeInitCallback(hpcd
);
255 /* DeInit the low level hardware: CLOCK, NVIC.*/
256 HAL_PCD_MspDeInit(hpcd
);
257 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
259 hpcd
->State
= HAL_PCD_STATE_RESET
;
265 * @brief Initializes the PCD MSP.
266 * @param hpcd PCD handle
269 __weak
void HAL_PCD_MspInit(PCD_HandleTypeDef
*hpcd
)
271 /* Prevent unused argument(s) compilation warning */
274 /* NOTE : This function should not be modified, when the callback is needed,
275 the HAL_PCD_MspInit could be implemented in the user file
280 * @brief DeInitializes PCD MSP.
281 * @param hpcd PCD handle
284 __weak
void HAL_PCD_MspDeInit(PCD_HandleTypeDef
*hpcd
)
286 /* Prevent unused argument(s) compilation warning */
289 /* NOTE : This function should not be modified, when the callback is needed,
290 the HAL_PCD_MspDeInit could be implemented in the user file
294 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
296 * @brief Register a User USB PCD Callback
297 * To be used instead of the weak predefined callback
298 * @param hpcd USB PCD handle
299 * @param CallbackID ID of the callback to be registered
300 * This parameter can be one of the following values:
301 * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
302 * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
303 * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
304 * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
305 * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
306 * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
307 * @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
308 * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
309 * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
310 * @param pCallback pointer to the Callback function
313 HAL_StatusTypeDef
HAL_PCD_RegisterCallback(PCD_HandleTypeDef
*hpcd
, HAL_PCD_CallbackIDTypeDef CallbackID
, pPCD_CallbackTypeDef pCallback
)
315 HAL_StatusTypeDef status
= HAL_OK
;
317 if (pCallback
== NULL
)
319 /* Update the error code */
320 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
326 if (hpcd
->State
== HAL_PCD_STATE_READY
)
330 case HAL_PCD_SOF_CB_ID
:
331 hpcd
->SOFCallback
= pCallback
;
334 case HAL_PCD_SETUPSTAGE_CB_ID
:
335 hpcd
->SetupStageCallback
= pCallback
;
338 case HAL_PCD_RESET_CB_ID
:
339 hpcd
->ResetCallback
= pCallback
;
342 case HAL_PCD_SUSPEND_CB_ID
:
343 hpcd
->SuspendCallback
= pCallback
;
346 case HAL_PCD_RESUME_CB_ID
:
347 hpcd
->ResumeCallback
= pCallback
;
350 case HAL_PCD_CONNECT_CB_ID
:
351 hpcd
->ConnectCallback
= pCallback
;
354 case HAL_PCD_DISCONNECT_CB_ID
:
355 hpcd
->DisconnectCallback
= pCallback
;
358 case HAL_PCD_MSPINIT_CB_ID
:
359 hpcd
->MspInitCallback
= pCallback
;
362 case HAL_PCD_MSPDEINIT_CB_ID
:
363 hpcd
->MspDeInitCallback
= pCallback
;
367 /* Update the error code */
368 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
369 /* Return error status */
374 else if (hpcd
->State
== HAL_PCD_STATE_RESET
)
378 case HAL_PCD_MSPINIT_CB_ID
:
379 hpcd
->MspInitCallback
= pCallback
;
382 case HAL_PCD_MSPDEINIT_CB_ID
:
383 hpcd
->MspDeInitCallback
= pCallback
;
387 /* Update the error code */
388 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
389 /* Return error status */
396 /* Update the error code */
397 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
398 /* Return error status */
408 * @brief Unregister an USB PCD Callback
409 * USB PCD callabck is redirected to the weak predefined callback
410 * @param hpcd USB PCD handle
411 * @param CallbackID ID of the callback to be unregistered
412 * This parameter can be one of the following values:
413 * @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
414 * @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
415 * @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
416 * @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
417 * @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
418 * @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
419 * @arg @ref HAL_PCD_DISCONNECT_CB_ID OTG PCD Disconnect callback ID
420 * @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
421 * @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
424 HAL_StatusTypeDef
HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef
*hpcd
, HAL_PCD_CallbackIDTypeDef CallbackID
)
426 HAL_StatusTypeDef status
= HAL_OK
;
431 /* Setup Legacy weak Callbacks */
432 if (hpcd
->State
== HAL_PCD_STATE_READY
)
436 case HAL_PCD_SOF_CB_ID
:
437 hpcd
->SOFCallback
= HAL_PCD_SOFCallback
;
440 case HAL_PCD_SETUPSTAGE_CB_ID
:
441 hpcd
->SetupStageCallback
= HAL_PCD_SetupStageCallback
;
444 case HAL_PCD_RESET_CB_ID
:
445 hpcd
->ResetCallback
= HAL_PCD_ResetCallback
;
448 case HAL_PCD_SUSPEND_CB_ID
:
449 hpcd
->SuspendCallback
= HAL_PCD_SuspendCallback
;
452 case HAL_PCD_RESUME_CB_ID
:
453 hpcd
->ResumeCallback
= HAL_PCD_ResumeCallback
;
456 case HAL_PCD_CONNECT_CB_ID
:
457 hpcd
->ConnectCallback
= HAL_PCD_ConnectCallback
;
460 case HAL_PCD_DISCONNECT_CB_ID
:
461 hpcd
->DisconnectCallback
= HAL_PCD_DisconnectCallback
;
464 case HAL_PCD_MSPINIT_CB_ID
:
465 hpcd
->MspInitCallback
= HAL_PCD_MspInit
;
468 case HAL_PCD_MSPDEINIT_CB_ID
:
469 hpcd
->MspDeInitCallback
= HAL_PCD_MspDeInit
;
473 /* Update the error code */
474 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
476 /* Return error status */
481 else if (hpcd
->State
== HAL_PCD_STATE_RESET
)
485 case HAL_PCD_MSPINIT_CB_ID
:
486 hpcd
->MspInitCallback
= HAL_PCD_MspInit
;
489 case HAL_PCD_MSPDEINIT_CB_ID
:
490 hpcd
->MspDeInitCallback
= HAL_PCD_MspDeInit
;
494 /* Update the error code */
495 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
497 /* Return error status */
504 /* Update the error code */
505 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
507 /* Return error status */
517 * @brief Register USB PCD Data OUT Stage Callback
518 * To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
519 * @param hpcd PCD handle
520 * @param pCallback pointer to the USB PCD Data OUT Stage Callback function
523 HAL_StatusTypeDef
HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef
*hpcd
, pPCD_DataOutStageCallbackTypeDef pCallback
)
525 HAL_StatusTypeDef status
= HAL_OK
;
527 if (pCallback
== NULL
)
529 /* Update the error code */
530 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
538 if (hpcd
->State
== HAL_PCD_STATE_READY
)
540 hpcd
->DataOutStageCallback
= pCallback
;
544 /* Update the error code */
545 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
547 /* Return error status */
558 * @brief UnRegister the USB PCD Data OUT Stage Callback
559 * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
560 * @param hpcd PCD handle
563 HAL_StatusTypeDef
HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef
*hpcd
)
565 HAL_StatusTypeDef status
= HAL_OK
;
570 if (hpcd
->State
== HAL_PCD_STATE_READY
)
572 hpcd
->DataOutStageCallback
= HAL_PCD_DataOutStageCallback
; /* Legacy weak DataOutStageCallback */
576 /* Update the error code */
577 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
579 /* Return error status */
590 * @brief Register USB PCD Data IN Stage Callback
591 * To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
592 * @param hpcd PCD handle
593 * @param pCallback pointer to the USB PCD Data IN Stage Callback function
596 HAL_StatusTypeDef
HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef
*hpcd
, pPCD_DataInStageCallbackTypeDef pCallback
)
598 HAL_StatusTypeDef status
= HAL_OK
;
600 if (pCallback
== NULL
)
602 /* Update the error code */
603 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
611 if (hpcd
->State
== HAL_PCD_STATE_READY
)
613 hpcd
->DataInStageCallback
= pCallback
;
617 /* Update the error code */
618 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
620 /* Return error status */
631 * @brief UnRegister the USB PCD Data IN Stage Callback
632 * USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
633 * @param hpcd PCD handle
636 HAL_StatusTypeDef
HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef
*hpcd
)
638 HAL_StatusTypeDef status
= HAL_OK
;
643 if (hpcd
->State
== HAL_PCD_STATE_READY
)
645 hpcd
->DataInStageCallback
= HAL_PCD_DataInStageCallback
; /* Legacy weak DataInStageCallback */
649 /* Update the error code */
650 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
652 /* Return error status */
663 * @brief Register USB PCD Iso OUT incomplete Callback
664 * To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
665 * @param hpcd PCD handle
666 * @param pCallback pointer to the USB PCD Iso OUT incomplete Callback function
669 HAL_StatusTypeDef
HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef
*hpcd
, pPCD_IsoOutIncpltCallbackTypeDef pCallback
)
671 HAL_StatusTypeDef status
= HAL_OK
;
673 if (pCallback
== NULL
)
675 /* Update the error code */
676 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
684 if (hpcd
->State
== HAL_PCD_STATE_READY
)
686 hpcd
->ISOOUTIncompleteCallback
= pCallback
;
690 /* Update the error code */
691 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
693 /* Return error status */
704 * @brief UnRegister the USB PCD Iso OUT incomplete Callback
705 * USB PCD Iso OUT incomplete Callback is redirected to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
706 * @param hpcd PCD handle
709 HAL_StatusTypeDef
HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef
*hpcd
)
711 HAL_StatusTypeDef status
= HAL_OK
;
716 if (hpcd
->State
== HAL_PCD_STATE_READY
)
718 hpcd
->ISOOUTIncompleteCallback
= HAL_PCD_ISOOUTIncompleteCallback
; /* Legacy weak ISOOUTIncompleteCallback */
722 /* Update the error code */
723 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
725 /* Return error status */
736 * @brief Register USB PCD Iso IN incomplete Callback
737 * To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
738 * @param hpcd PCD handle
739 * @param pCallback pointer to the USB PCD Iso IN incomplete Callback function
742 HAL_StatusTypeDef
HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef
*hpcd
, pPCD_IsoInIncpltCallbackTypeDef pCallback
)
744 HAL_StatusTypeDef status
= HAL_OK
;
746 if (pCallback
== NULL
)
748 /* Update the error code */
749 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
757 if (hpcd
->State
== HAL_PCD_STATE_READY
)
759 hpcd
->ISOINIncompleteCallback
= pCallback
;
763 /* Update the error code */
764 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
766 /* Return error status */
777 * @brief UnRegister the USB PCD Iso IN incomplete Callback
778 * USB PCD Iso IN incomplete Callback is redirected to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
779 * @param hpcd PCD handle
782 HAL_StatusTypeDef
HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef
*hpcd
)
784 HAL_StatusTypeDef status
= HAL_OK
;
789 if (hpcd
->State
== HAL_PCD_STATE_READY
)
791 hpcd
->ISOINIncompleteCallback
= HAL_PCD_ISOINIncompleteCallback
; /* Legacy weak ISOINIncompleteCallback */
795 /* Update the error code */
796 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
798 /* Return error status */
809 * @brief Register USB PCD LPM Callback
810 * To be used instead of the weak HAL_PCDEx_LPM_Callback() predefined callback
811 * @param hpcd PCD handle
812 * @param pCallback pointer to the USB PCD LPM Callback function
815 HAL_StatusTypeDef
HAL_PCD_RegisterLpmCallback(PCD_HandleTypeDef
*hpcd
, pPCD_LpmCallbackTypeDef pCallback
)
817 HAL_StatusTypeDef status
= HAL_OK
;
819 if (pCallback
== NULL
)
821 /* Update the error code */
822 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
830 if (hpcd
->State
== HAL_PCD_STATE_READY
)
832 hpcd
->LPMCallback
= pCallback
;
836 /* Update the error code */
837 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
839 /* Return error status */
850 * @brief UnRegister the USB PCD LPM Callback
851 * USB LPM Callback is redirected to the weak HAL_PCDEx_LPM_Callback() predefined callback
852 * @param hpcd PCD handle
855 HAL_StatusTypeDef
HAL_PCD_UnRegisterLpmCallback(PCD_HandleTypeDef
*hpcd
)
857 HAL_StatusTypeDef status
= HAL_OK
;
862 if (hpcd
->State
== HAL_PCD_STATE_READY
)
864 hpcd
->LPMCallback
= HAL_PCDEx_LPM_Callback
; /* Legacy weak HAL_PCDEx_LPM_Callback */
868 /* Update the error code */
869 hpcd
->ErrorCode
|= HAL_PCD_ERROR_INVALID_CALLBACK
;
871 /* Return error status */
880 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
886 /** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
887 * @brief Data transfers functions
890 ===============================================================================
891 ##### IO operation functions #####
892 ===============================================================================
894 This subsection provides a set of functions allowing to manage the PCD data
902 * @brief Start the USB device
903 * @param hpcd PCD handle
906 HAL_StatusTypeDef
HAL_PCD_Start(PCD_HandleTypeDef
*hpcd
)
909 (void)USB_DevConnect(hpcd
->Instance
);
910 __HAL_PCD_ENABLE(hpcd
);
916 * @brief Stop the USB device.
917 * @param hpcd PCD handle
920 HAL_StatusTypeDef
HAL_PCD_Stop(PCD_HandleTypeDef
*hpcd
)
923 __HAL_PCD_DISABLE(hpcd
);
925 if (USB_StopDevice(hpcd
->Instance
) != HAL_OK
)
931 (void)USB_DevDisconnect(hpcd
->Instance
);
936 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
938 * @brief Handles PCD interrupt request.
939 * @param hpcd PCD handle
942 void HAL_PCD_IRQHandler(PCD_HandleTypeDef
*hpcd
)
944 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
945 uint32_t USBx_BASE
= (uint32_t)USBx
;
946 uint32_t i
, ep_intr
, epint
, epnum
= 0U;
947 uint32_t fifoemptymsk
, temp
;
948 USB_OTG_EPTypeDef
*ep
;
950 /* ensure that we are in device mode */
951 if (USB_GetMode(hpcd
->Instance
) == USB_OTG_MODE_DEVICE
)
953 /* avoid spurious interrupt */
954 if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd
))
959 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_MMIS
))
961 /* incorrect mode, acknowledge the interrupt */
962 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_MMIS
);
965 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_OEPINT
))
969 /* Read in the device interrupt bits */
970 ep_intr
= USB_ReadDevAllOutEpInterrupt(hpcd
->Instance
);
972 while (ep_intr
!= 0U)
974 if ((ep_intr
& 0x1U
) != 0U)
976 epint
= USB_ReadDevOutEPInterrupt(hpcd
->Instance
, (uint8_t)epnum
);
978 if ((epint
& USB_OTG_DOEPINT_XFRC
) == USB_OTG_DOEPINT_XFRC
)
980 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_XFRC
);
981 (void)PCD_EP_OutXfrComplete_int(hpcd
, epnum
);
984 if ((epint
& USB_OTG_DOEPINT_STUP
) == USB_OTG_DOEPINT_STUP
)
986 /* Class B setup phase done for previous decoded setup */
987 (void)PCD_EP_OutSetupPacket_int(hpcd
, epnum
);
988 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STUP
);
991 if ((epint
& USB_OTG_DOEPINT_OTEPDIS
) == USB_OTG_DOEPINT_OTEPDIS
)
993 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_OTEPDIS
);
996 /* Clear Status Phase Received interrupt */
997 if ((epint
& USB_OTG_DOEPINT_OTEPSPR
) == USB_OTG_DOEPINT_OTEPSPR
)
999 if (hpcd
->Init
.dma_enable
== 1U)
1001 (void)USB_EP0_OutStart(hpcd
->Instance
, 1U, (uint8_t *)hpcd
->Setup
);
1003 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_OTEPSPR
);
1006 /* Clear OUT NAK interrupt */
1007 if ((epint
& USB_OTG_DOEPINT_NAK
) == USB_OTG_DOEPINT_NAK
)
1009 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_NAK
);
1017 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_IEPINT
))
1019 /* Read in the device interrupt bits */
1020 ep_intr
= USB_ReadDevAllInEpInterrupt(hpcd
->Instance
);
1024 while (ep_intr
!= 0U)
1026 if ((ep_intr
& 0x1U
) != 0U) /* In ITR */
1028 epint
= USB_ReadDevInEPInterrupt(hpcd
->Instance
, (uint8_t)epnum
);
1030 if ((epint
& USB_OTG_DIEPINT_XFRC
) == USB_OTG_DIEPINT_XFRC
)
1032 fifoemptymsk
= (uint32_t)(0x1UL
<< (epnum
& EP_ADDR_MSK
));
1033 USBx_DEVICE
->DIEPEMPMSK
&= ~fifoemptymsk
;
1035 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_XFRC
);
1037 if (hpcd
->Init
.dma_enable
== 1U)
1039 hpcd
->IN_ep
[epnum
].xfer_buff
+= hpcd
->IN_ep
[epnum
].maxpacket
;
1042 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1043 hpcd
->DataInStageCallback(hpcd
, (uint8_t)epnum
);
1045 HAL_PCD_DataInStageCallback(hpcd
, (uint8_t)epnum
);
1046 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1048 if (hpcd
->Init
.dma_enable
== 1U)
1050 /* this is ZLP, so prepare EP0 for next setup */
1051 if ((epnum
== 0U) && (hpcd
->IN_ep
[epnum
].xfer_len
== 0U))
1053 /* prepare to rx more setup packets */
1054 (void)USB_EP0_OutStart(hpcd
->Instance
, 1U, (uint8_t *)hpcd
->Setup
);
1058 if ((epint
& USB_OTG_DIEPINT_TOC
) == USB_OTG_DIEPINT_TOC
)
1060 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_TOC
);
1062 if ((epint
& USB_OTG_DIEPINT_ITTXFE
) == USB_OTG_DIEPINT_ITTXFE
)
1064 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_ITTXFE
);
1066 if ((epint
& USB_OTG_DIEPINT_INEPNE
) == USB_OTG_DIEPINT_INEPNE
)
1068 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_INEPNE
);
1070 if ((epint
& USB_OTG_DIEPINT_EPDISD
) == USB_OTG_DIEPINT_EPDISD
)
1072 CLEAR_IN_EP_INTR(epnum
, USB_OTG_DIEPINT_EPDISD
);
1074 if ((epint
& USB_OTG_DIEPINT_TXFE
) == USB_OTG_DIEPINT_TXFE
)
1076 (void)PCD_WriteEmptyTxFifo(hpcd
, epnum
);
1084 /* Handle Resume Interrupt */
1085 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_WKUINT
))
1087 /* Clear the Remote Wake-up Signaling */
1088 USBx_DEVICE
->DCTL
&= ~USB_OTG_DCTL_RWUSIG
;
1090 if (hpcd
->LPM_State
== LPM_L1
)
1092 hpcd
->LPM_State
= LPM_L0
;
1094 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1095 hpcd
->LPMCallback(hpcd
, PCD_LPM_L0_ACTIVE
);
1097 HAL_PCDEx_LPM_Callback(hpcd
, PCD_LPM_L0_ACTIVE
);
1098 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1102 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1103 hpcd
->ResumeCallback(hpcd
);
1105 HAL_PCD_ResumeCallback(hpcd
);
1106 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1109 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_WKUINT
);
1112 /* Handle Suspend Interrupt */
1113 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_USBSUSP
))
1115 if ((USBx_DEVICE
->DSTS
& USB_OTG_DSTS_SUSPSTS
) == USB_OTG_DSTS_SUSPSTS
)
1117 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1118 hpcd
->SuspendCallback(hpcd
);
1120 HAL_PCD_SuspendCallback(hpcd
);
1121 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1123 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_USBSUSP
);
1126 /* Handle LPM Interrupt */
1127 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_LPMINT
))
1129 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_LPMINT
);
1131 if (hpcd
->LPM_State
== LPM_L0
)
1133 hpcd
->LPM_State
= LPM_L1
;
1134 hpcd
->BESL
= (hpcd
->Instance
->GLPMCFG
& USB_OTG_GLPMCFG_BESL
) >> 2U;
1136 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1137 hpcd
->LPMCallback(hpcd
, PCD_LPM_L1_ACTIVE
);
1139 HAL_PCDEx_LPM_Callback(hpcd
, PCD_LPM_L1_ACTIVE
);
1140 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1144 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1145 hpcd
->SuspendCallback(hpcd
);
1147 HAL_PCD_SuspendCallback(hpcd
);
1148 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1152 /* Handle Reset Interrupt */
1153 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_USBRST
))
1155 USBx_DEVICE
->DCTL
&= ~USB_OTG_DCTL_RWUSIG
;
1156 (void)USB_FlushTxFifo(hpcd
->Instance
, 0x10U
);
1158 for (i
= 0U; i
< hpcd
->Init
.dev_endpoints
; i
++)
1160 USBx_INEP(i
)->DIEPINT
= 0xFB7FU
;
1161 USBx_INEP(i
)->DIEPCTL
&= ~USB_OTG_DIEPCTL_STALL
;
1162 USBx_OUTEP(i
)->DOEPINT
= 0xFB7FU
;
1163 USBx_OUTEP(i
)->DOEPCTL
&= ~USB_OTG_DOEPCTL_STALL
;
1165 USBx_DEVICE
->DAINTMSK
|= 0x10001U
;
1167 if (hpcd
->Init
.use_dedicated_ep1
!= 0U)
1169 USBx_DEVICE
->DOUTEP1MSK
|= USB_OTG_DOEPMSK_STUPM
|
1170 USB_OTG_DOEPMSK_XFRCM
|
1171 USB_OTG_DOEPMSK_EPDM
;
1173 USBx_DEVICE
->DINEP1MSK
|= USB_OTG_DIEPMSK_TOM
|
1174 USB_OTG_DIEPMSK_XFRCM
|
1175 USB_OTG_DIEPMSK_EPDM
;
1179 USBx_DEVICE
->DOEPMSK
|= USB_OTG_DOEPMSK_STUPM
|
1180 USB_OTG_DOEPMSK_XFRCM
|
1181 USB_OTG_DOEPMSK_EPDM
|
1182 USB_OTG_DOEPMSK_OTEPSPRM
|
1183 USB_OTG_DOEPMSK_NAKM
;
1185 USBx_DEVICE
->DIEPMSK
|= USB_OTG_DIEPMSK_TOM
|
1186 USB_OTG_DIEPMSK_XFRCM
|
1187 USB_OTG_DIEPMSK_EPDM
;
1190 /* Set Default Address to 0 */
1191 USBx_DEVICE
->DCFG
&= ~USB_OTG_DCFG_DAD
;
1193 /* setup EP0 to receive SETUP packets */
1194 (void)USB_EP0_OutStart(hpcd
->Instance
, (uint8_t)hpcd
->Init
.dma_enable
,
1195 (uint8_t *)hpcd
->Setup
);
1197 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_USBRST
);
1200 /* Handle Enumeration done Interrupt */
1201 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_ENUMDNE
))
1203 (void)USB_ActivateSetup(hpcd
->Instance
);
1205 if (USB_GetDevSpeed(hpcd
->Instance
) == USB_OTG_SPEED_HIGH
)
1207 hpcd
->Init
.speed
= USB_OTG_SPEED_HIGH
;
1211 hpcd
->Init
.speed
= USB_OTG_SPEED_FULL
;
1214 /* Set USB Turnaround time */
1215 (void)USB_SetTurnaroundTime(hpcd
->Instance
,
1216 HAL_RCC_GetHCLKFreq(),
1217 (uint8_t)hpcd
->Init
.speed
);
1219 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1220 hpcd
->ResetCallback(hpcd
);
1222 HAL_PCD_ResetCallback(hpcd
);
1223 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1225 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_ENUMDNE
);
1228 /* Handle RxQLevel Interrupt */
1229 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_RXFLVL
))
1231 USB_MASK_INTERRUPT(hpcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
1233 temp
= USBx
->GRXSTSP
;
1235 ep
= &hpcd
->OUT_ep
[temp
& USB_OTG_GRXSTSP_EPNUM
];
1237 if (((temp
& USB_OTG_GRXSTSP_PKTSTS
) >> 17) == STS_DATA_UPDT
)
1239 if ((temp
& USB_OTG_GRXSTSP_BCNT
) != 0U)
1241 (void)USB_ReadPacket(USBx
, ep
->xfer_buff
,
1242 (uint16_t)((temp
& USB_OTG_GRXSTSP_BCNT
) >> 4));
1244 ep
->xfer_buff
+= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1245 ep
->xfer_count
+= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1248 else if (((temp
& USB_OTG_GRXSTSP_PKTSTS
) >> 17) == STS_SETUP_UPDT
)
1250 (void)USB_ReadPacket(USBx
, (uint8_t *)hpcd
->Setup
, 8U);
1251 ep
->xfer_count
+= (temp
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1257 USB_UNMASK_INTERRUPT(hpcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
1260 /* Handle SOF Interrupt */
1261 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_SOF
))
1263 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1264 hpcd
->SOFCallback(hpcd
);
1266 HAL_PCD_SOFCallback(hpcd
);
1267 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1269 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_SOF
);
1272 /* Handle Incomplete ISO IN Interrupt */
1273 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_IISOIXFR
))
1275 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1276 hpcd
->ISOINIncompleteCallback(hpcd
, (uint8_t)epnum
);
1278 HAL_PCD_ISOINIncompleteCallback(hpcd
, (uint8_t)epnum
);
1279 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1281 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_IISOIXFR
);
1284 /* Handle Incomplete ISO OUT Interrupt */
1285 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
))
1287 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1288 hpcd
->ISOOUTIncompleteCallback(hpcd
, (uint8_t)epnum
);
1290 HAL_PCD_ISOOUTIncompleteCallback(hpcd
, (uint8_t)epnum
);
1291 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1293 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
);
1296 /* Handle Connection event Interrupt */
1297 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_SRQINT
))
1299 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1300 hpcd
->ConnectCallback(hpcd
);
1302 HAL_PCD_ConnectCallback(hpcd
);
1303 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1305 __HAL_PCD_CLEAR_FLAG(hpcd
, USB_OTG_GINTSTS_SRQINT
);
1308 /* Handle Disconnection event Interrupt */
1309 if (__HAL_PCD_GET_FLAG(hpcd
, USB_OTG_GINTSTS_OTGINT
))
1311 temp
= hpcd
->Instance
->GOTGINT
;
1313 if ((temp
& USB_OTG_GOTGINT_SEDET
) == USB_OTG_GOTGINT_SEDET
)
1315 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1316 hpcd
->DisconnectCallback(hpcd
);
1318 HAL_PCD_DisconnectCallback(hpcd
);
1319 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1321 hpcd
->Instance
->GOTGINT
|= temp
;
1325 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1329 * @brief Data OUT stage callback.
1330 * @param hpcd PCD handle
1331 * @param epnum endpoint number
1334 __weak
void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef
*hpcd
, uint8_t epnum
)
1336 /* Prevent unused argument(s) compilation warning */
1340 /* NOTE : This function should not be modified, when the callback is needed,
1341 the HAL_PCD_DataOutStageCallback could be implemented in the user file
1346 * @brief Data IN stage callback
1347 * @param hpcd PCD handle
1348 * @param epnum endpoint number
1351 __weak
void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef
*hpcd
, uint8_t epnum
)
1353 /* Prevent unused argument(s) compilation warning */
1357 /* NOTE : This function should not be modified, when the callback is needed,
1358 the HAL_PCD_DataInStageCallback could be implemented in the user file
1362 * @brief Setup stage callback
1363 * @param hpcd PCD handle
1366 __weak
void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef
*hpcd
)
1368 /* Prevent unused argument(s) compilation warning */
1371 /* NOTE : This function should not be modified, when the callback is needed,
1372 the HAL_PCD_SetupStageCallback could be implemented in the user file
1377 * @brief USB Start Of Frame callback.
1378 * @param hpcd PCD handle
1381 __weak
void HAL_PCD_SOFCallback(PCD_HandleTypeDef
*hpcd
)
1383 /* Prevent unused argument(s) compilation warning */
1386 /* NOTE : This function should not be modified, when the callback is needed,
1387 the HAL_PCD_SOFCallback could be implemented in the user file
1392 * @brief USB Reset callback.
1393 * @param hpcd PCD handle
1396 __weak
void HAL_PCD_ResetCallback(PCD_HandleTypeDef
*hpcd
)
1398 /* Prevent unused argument(s) compilation warning */
1401 /* NOTE : This function should not be modified, when the callback is needed,
1402 the HAL_PCD_ResetCallback could be implemented in the user file
1407 * @brief Suspend event callback.
1408 * @param hpcd PCD handle
1411 __weak
void HAL_PCD_SuspendCallback(PCD_HandleTypeDef
*hpcd
)
1413 /* Prevent unused argument(s) compilation warning */
1416 /* NOTE : This function should not be modified, when the callback is needed,
1417 the HAL_PCD_SuspendCallback could be implemented in the user file
1422 * @brief Resume event callback.
1423 * @param hpcd PCD handle
1426 __weak
void HAL_PCD_ResumeCallback(PCD_HandleTypeDef
*hpcd
)
1428 /* Prevent unused argument(s) compilation warning */
1431 /* NOTE : This function should not be modified, when the callback is needed,
1432 the HAL_PCD_ResumeCallback could be implemented in the user file
1437 * @brief Incomplete ISO OUT callback.
1438 * @param hpcd PCD handle
1439 * @param epnum endpoint number
1442 __weak
void HAL_PCD_ISOOUTIncompleteCallback(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_ISOOUTIncompleteCallback could be implemented in the user file
1454 * @brief Incomplete ISO IN callback.
1455 * @param hpcd PCD handle
1456 * @param epnum endpoint number
1459 __weak
void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef
*hpcd
, uint8_t epnum
)
1461 /* Prevent unused argument(s) compilation warning */
1465 /* NOTE : This function should not be modified, when the callback is needed,
1466 the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
1471 * @brief Connection event callback.
1472 * @param hpcd PCD handle
1475 __weak
void HAL_PCD_ConnectCallback(PCD_HandleTypeDef
*hpcd
)
1477 /* Prevent unused argument(s) compilation warning */
1480 /* NOTE : This function should not be modified, when the callback is needed,
1481 the HAL_PCD_ConnectCallback could be implemented in the user file
1486 * @brief Disconnection event callback.
1487 * @param hpcd PCD handle
1490 __weak
void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef
*hpcd
)
1492 /* Prevent unused argument(s) compilation warning */
1495 /* NOTE : This function should not be modified, when the callback is needed,
1496 the HAL_PCD_DisconnectCallback could be implemented in the user file
1504 /** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
1505 * @brief management functions
1508 ===============================================================================
1509 ##### Peripheral Control functions #####
1510 ===============================================================================
1512 This subsection provides a set of functions allowing to control the PCD data
1520 * @brief Connect the USB device
1521 * @param hpcd PCD handle
1522 * @retval HAL status
1524 HAL_StatusTypeDef
HAL_PCD_DevConnect(PCD_HandleTypeDef
*hpcd
)
1527 (void)USB_DevConnect(hpcd
->Instance
);
1533 * @brief Disconnect the USB device.
1534 * @param hpcd PCD handle
1535 * @retval HAL status
1537 HAL_StatusTypeDef
HAL_PCD_DevDisconnect(PCD_HandleTypeDef
*hpcd
)
1540 (void)USB_DevDisconnect(hpcd
->Instance
);
1546 * @brief Set the USB Device address.
1547 * @param hpcd PCD handle
1548 * @param address new device address
1549 * @retval HAL status
1551 HAL_StatusTypeDef
HAL_PCD_SetAddress(PCD_HandleTypeDef
*hpcd
, uint8_t address
)
1554 hpcd
->USB_Address
= address
;
1555 (void)USB_SetDevAddress(hpcd
->Instance
, address
);
1560 * @brief Open and configure an endpoint.
1561 * @param hpcd PCD handle
1562 * @param ep_addr endpoint address
1563 * @param ep_mps endpoint max packet size
1564 * @param ep_type endpoint type
1565 * @retval HAL status
1567 HAL_StatusTypeDef
HAL_PCD_EP_Open(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
, uint16_t ep_mps
, uint8_t ep_type
)
1569 HAL_StatusTypeDef ret
= HAL_OK
;
1572 if ((ep_addr
& 0x80U
) == 0x80U
)
1574 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1579 ep
= &hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
];
1583 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1584 ep
->maxpacket
= ep_mps
;
1587 if (ep
->is_in
!= 0U)
1589 /* Assign a Tx FIFO */
1590 ep
->tx_fifo_num
= ep
->num
;
1592 /* Set initial data PID. */
1593 if (ep_type
== EP_TYPE_BULK
)
1595 ep
->data_pid_start
= 0U;
1599 (void)USB_ActivateEndpoint(hpcd
->Instance
, ep
);
1606 * @brief Deactivate an endpoint.
1607 * @param hpcd PCD handle
1608 * @param ep_addr endpoint address
1609 * @retval HAL status
1611 HAL_StatusTypeDef
HAL_PCD_EP_Close(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1615 if ((ep_addr
& 0x80U
) == 0x80U
)
1617 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1622 ep
= &hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
];
1625 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1628 (void)USB_DeactivateEndpoint(hpcd
->Instance
, ep
);
1635 * @brief Receive an amount of data.
1636 * @param hpcd PCD handle
1637 * @param ep_addr endpoint address
1638 * @param pBuf pointer to the reception buffer
1639 * @param len amount of data to be received
1640 * @retval HAL status
1642 HAL_StatusTypeDef
HAL_PCD_EP_Receive(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
, uint8_t *pBuf
, uint32_t len
)
1646 ep
= &hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
];
1648 /*setup and start the Xfer */
1649 ep
->xfer_buff
= pBuf
;
1651 ep
->xfer_count
= 0U;
1653 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1655 if (hpcd
->Init
.dma_enable
== 1U)
1657 ep
->dma_addr
= (uint32_t)pBuf
;
1660 if ((ep_addr
& EP_ADDR_MSK
) == 0U)
1662 (void)USB_EP0StartXfer(hpcd
->Instance
, ep
, (uint8_t)hpcd
->Init
.dma_enable
);
1666 (void)USB_EPStartXfer(hpcd
->Instance
, ep
, (uint8_t)hpcd
->Init
.dma_enable
);
1673 * @brief Get Received Data Size
1674 * @param hpcd PCD handle
1675 * @param ep_addr endpoint address
1678 uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1680 return hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
].xfer_count
;
1683 * @brief Send an amount of data
1684 * @param hpcd PCD handle
1685 * @param ep_addr endpoint address
1686 * @param pBuf pointer to the transmission buffer
1687 * @param len amount of data to be sent
1688 * @retval HAL status
1690 HAL_StatusTypeDef
HAL_PCD_EP_Transmit(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
, uint8_t *pBuf
, uint32_t len
)
1694 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1696 /*setup and start the Xfer */
1697 ep
->xfer_buff
= pBuf
;
1699 ep
->xfer_count
= 0U;
1701 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1703 if (hpcd
->Init
.dma_enable
== 1U)
1705 ep
->dma_addr
= (uint32_t)pBuf
;
1708 if ((ep_addr
& EP_ADDR_MSK
) == 0U)
1710 (void)USB_EP0StartXfer(hpcd
->Instance
, ep
, (uint8_t)hpcd
->Init
.dma_enable
);
1714 (void)USB_EPStartXfer(hpcd
->Instance
, ep
, (uint8_t)hpcd
->Init
.dma_enable
);
1721 * @brief Set a STALL condition over an endpoint
1722 * @param hpcd PCD handle
1723 * @param ep_addr endpoint address
1724 * @retval HAL status
1726 HAL_StatusTypeDef
HAL_PCD_EP_SetStall(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1730 if (((uint32_t)ep_addr
& EP_ADDR_MSK
) > hpcd
->Init
.dev_endpoints
)
1735 if ((0x80U
& ep_addr
) == 0x80U
)
1737 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1742 ep
= &hpcd
->OUT_ep
[ep_addr
];
1747 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1751 (void)USB_EPSetStall(hpcd
->Instance
, ep
);
1752 if ((ep_addr
& EP_ADDR_MSK
) == 0U)
1754 (void)USB_EP0_OutStart(hpcd
->Instance
, (uint8_t)hpcd
->Init
.dma_enable
, (uint8_t *)hpcd
->Setup
);
1762 * @brief Clear a STALL condition over in an endpoint
1763 * @param hpcd PCD handle
1764 * @param ep_addr endpoint address
1765 * @retval HAL status
1767 HAL_StatusTypeDef
HAL_PCD_EP_ClrStall(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1771 if (((uint32_t)ep_addr
& 0x0FU
) > hpcd
->Init
.dev_endpoints
)
1776 if ((0x80U
& ep_addr
) == 0x80U
)
1778 ep
= &hpcd
->IN_ep
[ep_addr
& EP_ADDR_MSK
];
1783 ep
= &hpcd
->OUT_ep
[ep_addr
& EP_ADDR_MSK
];
1788 ep
->num
= ep_addr
& EP_ADDR_MSK
;
1791 (void)USB_EPClearStall(hpcd
->Instance
, ep
);
1798 * @brief Flush an endpoint
1799 * @param hpcd PCD handle
1800 * @param ep_addr endpoint address
1801 * @retval HAL status
1803 HAL_StatusTypeDef
HAL_PCD_EP_Flush(PCD_HandleTypeDef
*hpcd
, uint8_t ep_addr
)
1807 if ((ep_addr
& 0x80U
) == 0x80U
)
1809 (void)USB_FlushTxFifo(hpcd
->Instance
, (uint32_t)ep_addr
& EP_ADDR_MSK
);
1813 (void)USB_FlushRxFifo(hpcd
->Instance
);
1822 * @brief Activate remote wakeup signalling
1823 * @param hpcd PCD handle
1824 * @retval HAL status
1826 HAL_StatusTypeDef
HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef
*hpcd
)
1828 return (USB_ActivateRemoteWakeup(hpcd
->Instance
));
1832 * @brief De-activate remote wakeup signalling.
1833 * @param hpcd PCD handle
1834 * @retval HAL status
1836 HAL_StatusTypeDef
HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef
*hpcd
)
1838 return (USB_DeActivateRemoteWakeup(hpcd
->Instance
));
1845 /** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
1846 * @brief Peripheral State functions
1849 ===============================================================================
1850 ##### Peripheral State functions #####
1851 ===============================================================================
1853 This subsection permits to get in run-time the status of the peripheral
1861 * @brief Return the PCD handle state.
1862 * @param hpcd PCD handle
1865 PCD_StateTypeDef
HAL_PCD_GetState(PCD_HandleTypeDef
*hpcd
)
1878 /* Private functions ---------------------------------------------------------*/
1879 /** @addtogroup PCD_Private_Functions
1882 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
1884 * @brief Check FIFO for the next packet to be loaded.
1885 * @param hpcd PCD handle
1886 * @param epnum endpoint number
1887 * @retval HAL status
1889 static HAL_StatusTypeDef
PCD_WriteEmptyTxFifo(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
)
1891 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
1892 uint32_t USBx_BASE
= (uint32_t)USBx
;
1893 USB_OTG_EPTypeDef
*ep
;
1896 uint32_t fifoemptymsk
;
1898 ep
= &hpcd
->IN_ep
[epnum
];
1900 if (ep
->xfer_count
> ep
->xfer_len
)
1905 len
= ep
->xfer_len
- ep
->xfer_count
;
1907 if (len
> ep
->maxpacket
)
1909 len
= ep
->maxpacket
;
1912 len32b
= (len
+ 3U) / 4U;
1914 while (((USBx_INEP(epnum
)->DTXFSTS
& USB_OTG_DTXFSTS_INEPTFSAV
) >= len32b
) &&
1915 (ep
->xfer_count
< ep
->xfer_len
) && (ep
->xfer_len
!= 0U))
1917 /* Write the FIFO */
1918 len
= ep
->xfer_len
- ep
->xfer_count
;
1920 if (len
> ep
->maxpacket
)
1922 len
= ep
->maxpacket
;
1924 len32b
= (len
+ 3U) / 4U;
1926 (void)USB_WritePacket(USBx
, ep
->xfer_buff
, (uint8_t)epnum
, (uint16_t)len
,
1927 (uint8_t)hpcd
->Init
.dma_enable
);
1929 ep
->xfer_buff
+= len
;
1930 ep
->xfer_count
+= len
;
1933 if (ep
->xfer_len
<= ep
->xfer_count
)
1935 fifoemptymsk
= (uint32_t)(0x1UL
<< (epnum
& EP_ADDR_MSK
));
1936 USBx_DEVICE
->DIEPEMPMSK
&= ~fifoemptymsk
;
1944 * @brief process EP OUT transfer complete interrupt.
1945 * @param hpcd PCD handle
1946 * @param epnum endpoint number
1947 * @retval HAL status
1949 static HAL_StatusTypeDef
PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
)
1951 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
1952 uint32_t USBx_BASE
= (uint32_t)USBx
;
1953 uint32_t gSNPSiD
= *(__IO
uint32_t *)(&USBx
->CID
+ 0x1U
);
1954 uint32_t DoepintReg
= USBx_OUTEP(epnum
)->DOEPINT
;
1956 if (hpcd
->Init
.dma_enable
== 1U)
1958 if ((DoepintReg
& USB_OTG_DOEPINT_STUP
) == USB_OTG_DOEPINT_STUP
) /* Class C */
1960 /* StupPktRcvd = 1 this is a setup packet */
1961 if ((gSNPSiD
> USB_OTG_CORE_ID_300A
) &&
1962 ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
))
1964 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
1967 /* Inform the upper layer that a setup packet is available */
1968 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1969 hpcd
->SetupStageCallback(hpcd
);
1971 HAL_PCD_SetupStageCallback(hpcd
);
1972 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
1974 (void)USB_EP0_OutStart(hpcd
->Instance
, 1U, (uint8_t *)hpcd
->Setup
);
1975 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STUP
);
1977 else if ((DoepintReg
& USB_OTG_DOEPINT_OTEPSPR
) == USB_OTG_DOEPINT_OTEPSPR
) /* Class E */
1979 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_OTEPSPR
);
1981 else if ((DoepintReg
& (USB_OTG_DOEPINT_STUP
| USB_OTG_DOEPINT_OTEPSPR
)) == 0U)
1983 /* StupPktRcvd = 1 this is a setup packet */
1984 if ((gSNPSiD
> USB_OTG_CORE_ID_300A
) &&
1985 ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
))
1987 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
1991 /* out data packet received over EP0 */
1992 hpcd
->OUT_ep
[epnum
].xfer_count
=
1993 hpcd
->OUT_ep
[epnum
].maxpacket
-
1994 (USBx_OUTEP(epnum
)->DOEPTSIZ
& USB_OTG_DOEPTSIZ_XFRSIZ
);
1996 hpcd
->OUT_ep
[epnum
].xfer_buff
+= hpcd
->OUT_ep
[epnum
].maxpacket
;
1998 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
1999 hpcd
->DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2001 HAL_PCD_DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2002 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2004 if ((epnum
== 0U) && (hpcd
->OUT_ep
[epnum
].xfer_len
== 0U))
2006 /* this is ZLP, so prepare EP0 for next setup */
2007 (void)USB_EP0_OutStart(hpcd
->Instance
, 1U, (uint8_t *)hpcd
->Setup
);
2018 if (gSNPSiD
== USB_OTG_CORE_ID_310A
)
2020 /* StupPktRcvd = 1 this is a setup packet */
2021 if ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
)
2023 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
2027 if ((DoepintReg
& USB_OTG_DOEPINT_OTEPSPR
) == USB_OTG_DOEPINT_OTEPSPR
)
2029 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_OTEPSPR
);
2032 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2033 hpcd
->DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2035 HAL_PCD_DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2036 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2041 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2042 hpcd
->DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2044 HAL_PCD_DataOutStageCallback(hpcd
, (uint8_t)epnum
);
2045 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2054 * @brief process EP OUT setup packet received interrupt.
2055 * @param hpcd PCD handle
2056 * @param epnum endpoint number
2057 * @retval HAL status
2059 static HAL_StatusTypeDef
PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef
*hpcd
, uint32_t epnum
)
2061 USB_OTG_GlobalTypeDef
*USBx
= hpcd
->Instance
;
2062 uint32_t USBx_BASE
= (uint32_t)USBx
;
2063 uint32_t gSNPSiD
= *(__IO
uint32_t *)(&USBx
->CID
+ 0x1U
);
2064 uint32_t DoepintReg
= USBx_OUTEP(epnum
)->DOEPINT
;
2066 if (hpcd
->Init
.dma_enable
== 1U)
2068 /* StupPktRcvd = 1 pending setup packet int */
2069 if ((gSNPSiD
> USB_OTG_CORE_ID_300A
) &&
2070 ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
))
2072 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
2077 if ((gSNPSiD
== USB_OTG_CORE_ID_310A
) &&
2078 ((DoepintReg
& USB_OTG_DOEPINT_STPKTRX
) == USB_OTG_DOEPINT_STPKTRX
))
2080 CLEAR_OUT_EP_INTR(epnum
, USB_OTG_DOEPINT_STPKTRX
);
2084 /* Inform the upper layer that a setup packet is available */
2085 #if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
2086 hpcd
->SetupStageCallback(hpcd
);
2088 HAL_PCD_SetupStageCallback(hpcd
);
2089 #endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
2091 if ((gSNPSiD
> USB_OTG_CORE_ID_300A
) && (hpcd
->Init
.dma_enable
== 1U))
2093 (void)USB_EP0_OutStart(hpcd
->Instance
, 1U, (uint8_t *)hpcd
->Setup
);
2098 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2104 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
2105 #endif /* HAL_PCD_MODULE_ENABLED */
2115 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/