2 ******************************************************************************
3 * @file stm32h7xx_hal_hcd.c
4 * @author MCD Application Team
5 * @brief HCD 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
13 ******************************************************************************
16 * Copyright (c) 2017 STMicroelectronics.
17 * All rights reserved.
19 * This software is licensed under terms that can be found in the LICENSE file
20 * in the root directory of this software component.
21 * If no LICENSE file comes with this software, it is provided AS-IS.
23 ******************************************************************************
25 ==============================================================================
26 ##### How to use this driver #####
27 ==============================================================================
29 (#)Declare a HCD_HandleTypeDef handle structure, for example:
30 HCD_HandleTypeDef hhcd;
32 (#)Fill parameters of Init structure in HCD handle
34 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
36 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
37 (##) Enable the HCD/USB Low Level interface clock using the following macros
38 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
39 (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
40 (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
42 (##) Initialize the related GPIO clocks
43 (##) Configure HCD pin-out
44 (##) Configure HCD NVIC interrupt
46 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
47 (##) hhcd.pData = phost;
49 (#)Enable HCD transmission and reception:
53 ******************************************************************************
56 /* Includes ------------------------------------------------------------------*/
57 #include "stm32h7xx_hal.h"
59 /** @addtogroup STM32H7xx_HAL_Driver
63 #ifdef HAL_HCD_MODULE_ENABLED
64 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
67 * @brief HCD HAL module driver
71 /* Private typedef -----------------------------------------------------------*/
72 /* Private define ------------------------------------------------------------*/
73 /* Private macro -------------------------------------------------------------*/
74 /* Private variables ---------------------------------------------------------*/
75 /* Private function prototypes -----------------------------------------------*/
76 /** @defgroup HCD_Private_Functions HCD Private Functions
79 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
);
80 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
);
81 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef
*hhcd
);
82 static void HCD_Port_IRQHandler(HCD_HandleTypeDef
*hhcd
);
87 /* Exported functions --------------------------------------------------------*/
88 /** @defgroup HCD_Exported_Functions HCD Exported Functions
92 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
93 * @brief Initialization and Configuration functions
96 ===============================================================================
97 ##### Initialization and de-initialization functions #####
98 ===============================================================================
99 [..] This section provides functions allowing to:
106 * @brief Initialize the host driver.
107 * @param hhcd HCD handle
110 HAL_StatusTypeDef
HAL_HCD_Init(HCD_HandleTypeDef
*hhcd
)
112 /* Check the HCD handle allocation */
118 /* Check the parameters */
119 assert_param(IS_HCD_ALL_INSTANCE(hhcd
->Instance
));
121 if (hhcd
->State
== HAL_HCD_STATE_RESET
)
123 /* Allocate lock resource and initialize it */
124 hhcd
->Lock
= HAL_UNLOCKED
;
126 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
127 hhcd
->SOFCallback
= HAL_HCD_SOF_Callback
;
128 hhcd
->ConnectCallback
= HAL_HCD_Connect_Callback
;
129 hhcd
->DisconnectCallback
= HAL_HCD_Disconnect_Callback
;
130 hhcd
->PortEnabledCallback
= HAL_HCD_PortEnabled_Callback
;
131 hhcd
->PortDisabledCallback
= HAL_HCD_PortDisabled_Callback
;
132 hhcd
->HC_NotifyURBChangeCallback
= HAL_HCD_HC_NotifyURBChange_Callback
;
134 if (hhcd
->MspInitCallback
== NULL
)
136 hhcd
->MspInitCallback
= HAL_HCD_MspInit
;
139 /* Init the low level hardware */
140 hhcd
->MspInitCallback(hhcd
);
142 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
143 HAL_HCD_MspInit(hhcd
);
144 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
147 hhcd
->State
= HAL_HCD_STATE_BUSY
;
149 /* Disable the Interrupts */
150 __HAL_HCD_DISABLE(hhcd
);
152 /* Init the Core (common init.) */
153 if (USB_CoreInit(hhcd
->Instance
, hhcd
->Init
) != HAL_OK
)
155 hhcd
->State
= HAL_HCD_STATE_ERROR
;
159 /* Force Host Mode */
160 if (USB_SetCurrentMode(hhcd
->Instance
, USB_HOST_MODE
) != HAL_OK
)
162 hhcd
->State
= HAL_HCD_STATE_ERROR
;
167 if (USB_HostInit(hhcd
->Instance
, hhcd
->Init
) != HAL_OK
)
169 hhcd
->State
= HAL_HCD_STATE_ERROR
;
173 hhcd
->State
= HAL_HCD_STATE_READY
;
179 * @brief Initialize a host channel.
180 * @param hhcd HCD handle
181 * @param ch_num Channel number.
182 * This parameter can be a value from 1 to 15
183 * @param epnum Endpoint number.
184 * This parameter can be a value from 1 to 15
185 * @param dev_address Current device address
186 * This parameter can be a value from 0 to 255
187 * @param speed Current device speed.
188 * This parameter can be one of these values:
189 * HCD_DEVICE_SPEED_HIGH: High speed mode,
190 * HCD_DEVICE_SPEED_FULL: Full speed mode,
191 * HCD_DEVICE_SPEED_LOW: Low speed mode
192 * @param ep_type Endpoint Type.
193 * This parameter can be one of these values:
194 * EP_TYPE_CTRL: Control type,
195 * EP_TYPE_ISOC: Isochronous type,
196 * EP_TYPE_BULK: Bulk type,
197 * EP_TYPE_INTR: Interrupt type
198 * @param mps Max Packet Size.
199 * This parameter can be a value from 0 to32K
202 HAL_StatusTypeDef
HAL_HCD_HC_Init(HCD_HandleTypeDef
*hhcd
, uint8_t ch_num
, uint8_t epnum
,
203 uint8_t dev_address
, uint8_t speed
, uint8_t ep_type
, uint16_t mps
)
205 HAL_StatusTypeDef status
;
206 uint32_t HostCoreSpeed
;
207 uint32_t HCcharMps
= mps
;
210 hhcd
->hc
[ch_num
].do_ping
= 0U;
211 hhcd
->hc
[ch_num
].dev_addr
= dev_address
;
212 hhcd
->hc
[ch_num
].ch_num
= ch_num
;
213 hhcd
->hc
[ch_num
].ep_type
= ep_type
;
214 hhcd
->hc
[ch_num
].ep_num
= epnum
& 0x7FU
;
216 (void)HAL_HCD_HC_ClearHubInfo(hhcd
, ch_num
);
218 if ((epnum
& 0x80U
) == 0x80U
)
220 hhcd
->hc
[ch_num
].ep_is_in
= 1U;
224 hhcd
->hc
[ch_num
].ep_is_in
= 0U;
227 HostCoreSpeed
= USB_GetHostSpeed(hhcd
->Instance
);
229 if (ep_type
== EP_TYPE_ISOC
)
231 /* FS device plugged to HS HUB */
232 if ((speed
== HCD_DEVICE_SPEED_FULL
) && (HostCoreSpeed
== HPRT0_PRTSPD_HIGH_SPEED
))
234 if (HCcharMps
> ISO_SPLT_MPS
)
236 /* ISO Max Packet Size for Split mode */
237 HCcharMps
= ISO_SPLT_MPS
;
242 hhcd
->hc
[ch_num
].speed
= speed
;
243 hhcd
->hc
[ch_num
].max_packet
= (uint16_t)HCcharMps
;
245 status
= USB_HC_Init(hhcd
->Instance
, ch_num
, epnum
,
246 dev_address
, speed
, ep_type
, (uint16_t)HCcharMps
);
254 * @brief Halt a host channel.
255 * @param hhcd HCD handle
256 * @param ch_num Channel number.
257 * This parameter can be a value from 1 to 15
260 HAL_StatusTypeDef
HAL_HCD_HC_Halt(HCD_HandleTypeDef
*hhcd
, uint8_t ch_num
)
262 HAL_StatusTypeDef status
= HAL_OK
;
265 (void)USB_HC_Halt(hhcd
->Instance
, ch_num
);
272 * @brief DeInitialize the host driver.
273 * @param hhcd HCD handle
276 HAL_StatusTypeDef
HAL_HCD_DeInit(HCD_HandleTypeDef
*hhcd
)
278 /* Check the HCD handle allocation */
284 hhcd
->State
= HAL_HCD_STATE_BUSY
;
286 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
287 if (hhcd
->MspDeInitCallback
== NULL
)
289 hhcd
->MspDeInitCallback
= HAL_HCD_MspDeInit
; /* Legacy weak MspDeInit */
292 /* DeInit the low level hardware */
293 hhcd
->MspDeInitCallback(hhcd
);
295 /* DeInit the low level hardware: CLOCK, NVIC.*/
296 HAL_HCD_MspDeInit(hhcd
);
297 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
299 __HAL_HCD_DISABLE(hhcd
);
301 hhcd
->State
= HAL_HCD_STATE_RESET
;
307 * @brief Initialize the HCD MSP.
308 * @param hhcd HCD handle
311 __weak
void HAL_HCD_MspInit(HCD_HandleTypeDef
*hhcd
)
313 /* Prevent unused argument(s) compilation warning */
316 /* NOTE : This function should not be modified, when the callback is needed,
317 the HAL_HCD_MspInit could be implemented in the user file
322 * @brief DeInitialize the HCD MSP.
323 * @param hhcd HCD handle
326 __weak
void HAL_HCD_MspDeInit(HCD_HandleTypeDef
*hhcd
)
328 /* Prevent unused argument(s) compilation warning */
331 /* NOTE : This function should not be modified, when the callback is needed,
332 the HAL_HCD_MspDeInit could be implemented in the user file
340 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
341 * @brief HCD IO operation functions
344 ===============================================================================
345 ##### IO operation functions #####
346 ===============================================================================
347 [..] This subsection provides a set of functions allowing to manage the USB Host Data
355 * @brief Submit a new URB for processing.
356 * @param hhcd HCD handle
357 * @param ch_num Channel number.
358 * This parameter can be a value from 1 to 15
359 * @param direction Channel number.
360 * This parameter can be one of these values:
361 * 0 : Output / 1 : Input
362 * @param ep_type Endpoint Type.
363 * This parameter can be one of these values:
364 * EP_TYPE_CTRL: Control type/
365 * EP_TYPE_ISOC: Isochronous type/
366 * EP_TYPE_BULK: Bulk type/
367 * EP_TYPE_INTR: Interrupt type/
368 * @param token Endpoint Type.
369 * This parameter can be one of these values:
370 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
371 * @param pbuff pointer to URB data
372 * @param length Length of URB data
373 * @param do_ping activate do ping protocol (for high speed only).
374 * This parameter can be one of these values:
375 * 0 : do ping inactive / 1 : do ping active
378 HAL_StatusTypeDef
HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef
*hhcd
,
387 hhcd
->hc
[ch_num
].ep_is_in
= direction
;
388 hhcd
->hc
[ch_num
].ep_type
= ep_type
;
392 hhcd
->hc
[ch_num
].data_pid
= HC_PID_SETUP
;
393 hhcd
->hc
[ch_num
].do_ping
= do_ping
;
397 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
400 /* Manage Data Toggle */
404 if (token
== 1U) /* send data */
410 /* For Status OUT stage, Length == 0U, Status Out PID = 1 */
411 hhcd
->hc
[ch_num
].toggle_out
= 1U;
414 /* Set the Data Toggle bit as per the Flag */
415 if (hhcd
->hc
[ch_num
].toggle_out
== 0U)
418 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
423 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
428 if (hhcd
->hc
[ch_num
].do_ssplit
== 1U)
430 if (hhcd
->hc
[ch_num
].toggle_in
== 0U)
432 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
436 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
446 /* Set the Data Toggle bit as per the Flag */
447 if (hhcd
->hc
[ch_num
].toggle_out
== 0U)
450 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
455 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
460 if (hhcd
->hc
[ch_num
].toggle_in
== 0U)
462 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
466 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
474 /* Set the Data Toggle bit as per the Flag */
475 if (hhcd
->hc
[ch_num
].toggle_out
== 0U)
478 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
483 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
488 if (hhcd
->hc
[ch_num
].toggle_in
== 0U)
490 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
494 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA1
;
500 hhcd
->hc
[ch_num
].data_pid
= HC_PID_DATA0
;
507 hhcd
->hc
[ch_num
].xfer_buff
= pbuff
;
508 hhcd
->hc
[ch_num
].xfer_len
= length
;
509 hhcd
->hc
[ch_num
].urb_state
= URB_IDLE
;
510 hhcd
->hc
[ch_num
].xfer_count
= 0U;
511 hhcd
->hc
[ch_num
].ch_num
= ch_num
;
512 hhcd
->hc
[ch_num
].state
= HC_IDLE
;
514 return USB_HC_StartXfer(hhcd
->Instance
, &hhcd
->hc
[ch_num
], (uint8_t)hhcd
->Init
.dma_enable
);
518 * @brief Handle HCD interrupt request.
519 * @param hhcd HCD handle
522 void HAL_HCD_IRQHandler(HCD_HandleTypeDef
*hhcd
)
524 USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
525 uint32_t USBx_BASE
= (uint32_t)USBx
;
529 /* Ensure that we are in device mode */
530 if (USB_GetMode(hhcd
->Instance
) == USB_OTG_MODE_HOST
)
532 /* Avoid spurious interrupt */
533 if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd
))
538 if (__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
))
540 /* Incorrect mode, acknowledge the interrupt */
541 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT
);
544 if (__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_IISOIXFR
))
546 /* Incorrect mode, acknowledge the interrupt */
547 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_IISOIXFR
);
550 if (__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_PTXFE
))
552 /* Incorrect mode, acknowledge the interrupt */
553 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_PTXFE
);
556 if (__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_MMIS
))
558 /* Incorrect mode, acknowledge the interrupt */
559 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_MMIS
);
562 /* Handle Host Disconnect Interrupts */
563 if (__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_DISCINT
))
565 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_DISCINT
);
567 if ((USBx_HPRT0
& USB_OTG_HPRT_PCSTS
) == 0U)
570 (void)USB_FlushTxFifo(USBx
, 0x10U
);
571 (void)USB_FlushRxFifo(USBx
);
573 if (hhcd
->Init
.phy_itface
== USB_OTG_EMBEDDED_PHY
)
575 /* Restore FS Clock */
576 (void)USB_InitFSLSPClkSel(hhcd
->Instance
, HCFG_48_MHZ
);
579 /* Handle Host Port Disconnect Interrupt */
580 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
581 hhcd
->DisconnectCallback(hhcd
);
583 HAL_HCD_Disconnect_Callback(hhcd
);
584 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
588 /* Handle Host Port Interrupts */
589 if (__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_HPRTINT
))
591 HCD_Port_IRQHandler(hhcd
);
594 /* Handle Host SOF Interrupt */
595 if (__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_SOF
))
597 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
598 hhcd
->SOFCallback(hhcd
);
600 HAL_HCD_SOF_Callback(hhcd
);
601 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
603 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_SOF
);
606 /* Handle Host channel Interrupt */
607 if (__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_HCINT
))
609 interrupt
= USB_HC_ReadInterrupt(hhcd
->Instance
);
610 for (i
= 0U; i
< hhcd
->Init
.Host_channels
; i
++)
612 if ((interrupt
& (1UL << (i
& 0xFU
))) != 0U)
614 if ((USBx_HC(i
)->HCCHAR
& USB_OTG_HCCHAR_EPDIR
) == USB_OTG_HCCHAR_EPDIR
)
616 HCD_HC_IN_IRQHandler(hhcd
, (uint8_t)i
);
620 HCD_HC_OUT_IRQHandler(hhcd
, (uint8_t)i
);
624 __HAL_HCD_CLEAR_FLAG(hhcd
, USB_OTG_GINTSTS_HCINT
);
627 /* Handle Rx Queue Level Interrupts */
628 if ((__HAL_HCD_GET_FLAG(hhcd
, USB_OTG_GINTSTS_RXFLVL
)) != 0U)
630 USB_MASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
632 HCD_RXQLVL_IRQHandler(hhcd
);
634 USB_UNMASK_INTERRUPT(hhcd
->Instance
, USB_OTG_GINTSTS_RXFLVL
);
641 * @brief SOF callback.
642 * @param hhcd HCD handle
645 __weak
void HAL_HCD_SOF_Callback(HCD_HandleTypeDef
*hhcd
)
647 /* Prevent unused argument(s) compilation warning */
650 /* NOTE : This function should not be modified, when the callback is needed,
651 the HAL_HCD_SOF_Callback could be implemented in the user file
656 * @brief Connection Event callback.
657 * @param hhcd HCD handle
660 __weak
void HAL_HCD_Connect_Callback(HCD_HandleTypeDef
*hhcd
)
662 /* Prevent unused argument(s) compilation warning */
665 /* NOTE : This function should not be modified, when the callback is needed,
666 the HAL_HCD_Connect_Callback could be implemented in the user file
671 * @brief Disconnection Event callback.
672 * @param hhcd HCD handle
675 __weak
void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef
*hhcd
)
677 /* Prevent unused argument(s) compilation warning */
680 /* NOTE : This function should not be modified, when the callback is needed,
681 the HAL_HCD_Disconnect_Callback could be implemented in the user file
686 * @brief Port Enabled Event callback.
687 * @param hhcd HCD handle
690 __weak
void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef
*hhcd
)
692 /* Prevent unused argument(s) compilation warning */
695 /* NOTE : This function should not be modified, when the callback is needed,
696 the HAL_HCD_Disconnect_Callback could be implemented in the user file
701 * @brief Port Disabled Event callback.
702 * @param hhcd HCD handle
705 __weak
void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef
*hhcd
)
707 /* Prevent unused argument(s) compilation warning */
710 /* NOTE : This function should not be modified, when the callback is needed,
711 the HAL_HCD_Disconnect_Callback could be implemented in the user file
716 * @brief Notify URB state change callback.
717 * @param hhcd HCD handle
718 * @param chnum Channel number.
719 * This parameter can be a value from 1 to 15
721 * This parameter can be one of these values:
730 __weak
void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
, HCD_URBStateTypeDef urb_state
)
732 /* Prevent unused argument(s) compilation warning */
737 /* NOTE : This function should not be modified, when the callback is needed,
738 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
742 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
744 * @brief Register a User USB HCD Callback
745 * To be used instead of the weak predefined callback
746 * @param hhcd USB HCD handle
747 * @param CallbackID ID of the callback to be registered
748 * This parameter can be one of the following values:
749 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
750 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
751 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
752 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
753 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
754 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
755 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
756 * @param pCallback pointer to the Callback function
759 HAL_StatusTypeDef
HAL_HCD_RegisterCallback(HCD_HandleTypeDef
*hhcd
,
760 HAL_HCD_CallbackIDTypeDef CallbackID
,
761 pHCD_CallbackTypeDef pCallback
)
763 HAL_StatusTypeDef status
= HAL_OK
;
765 if (pCallback
== NULL
)
767 /* Update the error code */
768 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
774 if (hhcd
->State
== HAL_HCD_STATE_READY
)
778 case HAL_HCD_SOF_CB_ID
:
779 hhcd
->SOFCallback
= pCallback
;
782 case HAL_HCD_CONNECT_CB_ID
:
783 hhcd
->ConnectCallback
= pCallback
;
786 case HAL_HCD_DISCONNECT_CB_ID
:
787 hhcd
->DisconnectCallback
= pCallback
;
790 case HAL_HCD_PORT_ENABLED_CB_ID
:
791 hhcd
->PortEnabledCallback
= pCallback
;
794 case HAL_HCD_PORT_DISABLED_CB_ID
:
795 hhcd
->PortDisabledCallback
= pCallback
;
798 case HAL_HCD_MSPINIT_CB_ID
:
799 hhcd
->MspInitCallback
= pCallback
;
802 case HAL_HCD_MSPDEINIT_CB_ID
:
803 hhcd
->MspDeInitCallback
= pCallback
;
807 /* Update the error code */
808 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
809 /* Return error status */
814 else if (hhcd
->State
== HAL_HCD_STATE_RESET
)
818 case HAL_HCD_MSPINIT_CB_ID
:
819 hhcd
->MspInitCallback
= pCallback
;
822 case HAL_HCD_MSPDEINIT_CB_ID
:
823 hhcd
->MspDeInitCallback
= pCallback
;
827 /* Update the error code */
828 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
829 /* Return error status */
836 /* Update the error code */
837 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
838 /* Return error status */
848 * @brief Unregister an USB HCD Callback
849 * USB HCD callback is redirected to the weak predefined callback
850 * @param hhcd USB HCD handle
851 * @param CallbackID ID of the callback to be unregistered
852 * This parameter can be one of the following values:
853 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
854 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
855 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
856 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
857 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
858 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
859 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
862 HAL_StatusTypeDef
HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef
*hhcd
, HAL_HCD_CallbackIDTypeDef CallbackID
)
864 HAL_StatusTypeDef status
= HAL_OK
;
869 /* Setup Legacy weak Callbacks */
870 if (hhcd
->State
== HAL_HCD_STATE_READY
)
874 case HAL_HCD_SOF_CB_ID
:
875 hhcd
->SOFCallback
= HAL_HCD_SOF_Callback
;
878 case HAL_HCD_CONNECT_CB_ID
:
879 hhcd
->ConnectCallback
= HAL_HCD_Connect_Callback
;
882 case HAL_HCD_DISCONNECT_CB_ID
:
883 hhcd
->DisconnectCallback
= HAL_HCD_Disconnect_Callback
;
886 case HAL_HCD_PORT_ENABLED_CB_ID
:
887 hhcd
->PortEnabledCallback
= HAL_HCD_PortEnabled_Callback
;
890 case HAL_HCD_PORT_DISABLED_CB_ID
:
891 hhcd
->PortDisabledCallback
= HAL_HCD_PortDisabled_Callback
;
894 case HAL_HCD_MSPINIT_CB_ID
:
895 hhcd
->MspInitCallback
= HAL_HCD_MspInit
;
898 case HAL_HCD_MSPDEINIT_CB_ID
:
899 hhcd
->MspDeInitCallback
= HAL_HCD_MspDeInit
;
903 /* Update the error code */
904 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
906 /* Return error status */
911 else if (hhcd
->State
== HAL_HCD_STATE_RESET
)
915 case HAL_HCD_MSPINIT_CB_ID
:
916 hhcd
->MspInitCallback
= HAL_HCD_MspInit
;
919 case HAL_HCD_MSPDEINIT_CB_ID
:
920 hhcd
->MspDeInitCallback
= HAL_HCD_MspDeInit
;
924 /* Update the error code */
925 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
927 /* Return error status */
934 /* Update the error code */
935 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
937 /* Return error status */
947 * @brief Register USB HCD Host Channel Notify URB Change Callback
948 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
949 * @param hhcd HCD handle
950 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
953 HAL_StatusTypeDef
HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef
*hhcd
,
954 pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback
)
956 HAL_StatusTypeDef status
= HAL_OK
;
958 if (pCallback
== NULL
)
960 /* Update the error code */
961 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
969 if (hhcd
->State
== HAL_HCD_STATE_READY
)
971 hhcd
->HC_NotifyURBChangeCallback
= pCallback
;
975 /* Update the error code */
976 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
978 /* Return error status */
989 * @brief Unregister the USB HCD Host Channel Notify URB Change Callback
990 * USB HCD Host Channel Notify URB Change Callback is redirected
991 * to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
992 * @param hhcd HCD handle
995 HAL_StatusTypeDef
HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef
*hhcd
)
997 HAL_StatusTypeDef status
= HAL_OK
;
1002 if (hhcd
->State
== HAL_HCD_STATE_READY
)
1004 hhcd
->HC_NotifyURBChangeCallback
= HAL_HCD_HC_NotifyURBChange_Callback
; /* Legacy weak DataOutStageCallback */
1008 /* Update the error code */
1009 hhcd
->ErrorCode
|= HAL_HCD_ERROR_INVALID_CALLBACK
;
1011 /* Return error status */
1020 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1026 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
1027 * @brief Management functions
1030 ===============================================================================
1031 ##### Peripheral Control functions #####
1032 ===============================================================================
1034 This subsection provides a set of functions allowing to control the HCD data
1042 * @brief Start the host driver.
1043 * @param hhcd HCD handle
1044 * @retval HAL status
1046 HAL_StatusTypeDef
HAL_HCD_Start(HCD_HandleTypeDef
*hhcd
)
1049 /* Enable port power */
1050 (void)USB_DriveVbus(hhcd
->Instance
, 1U);
1052 /* Enable global interrupt */
1053 __HAL_HCD_ENABLE(hhcd
);
1060 * @brief Stop the host driver.
1061 * @param hhcd HCD handle
1062 * @retval HAL status
1065 HAL_StatusTypeDef
HAL_HCD_Stop(HCD_HandleTypeDef
*hhcd
)
1068 (void)USB_StopHost(hhcd
->Instance
);
1075 * @brief Reset the host port.
1076 * @param hhcd HCD handle
1077 * @retval HAL status
1079 HAL_StatusTypeDef
HAL_HCD_ResetPort(HCD_HandleTypeDef
*hhcd
)
1081 return (USB_ResetPort(hhcd
->Instance
));
1088 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1089 * @brief Peripheral State functions
1092 ===============================================================================
1093 ##### Peripheral State functions #####
1094 ===============================================================================
1096 This subsection permits to get in run-time the status of the peripheral
1104 * @brief Return the HCD handle state.
1105 * @param hhcd HCD handle
1108 HCD_StateTypeDef
HAL_HCD_GetState(HCD_HandleTypeDef
const *hhcd
)
1114 * @brief Return URB state for a channel.
1115 * @param hhcd HCD handle
1116 * @param chnum Channel number.
1117 * This parameter can be a value from 1 to 15
1118 * @retval URB state.
1119 * This parameter can be one of these values:
1127 HCD_URBStateTypeDef
HAL_HCD_HC_GetURBState(HCD_HandleTypeDef
const *hhcd
, uint8_t chnum
)
1129 return hhcd
->hc
[chnum
].urb_state
;
1134 * @brief Return the last host transfer size.
1135 * @param hhcd HCD handle
1136 * @param chnum Channel number.
1137 * This parameter can be a value from 1 to 15
1138 * @retval last transfer size in byte
1140 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef
const *hhcd
, uint8_t chnum
)
1142 return hhcd
->hc
[chnum
].xfer_count
;
1146 * @brief Return the Host Channel state.
1147 * @param hhcd HCD handle
1148 * @param chnum Channel number.
1149 * This parameter can be a value from 1 to 15
1150 * @retval Host channel state
1151 * This parameter can be one of these values:
1162 HCD_HCStateTypeDef
HAL_HCD_HC_GetState(HCD_HandleTypeDef
const *hhcd
, uint8_t chnum
)
1164 return hhcd
->hc
[chnum
].state
;
1168 * @brief Return the current Host frame number.
1169 * @param hhcd HCD handle
1170 * @retval Current Host frame number
1172 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef
*hhcd
)
1174 return (USB_GetCurrentFrame(hhcd
->Instance
));
1178 * @brief Return the Host enumeration speed.
1179 * @param hhcd HCD handle
1180 * @retval Enumeration speed
1182 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef
*hhcd
)
1184 return (USB_GetHostSpeed(hhcd
->Instance
));
1188 * @brief Set host channel Hub information.
1189 * @param hhcd HCD handle
1190 * @param ch_num Channel number.
1191 * This parameter can be a value from 1 to 15
1192 * @param addr Hub address
1193 * @param PortNbr Hub port number
1194 * @retval HAL status
1196 HAL_StatusTypeDef
HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef
*hhcd
, uint8_t ch_num
,
1197 uint8_t addr
, uint8_t PortNbr
)
1199 uint32_t HostCoreSpeed
= USB_GetHostSpeed(hhcd
->Instance
);
1201 /* LS/FS device plugged to HS HUB */
1202 if ((hhcd
->hc
[ch_num
].speed
!= HCD_DEVICE_SPEED_HIGH
) && (HostCoreSpeed
== HPRT0_PRTSPD_HIGH_SPEED
))
1204 hhcd
->hc
[ch_num
].do_ssplit
= 1U;
1206 if ((hhcd
->hc
[ch_num
].ep_type
== EP_TYPE_CTRL
) && (hhcd
->hc
[ch_num
].ep_is_in
!= 0U))
1208 hhcd
->hc
[ch_num
].toggle_in
= 1U;
1212 hhcd
->hc
[ch_num
].hub_addr
= addr
;
1213 hhcd
->hc
[ch_num
].hub_port_nbr
= PortNbr
;
1220 * @brief Clear host channel hub information.
1221 * @param hhcd HCD handle
1222 * @param ch_num Channel number.
1223 * This parameter can be a value from 1 to 15
1224 * @retval HAL status
1226 HAL_StatusTypeDef
HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef
*hhcd
, uint8_t ch_num
)
1228 hhcd
->hc
[ch_num
].do_ssplit
= 0U;
1229 hhcd
->hc
[ch_num
].do_csplit
= 0U;
1230 hhcd
->hc
[ch_num
].hub_addr
= 0U;
1231 hhcd
->hc
[ch_num
].hub_port_nbr
= 0U;
1243 /** @addtogroup HCD_Private_Functions
1247 * @brief Handle Host Channel IN interrupt requests.
1248 * @param hhcd HCD handle
1249 * @param chnum Channel number.
1250 * This parameter can be a value from 1 to 15
1253 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
1255 const USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1256 uint32_t USBx_BASE
= (uint32_t)USBx
;
1259 if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_AHBERR
))
1261 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_AHBERR
);
1262 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
1263 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1265 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_BBERR
))
1267 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_BBERR
);
1268 hhcd
->hc
[chnum
].state
= HC_BBLERR
;
1269 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1271 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_STALL
))
1273 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_STALL
);
1274 hhcd
->hc
[chnum
].state
= HC_STALL
;
1275 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1277 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_DTERR
))
1279 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_DTERR
);
1280 hhcd
->hc
[chnum
].state
= HC_DATATGLERR
;
1281 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1283 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_TXERR
))
1285 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_TXERR
);
1286 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
1287 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1294 if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_FRMOR
))
1296 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1297 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_FRMOR
);
1299 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_XFRC
))
1301 /* Clear any pending ACK IT */
1302 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_ACK
);
1304 if (hhcd
->hc
[chnum
].do_csplit
== 1U)
1306 hhcd
->hc
[chnum
].do_csplit
= 0U;
1307 __HAL_HCD_CLEAR_HC_CSPLT(chnum
);
1310 if (hhcd
->Init
.dma_enable
!= 0U)
1312 hhcd
->hc
[chnum
].xfer_count
= hhcd
->hc
[chnum
].XferSize
- (USBx_HC(chnum
)->HCTSIZ
& USB_OTG_HCTSIZ_XFRSIZ
);
1315 hhcd
->hc
[chnum
].state
= HC_XFRC
;
1316 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1317 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_XFRC
);
1319 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
) ||
1320 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
1322 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1323 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
1325 else if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
) ||
1326 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_ISOC
))
1328 USBx_HC(chnum
)->HCCHAR
|= USB_OTG_HCCHAR_ODDFRM
;
1329 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
1331 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1332 hhcd
->HC_NotifyURBChangeCallback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1334 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1335 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1342 if (hhcd
->Init
.dma_enable
== 1U)
1344 if ((((hhcd
->hc
[chnum
].xfer_count
+ hhcd
->hc
[chnum
].max_packet
- 1U) / hhcd
->hc
[chnum
].max_packet
) & 1U) != 0U)
1346 hhcd
->hc
[chnum
].toggle_in
^= 1U;
1351 hhcd
->hc
[chnum
].toggle_in
^= 1U;
1354 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_ACK
))
1356 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_ACK
);
1358 if (hhcd
->hc
[chnum
].do_ssplit
== 1U)
1360 hhcd
->hc
[chnum
].do_csplit
= 1U;
1361 hhcd
->hc
[chnum
].state
= HC_ACK
;
1363 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1366 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_CHH
))
1368 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_CHH
);
1370 if (hhcd
->hc
[chnum
].state
== HC_XFRC
)
1372 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1373 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
1375 else if (hhcd
->hc
[chnum
].state
== HC_STALL
)
1377 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1378 hhcd
->hc
[chnum
].urb_state
= URB_STALL
;
1380 else if ((hhcd
->hc
[chnum
].state
== HC_XACTERR
) ||
1381 (hhcd
->hc
[chnum
].state
== HC_DATATGLERR
))
1383 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1384 hhcd
->hc
[chnum
].ErrCnt
++;
1385 if (hhcd
->hc
[chnum
].ErrCnt
> 2U)
1387 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1389 if (hhcd
->hc
[chnum
].do_ssplit
== 1U)
1391 hhcd
->hc
[chnum
].do_csplit
= 0U;
1392 hhcd
->hc
[chnum
].ep_ss_schedule
= 0U;
1393 __HAL_HCD_CLEAR_HC_CSPLT(chnum
);
1396 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1400 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1402 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
) ||
1403 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
1405 /* re-activate the channel */
1406 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1407 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1408 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1409 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1413 else if (hhcd
->hc
[chnum
].state
== HC_NYET
)
1415 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1417 if (hhcd
->hc
[chnum
].do_csplit
== 1U)
1419 if (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
)
1421 hhcd
->hc
[chnum
].NyetErrCnt
++;
1422 if (hhcd
->hc
[chnum
].NyetErrCnt
> 2U)
1424 hhcd
->hc
[chnum
].NyetErrCnt
= 0U;
1425 hhcd
->hc
[chnum
].do_csplit
= 0U;
1427 if (hhcd
->hc
[chnum
].ErrCnt
< 3U)
1429 hhcd
->hc
[chnum
].ep_ss_schedule
= 1U;
1431 __HAL_HCD_CLEAR_HC_CSPLT(chnum
);
1432 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1436 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1441 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1444 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
) ||
1445 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
1447 /* re-activate the channel */
1448 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1449 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1450 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1451 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1455 else if (hhcd
->hc
[chnum
].state
== HC_ACK
)
1457 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1459 if (hhcd
->hc
[chnum
].do_csplit
== 1U)
1461 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1463 /* Set Complete split and re-activate the channel */
1464 USBx_HC(chnum
)->HCSPLT
|= USB_OTG_HCSPLT_COMPLSPLT
;
1465 USBx_HC(chnum
)->HCINTMSK
|= USB_OTG_HCINTMSK_NYET
;
1466 USBx_HC(chnum
)->HCINTMSK
&= ~USB_OTG_HCINT_ACK
;
1468 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
) ||
1469 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
1471 /* re-activate the channel */
1472 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1473 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1474 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1475 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1479 else if (hhcd
->hc
[chnum
].state
== HC_NAK
)
1481 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1482 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1484 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
) ||
1485 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
1487 /* re-activate the channel */
1488 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1489 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1490 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1491 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1494 else if (hhcd
->hc
[chnum
].state
== HC_BBLERR
)
1496 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1497 hhcd
->hc
[chnum
].ErrCnt
++;
1498 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1502 if (hhcd
->hc
[chnum
].state
== HC_HALTED
)
1508 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1509 hhcd
->HC_NotifyURBChangeCallback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1511 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1512 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1514 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_NYET
))
1516 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NYET
);
1517 hhcd
->hc
[chnum
].state
= HC_NYET
;
1519 if (hhcd
->hc
[chnum
].do_ssplit
== 0U)
1521 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1524 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1526 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_NAK
))
1528 if (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
)
1530 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1531 hhcd
->hc
[chnum
].state
= HC_NAK
;
1532 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1534 else if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_CTRL
) ||
1535 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
))
1537 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1539 if ((hhcd
->Init
.dma_enable
== 0U) || (hhcd
->hc
[chnum
].do_csplit
== 1U))
1541 hhcd
->hc
[chnum
].state
= HC_NAK
;
1542 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1550 if (hhcd
->hc
[chnum
].do_csplit
== 1U)
1552 hhcd
->hc
[chnum
].do_csplit
= 0U;
1553 __HAL_HCD_CLEAR_HC_CSPLT(chnum
);
1554 __HAL_HCD_UNMASK_ACK_HC_INT(chnum
);
1557 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
1566 * @brief Handle Host Channel OUT interrupt requests.
1567 * @param hhcd HCD handle
1568 * @param chnum Channel number.
1569 * This parameter can be a value from 1 to 15
1572 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef
*hhcd
, uint8_t chnum
)
1574 const USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1575 uint32_t USBx_BASE
= (uint32_t)USBx
;
1577 uint32_t num_packets
;
1579 if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_AHBERR
))
1581 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_AHBERR
);
1582 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
1583 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1585 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_ACK
))
1587 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_ACK
);
1589 if (hhcd
->hc
[chnum
].do_ping
== 1U)
1591 hhcd
->hc
[chnum
].do_ping
= 0U;
1592 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1593 hhcd
->hc
[chnum
].state
= HC_ACK
;
1594 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1597 if ((hhcd
->hc
[chnum
].do_ssplit
== 1U) && (hhcd
->hc
[chnum
].do_csplit
== 0U))
1599 if (hhcd
->hc
[chnum
].ep_type
!= EP_TYPE_ISOC
)
1601 hhcd
->hc
[chnum
].do_csplit
= 1U;
1604 hhcd
->hc
[chnum
].state
= HC_ACK
;
1605 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1607 /* reset error_count */
1608 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1611 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_FRMOR
))
1613 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_FRMOR
);
1614 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1616 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_XFRC
))
1618 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1620 /* transaction completed with NYET state, update do ping state */
1621 if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_NYET
))
1623 hhcd
->hc
[chnum
].do_ping
= 1U;
1624 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NYET
);
1627 if (hhcd
->hc
[chnum
].do_csplit
!= 0U)
1629 hhcd
->hc
[chnum
].do_csplit
= 0U;
1630 __HAL_HCD_CLEAR_HC_CSPLT(chnum
);
1633 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_XFRC
);
1634 hhcd
->hc
[chnum
].state
= HC_XFRC
;
1635 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1637 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_NYET
))
1639 hhcd
->hc
[chnum
].state
= HC_NYET
;
1641 if (hhcd
->hc
[chnum
].do_ssplit
== 0U)
1643 hhcd
->hc
[chnum
].do_ping
= 1U;
1646 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1647 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1648 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NYET
);
1650 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_STALL
))
1652 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_STALL
);
1653 hhcd
->hc
[chnum
].state
= HC_STALL
;
1654 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1656 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_NAK
))
1658 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1659 hhcd
->hc
[chnum
].state
= HC_NAK
;
1661 if (hhcd
->hc
[chnum
].do_ping
== 0U)
1663 if (hhcd
->hc
[chnum
].speed
== HCD_DEVICE_SPEED_HIGH
)
1665 hhcd
->hc
[chnum
].do_ping
= 1U;
1669 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1670 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_NAK
);
1672 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_TXERR
))
1674 if (hhcd
->Init
.dma_enable
== 0U)
1676 hhcd
->hc
[chnum
].state
= HC_XACTERR
;
1677 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1681 hhcd
->hc
[chnum
].ErrCnt
++;
1682 if (hhcd
->hc
[chnum
].ErrCnt
> 2U)
1684 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1685 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1687 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1688 hhcd
->HC_NotifyURBChangeCallback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1690 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1691 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1695 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1697 /* Re-activate the channel */
1698 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1699 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1700 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1701 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1704 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_TXERR
);
1706 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_DTERR
))
1708 hhcd
->hc
[chnum
].state
= HC_DATATGLERR
;
1709 (void)USB_HC_Halt(hhcd
->Instance
, chnum
);
1710 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_DTERR
);
1712 else if (__HAL_HCD_GET_CH_FLAG(hhcd
, chnum
, USB_OTG_HCINT_CHH
))
1714 __HAL_HCD_CLEAR_HC_INT(chnum
, USB_OTG_HCINT_CHH
);
1716 if (hhcd
->hc
[chnum
].state
== HC_XFRC
)
1718 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1719 hhcd
->hc
[chnum
].urb_state
= URB_DONE
;
1721 if ((hhcd
->hc
[chnum
].ep_type
== EP_TYPE_BULK
) ||
1722 (hhcd
->hc
[chnum
].ep_type
== EP_TYPE_INTR
))
1724 if (hhcd
->Init
.dma_enable
== 0U)
1726 hhcd
->hc
[chnum
].toggle_out
^= 1U;
1729 if ((hhcd
->Init
.dma_enable
== 1U) && (hhcd
->hc
[chnum
].xfer_len
> 0U))
1731 num_packets
= (hhcd
->hc
[chnum
].xfer_len
+ hhcd
->hc
[chnum
].max_packet
- 1U) / hhcd
->hc
[chnum
].max_packet
;
1733 if ((num_packets
& 1U) != 0U)
1735 hhcd
->hc
[chnum
].toggle_out
^= 1U;
1740 else if (hhcd
->hc
[chnum
].state
== HC_ACK
)
1742 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1744 if (hhcd
->hc
[chnum
].do_csplit
== 1U)
1746 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1749 else if (hhcd
->hc
[chnum
].state
== HC_NAK
)
1751 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1752 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1754 if (hhcd
->hc
[chnum
].do_csplit
== 1U)
1756 hhcd
->hc
[chnum
].do_csplit
= 0U;
1757 __HAL_HCD_CLEAR_HC_CSPLT(chnum
);
1760 else if (hhcd
->hc
[chnum
].state
== HC_NYET
)
1762 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1763 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1765 else if (hhcd
->hc
[chnum
].state
== HC_STALL
)
1767 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1768 hhcd
->hc
[chnum
].urb_state
= URB_STALL
;
1770 else if ((hhcd
->hc
[chnum
].state
== HC_XACTERR
) ||
1771 (hhcd
->hc
[chnum
].state
== HC_DATATGLERR
))
1773 hhcd
->hc
[chnum
].state
= HC_HALTED
;
1774 hhcd
->hc
[chnum
].ErrCnt
++;
1775 if (hhcd
->hc
[chnum
].ErrCnt
> 2U)
1777 hhcd
->hc
[chnum
].ErrCnt
= 0U;
1778 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1782 hhcd
->hc
[chnum
].urb_state
= URB_NOTREADY
;
1784 /* re-activate the channel */
1785 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1786 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1787 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1788 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1796 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1797 hhcd
->HC_NotifyURBChangeCallback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1799 HAL_HCD_HC_NotifyURBChange_Callback(hhcd
, chnum
, hhcd
->hc
[chnum
].urb_state
);
1800 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1809 * @brief Handle Rx Queue Level interrupt requests.
1810 * @param hhcd HCD handle
1813 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef
*hhcd
)
1815 const USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1816 uint32_t USBx_BASE
= (uint32_t)USBx
;
1819 uint32_t GrxstspReg
;
1820 uint32_t xferSizePktCnt
;
1824 GrxstspReg
= hhcd
->Instance
->GRXSTSP
;
1825 chnum
= GrxstspReg
& USB_OTG_GRXSTSP_EPNUM
;
1826 pktsts
= (GrxstspReg
& USB_OTG_GRXSTSP_PKTSTS
) >> 17;
1827 pktcnt
= (GrxstspReg
& USB_OTG_GRXSTSP_BCNT
) >> 4;
1831 case GRXSTS_PKTSTS_IN
:
1832 /* Read the data into the host buffer. */
1833 if ((pktcnt
> 0U) && (hhcd
->hc
[chnum
].xfer_buff
!= (void *)0))
1835 if ((hhcd
->hc
[chnum
].xfer_count
+ pktcnt
) <= hhcd
->hc
[chnum
].xfer_len
)
1837 (void)USB_ReadPacket(hhcd
->Instance
,
1838 hhcd
->hc
[chnum
].xfer_buff
, (uint16_t)pktcnt
);
1840 /* manage multiple Xfer */
1841 hhcd
->hc
[chnum
].xfer_buff
+= pktcnt
;
1842 hhcd
->hc
[chnum
].xfer_count
+= pktcnt
;
1844 /* get transfer size packet count */
1845 xferSizePktCnt
= (USBx_HC(chnum
)->HCTSIZ
& USB_OTG_HCTSIZ_PKTCNT
) >> 19;
1847 if ((hhcd
->hc
[chnum
].max_packet
== pktcnt
) && (xferSizePktCnt
> 0U))
1849 /* re-activate the channel when more packets are expected */
1850 tmpreg
= USBx_HC(chnum
)->HCCHAR
;
1851 tmpreg
&= ~USB_OTG_HCCHAR_CHDIS
;
1852 tmpreg
|= USB_OTG_HCCHAR_CHENA
;
1853 USBx_HC(chnum
)->HCCHAR
= tmpreg
;
1854 hhcd
->hc
[chnum
].toggle_in
^= 1U;
1859 hhcd
->hc
[chnum
].urb_state
= URB_ERROR
;
1864 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR
:
1867 case GRXSTS_PKTSTS_IN_XFER_COMP
:
1868 case GRXSTS_PKTSTS_CH_HALTED
:
1875 * @brief Handle Host Port interrupt requests.
1876 * @param hhcd HCD handle
1879 static void HCD_Port_IRQHandler(HCD_HandleTypeDef
*hhcd
)
1881 const USB_OTG_GlobalTypeDef
*USBx
= hhcd
->Instance
;
1882 uint32_t USBx_BASE
= (uint32_t)USBx
;
1883 __IO
uint32_t hprt0
;
1884 __IO
uint32_t hprt0_dup
;
1886 /* Handle Host Port Interrupts */
1888 hprt0_dup
= USBx_HPRT0
;
1890 hprt0_dup
&= ~(USB_OTG_HPRT_PENA
| USB_OTG_HPRT_PCDET
| \
1891 USB_OTG_HPRT_PENCHNG
| USB_OTG_HPRT_POCCHNG
);
1893 /* Check whether Port Connect detected */
1894 if ((hprt0
& USB_OTG_HPRT_PCDET
) == USB_OTG_HPRT_PCDET
)
1896 if ((hprt0
& USB_OTG_HPRT_PCSTS
) == USB_OTG_HPRT_PCSTS
)
1898 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1899 hhcd
->ConnectCallback(hhcd
);
1901 HAL_HCD_Connect_Callback(hhcd
);
1902 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1904 hprt0_dup
|= USB_OTG_HPRT_PCDET
;
1907 /* Check whether Port Enable Changed */
1908 if ((hprt0
& USB_OTG_HPRT_PENCHNG
) == USB_OTG_HPRT_PENCHNG
)
1910 hprt0_dup
|= USB_OTG_HPRT_PENCHNG
;
1912 if ((hprt0
& USB_OTG_HPRT_PENA
) == USB_OTG_HPRT_PENA
)
1914 if (hhcd
->Init
.phy_itface
== USB_OTG_EMBEDDED_PHY
)
1916 if ((hprt0
& USB_OTG_HPRT_PSPD
) == (HPRT0_PRTSPD_LOW_SPEED
<< 17))
1918 (void)USB_InitFSLSPClkSel(hhcd
->Instance
, HCFG_6_MHZ
);
1922 (void)USB_InitFSLSPClkSel(hhcd
->Instance
, HCFG_48_MHZ
);
1927 if (hhcd
->Init
.speed
== HCD_SPEED_FULL
)
1929 USBx_HOST
->HFIR
= HFIR_60_MHZ
;
1932 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1933 hhcd
->PortEnabledCallback(hhcd
);
1935 HAL_HCD_PortEnabled_Callback(hhcd
);
1936 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1941 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1942 hhcd
->PortDisabledCallback(hhcd
);
1944 HAL_HCD_PortDisabled_Callback(hhcd
);
1945 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1949 /* Check for an overcurrent */
1950 if ((hprt0
& USB_OTG_HPRT_POCCHNG
) == USB_OTG_HPRT_POCCHNG
)
1952 hprt0_dup
|= USB_OTG_HPRT_POCCHNG
;
1955 /* Clear Port Interrupts */
1956 USBx_HPRT0
= hprt0_dup
;
1967 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1968 #endif /* HAL_HCD_MODULE_ENABLED */