Updated and Validated
[betaflight.git] / lib / main / STM32F7 / Drivers / STM32F7xx_HAL_Driver / Src / stm32f7xx_hal_hcd.c
blob92a6277ed153fa75f1572f747823f8090d06f057
1 /**
2 ******************************************************************************
3 * @file stm32f7xx_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 @verbatim
14 ==============================================================================
15 ##### How to use this driver #####
16 ==============================================================================
17 [..]
18 (#)Declare a HCD_HandleTypeDef handle structure, for example:
19 HCD_HandleTypeDef hhcd;
21 (#)Fill parameters of Init structure in HCD handle
23 (#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
25 (#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
26 (##) Enable the HCD/USB Low Level interface clock using the following macros
27 (+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
28 (+++) __HAL_RCC_USB_OTG_HS_CLK_ENABLE(); (For High Speed Mode)
29 (+++) __HAL_RCC_USB_OTG_HS_ULPI_CLK_ENABLE(); (For High Speed Mode)
31 (##) Initialize the related GPIO clocks
32 (##) Configure HCD pin-out
33 (##) Configure HCD NVIC interrupt
35 (#)Associate the Upper USB Host stack to the HAL HCD Driver:
36 (##) hhcd.pData = phost;
38 (#)Enable HCD transmission and reception:
39 (##) HAL_HCD_Start();
41 @endverbatim
42 ******************************************************************************
43 * @attention
45 * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
47 * @attention
49 * <h2><center>&copy; Copyright (c) YYYY STMicroelectronics.
50 * All rights reserved.</center></h2>
52 * This software component is licensed by ST under BSD 3-Clause license,
53 * the "License"; You may not use this file except in compliance with the
54 * License. You may obtain a copy of the License at:
55 * opensource.org/licenses/BSD-3-Clause
57 ******************************************************************************
60 /* Includes ------------------------------------------------------------------*/
61 #include "stm32f7xx_hal.h"
63 /** @addtogroup STM32F7xx_HAL_Driver
64 * @{
67 #ifdef HAL_HCD_MODULE_ENABLED
69 #if defined (USB_OTG_FS) || defined (USB_OTG_HS)
71 /** @defgroup HCD HCD
72 * @brief HCD HAL module driver
73 * @{
76 /* Private typedef -----------------------------------------------------------*/
77 /* Private define ------------------------------------------------------------*/
78 /* Private macro -------------------------------------------------------------*/
79 /* Private variables ---------------------------------------------------------*/
80 /* Private function prototypes -----------------------------------------------*/
81 /** @defgroup HCD_Private_Functions HCD Private Functions
82 * @{
84 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
85 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
86 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
87 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
88 /**
89 * @}
92 /* Exported functions --------------------------------------------------------*/
93 /** @defgroup HCD_Exported_Functions HCD Exported Functions
94 * @{
97 /** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
98 * @brief Initialization and Configuration functions
100 @verbatim
101 ===============================================================================
102 ##### Initialization and de-initialization functions #####
103 ===============================================================================
104 [..] This section provides functions allowing to:
106 @endverbatim
107 * @{
111 * @brief Initialize the host driver.
112 * @param hhcd HCD handle
113 * @retval HAL status
115 HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
117 /* Check the HCD handle allocation */
118 if (hhcd == NULL)
120 return HAL_ERROR;
123 /* Check the parameters */
124 assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
126 if (hhcd->State == HAL_HCD_STATE_RESET)
128 /* Allocate lock resource and initialize it */
129 hhcd->Lock = HAL_UNLOCKED;
131 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
132 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
133 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
134 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
135 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
136 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
137 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
139 if (hhcd->MspInitCallback == NULL)
141 hhcd->MspInitCallback = HAL_HCD_MspInit;
144 /* Init the low level hardware */
145 hhcd->MspInitCallback(hhcd);
146 #else
147 /* Init the low level hardware : GPIO, CLOCK, NVIC... */
148 HAL_HCD_MspInit(hhcd);
149 #endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
152 hhcd->State = HAL_HCD_STATE_BUSY;
154 /* Disable the Interrupts */
155 __HAL_HCD_DISABLE(hhcd);
157 /* Init the Core (common init.) */
158 (void)USB_CoreInit(hhcd->Instance, hhcd->Init);
160 /* Force Host Mode*/
161 (void)USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE);
163 /* Init Host */
164 (void)USB_HostInit(hhcd->Instance, hhcd->Init);
166 hhcd->State = HAL_HCD_STATE_READY;
168 return HAL_OK;
172 * @brief Initialize a host channel.
173 * @param hhcd HCD handle
174 * @param ch_num Channel number.
175 * This parameter can be a value from 1 to 15
176 * @param epnum Endpoint number.
177 * This parameter can be a value from 1 to 15
178 * @param dev_address Current device address
179 * This parameter can be a value from 0 to 255
180 * @param speed Current device speed.
181 * This parameter can be one of these values:
182 * HCD_SPEED_HIGH: High speed mode,
183 * HCD_SPEED_FULL: Full speed mode,
184 * HCD_SPEED_LOW: Low speed mode
185 * @param ep_type Endpoint Type.
186 * This parameter can be one of these values:
187 * EP_TYPE_CTRL: Control type,
188 * EP_TYPE_ISOC: Isochronous type,
189 * EP_TYPE_BULK: Bulk type,
190 * EP_TYPE_INTR: Interrupt type
191 * @param mps Max Packet Size.
192 * This parameter can be a value from 0 to32K
193 * @retval HAL status
195 HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd,
196 uint8_t ch_num,
197 uint8_t epnum,
198 uint8_t dev_address,
199 uint8_t speed,
200 uint8_t ep_type,
201 uint16_t mps)
203 HAL_StatusTypeDef status;
205 __HAL_LOCK(hhcd);
206 hhcd->hc[ch_num].do_ping = 0U;
207 hhcd->hc[ch_num].dev_addr = dev_address;
208 hhcd->hc[ch_num].max_packet = mps;
209 hhcd->hc[ch_num].ch_num = ch_num;
210 hhcd->hc[ch_num].ep_type = ep_type;
211 hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
213 if ((epnum & 0x80U) == 0x80U)
215 hhcd->hc[ch_num].ep_is_in = 1U;
217 else
219 hhcd->hc[ch_num].ep_is_in = 0U;
222 hhcd->hc[ch_num].speed = speed;
224 status = USB_HC_Init(hhcd->Instance,
225 ch_num,
226 epnum,
227 dev_address,
228 speed,
229 ep_type,
230 mps);
231 __HAL_UNLOCK(hhcd);
233 return status;
237 * @brief Halt a host channel.
238 * @param hhcd HCD handle
239 * @param ch_num Channel number.
240 * This parameter can be a value from 1 to 15
241 * @retval HAL status
243 HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
245 HAL_StatusTypeDef status = HAL_OK;
247 __HAL_LOCK(hhcd);
248 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
249 __HAL_UNLOCK(hhcd);
251 return status;
255 * @brief DeInitialize the host driver.
256 * @param hhcd HCD handle
257 * @retval HAL status
259 HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
261 /* Check the HCD handle allocation */
262 if (hhcd == NULL)
264 return HAL_ERROR;
267 hhcd->State = HAL_HCD_STATE_BUSY;
269 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
270 if (hhcd->MspDeInitCallback == NULL)
272 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
275 /* DeInit the low level hardware */
276 hhcd->MspDeInitCallback(hhcd);
277 #else
278 /* DeInit the low level hardware: CLOCK, NVIC.*/
279 HAL_HCD_MspDeInit(hhcd);
280 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
282 __HAL_HCD_DISABLE(hhcd);
284 hhcd->State = HAL_HCD_STATE_RESET;
286 return HAL_OK;
290 * @brief Initialize the HCD MSP.
291 * @param hhcd HCD handle
292 * @retval None
294 __weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
296 /* Prevent unused argument(s) compilation warning */
297 UNUSED(hhcd);
299 /* NOTE : This function should not be modified, when the callback is needed,
300 the HAL_HCD_MspInit could be implemented in the user file
305 * @brief DeInitialize the HCD MSP.
306 * @param hhcd HCD handle
307 * @retval None
309 __weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
311 /* Prevent unused argument(s) compilation warning */
312 UNUSED(hhcd);
314 /* NOTE : This function should not be modified, when the callback is needed,
315 the HAL_HCD_MspDeInit could be implemented in the user file
320 * @}
323 /** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
324 * @brief HCD IO operation functions
326 @verbatim
327 ===============================================================================
328 ##### IO operation functions #####
329 ===============================================================================
330 [..] This subsection provides a set of functions allowing to manage the USB Host Data
331 Transfer
333 @endverbatim
334 * @{
338 * @brief Submit a new URB for processing.
339 * @param hhcd HCD handle
340 * @param ch_num Channel number.
341 * This parameter can be a value from 1 to 15
342 * @param direction Channel number.
343 * This parameter can be one of these values:
344 * 0 : Output / 1 : Input
345 * @param ep_type Endpoint Type.
346 * This parameter can be one of these values:
347 * EP_TYPE_CTRL: Control type/
348 * EP_TYPE_ISOC: Isochronous type/
349 * EP_TYPE_BULK: Bulk type/
350 * EP_TYPE_INTR: Interrupt type/
351 * @param token Endpoint Type.
352 * This parameter can be one of these values:
353 * 0: HC_PID_SETUP / 1: HC_PID_DATA1
354 * @param pbuff pointer to URB data
355 * @param length Length of URB data
356 * @param do_ping activate do ping protocol (for high speed only).
357 * This parameter can be one of these values:
358 * 0 : do ping inactive / 1 : do ping active
359 * @retval HAL status
361 HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
362 uint8_t ch_num,
363 uint8_t direction,
364 uint8_t ep_type,
365 uint8_t token,
366 uint8_t *pbuff,
367 uint16_t length,
368 uint8_t do_ping)
370 UNUSED(do_ping);
372 hhcd->hc[ch_num].ep_is_in = direction;
373 hhcd->hc[ch_num].ep_type = ep_type;
375 if (token == 0U)
377 hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
379 else
381 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
384 /* Manage Data Toggle */
385 switch (ep_type)
387 case EP_TYPE_CTRL:
388 if ((token == 1U) && (direction == 0U)) /*send data */
390 if (length == 0U)
392 /* For Status OUT stage, Length==0, Status Out PID = 1 */
393 hhcd->hc[ch_num].toggle_out = 1U;
396 /* Set the Data Toggle bit as per the Flag */
397 if (hhcd->hc[ch_num].toggle_out == 0U)
399 /* Put the PID 0 */
400 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
402 else
404 /* Put the PID 1 */
405 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
408 break;
410 case EP_TYPE_BULK:
411 if (direction == 0U)
413 /* Set the Data Toggle bit as per the Flag */
414 if (hhcd->hc[ch_num].toggle_out == 0U)
416 /* Put the PID 0 */
417 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
419 else
421 /* Put the PID 1 */
422 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
425 else
427 if (hhcd->hc[ch_num].toggle_in == 0U)
429 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
431 else
433 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
437 break;
438 case EP_TYPE_INTR:
439 if (direction == 0U)
441 /* Set the Data Toggle bit as per the Flag */
442 if (hhcd->hc[ch_num].toggle_out == 0U)
444 /* Put the PID 0 */
445 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
447 else
449 /* Put the PID 1 */
450 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
453 else
455 if (hhcd->hc[ch_num].toggle_in == 0U)
457 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
459 else
461 hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
464 break;
466 case EP_TYPE_ISOC:
467 hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
468 break;
470 default:
471 break;
474 hhcd->hc[ch_num].xfer_buff = pbuff;
475 hhcd->hc[ch_num].xfer_len = length;
476 hhcd->hc[ch_num].urb_state = URB_IDLE;
477 hhcd->hc[ch_num].xfer_count = 0U;
478 hhcd->hc[ch_num].ch_num = ch_num;
479 hhcd->hc[ch_num].state = HC_IDLE;
481 return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num], (uint8_t)hhcd->Init.dma_enable);
485 * @brief Handle HCD interrupt request.
486 * @param hhcd HCD handle
487 * @retval None
489 void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
491 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
492 uint32_t USBx_BASE = (uint32_t)USBx;
493 uint32_t i, interrupt;
495 /* Ensure that we are in device mode */
496 if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
498 /* Avoid spurious interrupt */
499 if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
501 return;
504 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
506 /* Incorrect mode, acknowledge the interrupt */
507 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
510 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
512 /* Incorrect mode, acknowledge the interrupt */
513 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
516 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
518 /* Incorrect mode, acknowledge the interrupt */
519 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
522 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
524 /* Incorrect mode, acknowledge the interrupt */
525 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
528 /* Handle Host Disconnect Interrupts */
529 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
532 /* Cleanup HPRT */
533 USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
534 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
536 /* Handle Host Port Disconnect Interrupt */
537 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
538 hhcd->DisconnectCallback(hhcd);
539 #else
540 HAL_HCD_Disconnect_Callback(hhcd);
541 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
543 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
544 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
547 /* Handle Host Port Interrupts */
548 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
550 HCD_Port_IRQHandler(hhcd);
553 /* Handle Host SOF Interrupt */
554 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
556 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
557 hhcd->SOFCallback(hhcd);
558 #else
559 HAL_HCD_SOF_Callback(hhcd);
560 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
562 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
565 /* Handle Host channel Interrupt */
566 if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
568 interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
569 for (i = 0U; i < hhcd->Init.Host_channels; i++)
571 if ((interrupt & (1UL << (i & 0xFU))) != 0U)
573 if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
575 HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
577 else
579 HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
583 __HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
586 /* Handle Rx Queue Level Interrupts */
587 if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
589 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
591 HCD_RXQLVL_IRQHandler(hhcd);
593 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
599 * @brief SOF callback.
600 * @param hhcd HCD handle
601 * @retval None
603 __weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
605 /* Prevent unused argument(s) compilation warning */
606 UNUSED(hhcd);
608 /* NOTE : This function should not be modified, when the callback is needed,
609 the HAL_HCD_SOF_Callback could be implemented in the user file
614 * @brief Connection Event callback.
615 * @param hhcd HCD handle
616 * @retval None
618 __weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
620 /* Prevent unused argument(s) compilation warning */
621 UNUSED(hhcd);
623 /* NOTE : This function should not be modified, when the callback is needed,
624 the HAL_HCD_Connect_Callback could be implemented in the user file
629 * @brief Disconnection Event callback.
630 * @param hhcd HCD handle
631 * @retval None
633 __weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
635 /* Prevent unused argument(s) compilation warning */
636 UNUSED(hhcd);
638 /* NOTE : This function should not be modified, when the callback is needed,
639 the HAL_HCD_Disconnect_Callback could be implemented in the user file
644 * @brief Port Enabled Event callback.
645 * @param hhcd HCD handle
646 * @retval None
648 __weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
650 /* Prevent unused argument(s) compilation warning */
651 UNUSED(hhcd);
653 /* NOTE : This function should not be modified, when the callback is needed,
654 the HAL_HCD_Disconnect_Callback could be implemented in the user file
659 * @brief Port Disabled Event callback.
660 * @param hhcd HCD handle
661 * @retval None
663 __weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
665 /* Prevent unused argument(s) compilation warning */
666 UNUSED(hhcd);
668 /* NOTE : This function should not be modified, when the callback is needed,
669 the HAL_HCD_Disconnect_Callback could be implemented in the user file
674 * @brief Notify URB state change callback.
675 * @param hhcd HCD handle
676 * @param chnum Channel number.
677 * This parameter can be a value from 1 to 15
678 * @param urb_state:
679 * This parameter can be one of these values:
680 * URB_IDLE/
681 * URB_DONE/
682 * URB_NOTREADY/
683 * URB_NYET/
684 * URB_ERROR/
685 * URB_STALL/
686 * @retval None
688 __weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
690 /* Prevent unused argument(s) compilation warning */
691 UNUSED(hhcd);
692 UNUSED(chnum);
693 UNUSED(urb_state);
695 /* NOTE : This function should not be modified, when the callback is needed,
696 the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
700 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
702 * @brief Register a User USB HCD Callback
703 * To be used instead of the weak predefined callback
704 * @param hhcd USB HCD handle
705 * @param CallbackID ID of the callback to be registered
706 * This parameter can be one of the following values:
707 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
708 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
709 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
710 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
711 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
712 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
713 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
714 * @param pCallback pointer to the Callback function
715 * @retval HAL status
717 HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID, pHCD_CallbackTypeDef pCallback)
719 HAL_StatusTypeDef status = HAL_OK;
721 if (pCallback == NULL)
723 /* Update the error code */
724 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
725 return HAL_ERROR;
727 /* Process locked */
728 __HAL_LOCK(hhcd);
730 if (hhcd->State == HAL_HCD_STATE_READY)
732 switch (CallbackID)
734 case HAL_HCD_SOF_CB_ID :
735 hhcd->SOFCallback = pCallback;
736 break;
738 case HAL_HCD_CONNECT_CB_ID :
739 hhcd->ConnectCallback = pCallback;
740 break;
742 case HAL_HCD_DISCONNECT_CB_ID :
743 hhcd->DisconnectCallback = pCallback;
744 break;
746 case HAL_HCD_PORT_ENABLED_CB_ID :
747 hhcd->PortEnabledCallback = pCallback;
748 break;
750 case HAL_HCD_PORT_DISABLED_CB_ID :
751 hhcd->PortDisabledCallback = pCallback;
752 break;
754 case HAL_HCD_MSPINIT_CB_ID :
755 hhcd->MspInitCallback = pCallback;
756 break;
758 case HAL_HCD_MSPDEINIT_CB_ID :
759 hhcd->MspDeInitCallback = pCallback;
760 break;
762 default :
763 /* Update the error code */
764 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
765 /* Return error status */
766 status = HAL_ERROR;
767 break;
770 else if (hhcd->State == HAL_HCD_STATE_RESET)
772 switch (CallbackID)
774 case HAL_HCD_MSPINIT_CB_ID :
775 hhcd->MspInitCallback = pCallback;
776 break;
778 case HAL_HCD_MSPDEINIT_CB_ID :
779 hhcd->MspDeInitCallback = pCallback;
780 break;
782 default :
783 /* Update the error code */
784 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
785 /* Return error status */
786 status = HAL_ERROR;
787 break;
790 else
792 /* Update the error code */
793 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
794 /* Return error status */
795 status = HAL_ERROR;
798 /* Release Lock */
799 __HAL_UNLOCK(hhcd);
800 return status;
804 * @brief Unregister an USB HCD Callback
805 * USB HCD callabck is redirected to the weak predefined callback
806 * @param hhcd USB HCD handle
807 * @param CallbackID ID of the callback to be unregistered
808 * This parameter can be one of the following values:
809 * @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
810 * @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
811 * @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
812 * @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
813 * @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
814 * @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
815 * @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
816 * @retval HAL status
818 HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
820 HAL_StatusTypeDef status = HAL_OK;
822 /* Process locked */
823 __HAL_LOCK(hhcd);
825 /* Setup Legacy weak Callbacks */
826 if (hhcd->State == HAL_HCD_STATE_READY)
828 switch (CallbackID)
830 case HAL_HCD_SOF_CB_ID :
831 hhcd->SOFCallback = HAL_HCD_SOF_Callback;
832 break;
834 case HAL_HCD_CONNECT_CB_ID :
835 hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
836 break;
838 case HAL_HCD_DISCONNECT_CB_ID :
839 hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
840 break;
842 case HAL_HCD_PORT_ENABLED_CB_ID :
843 hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
844 break;
846 case HAL_HCD_PORT_DISABLED_CB_ID :
847 hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
848 break;
850 case HAL_HCD_MSPINIT_CB_ID :
851 hhcd->MspInitCallback = HAL_HCD_MspInit;
852 break;
854 case HAL_HCD_MSPDEINIT_CB_ID :
855 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
856 break;
858 default :
859 /* Update the error code */
860 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
862 /* Return error status */
863 status = HAL_ERROR;
864 break;
867 else if (hhcd->State == HAL_HCD_STATE_RESET)
869 switch (CallbackID)
871 case HAL_HCD_MSPINIT_CB_ID :
872 hhcd->MspInitCallback = HAL_HCD_MspInit;
873 break;
875 case HAL_HCD_MSPDEINIT_CB_ID :
876 hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
877 break;
879 default :
880 /* Update the error code */
881 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
883 /* Return error status */
884 status = HAL_ERROR;
885 break;
888 else
890 /* Update the error code */
891 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
893 /* Return error status */
894 status = HAL_ERROR;
897 /* Release Lock */
898 __HAL_UNLOCK(hhcd);
899 return status;
903 * @brief Register USB HCD Host Channel Notify URB Change Callback
904 * To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
905 * @param hhcd HCD handle
906 * @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
907 * @retval HAL status
909 HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd, pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
911 HAL_StatusTypeDef status = HAL_OK;
913 if (pCallback == NULL)
915 /* Update the error code */
916 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
918 return HAL_ERROR;
921 /* Process locked */
922 __HAL_LOCK(hhcd);
924 if (hhcd->State == HAL_HCD_STATE_READY)
926 hhcd->HC_NotifyURBChangeCallback = pCallback;
928 else
930 /* Update the error code */
931 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
933 /* Return error status */
934 status = HAL_ERROR;
937 /* Release Lock */
938 __HAL_UNLOCK(hhcd);
940 return status;
944 * @brief UnRegister the USB HCD Host Channel Notify URB Change Callback
945 * USB HCD Host Channel Notify URB Change Callback is redirected to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
946 * @param hhcd HCD handle
947 * @retval HAL status
949 HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
951 HAL_StatusTypeDef status = HAL_OK;
953 /* Process locked */
954 __HAL_LOCK(hhcd);
956 if (hhcd->State == HAL_HCD_STATE_READY)
958 hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
960 else
962 /* Update the error code */
963 hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
965 /* Return error status */
966 status = HAL_ERROR;
969 /* Release Lock */
970 __HAL_UNLOCK(hhcd);
972 return status;
974 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
977 * @}
980 /** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
981 * @brief Management functions
983 @verbatim
984 ===============================================================================
985 ##### Peripheral Control functions #####
986 ===============================================================================
987 [..]
988 This subsection provides a set of functions allowing to control the HCD data
989 transfers.
991 @endverbatim
992 * @{
996 * @brief Start the host driver.
997 * @param hhcd HCD handle
998 * @retval HAL status
1000 HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
1002 __HAL_LOCK(hhcd);
1003 __HAL_HCD_ENABLE(hhcd);
1004 (void)USB_DriveVbus(hhcd->Instance, 1U);
1005 __HAL_UNLOCK(hhcd);
1006 return HAL_OK;
1010 * @brief Stop the host driver.
1011 * @param hhcd HCD handle
1012 * @retval HAL status
1015 HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
1017 __HAL_LOCK(hhcd);
1018 (void)USB_StopHost(hhcd->Instance);
1019 __HAL_UNLOCK(hhcd);
1020 return HAL_OK;
1024 * @brief Reset the host port.
1025 * @param hhcd HCD handle
1026 * @retval HAL status
1028 HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
1030 return (USB_ResetPort(hhcd->Instance));
1034 * @}
1037 /** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
1038 * @brief Peripheral State functions
1040 @verbatim
1041 ===============================================================================
1042 ##### Peripheral State functions #####
1043 ===============================================================================
1044 [..]
1045 This subsection permits to get in run-time the status of the peripheral
1046 and the data flow.
1048 @endverbatim
1049 * @{
1053 * @brief Return the HCD handle state.
1054 * @param hhcd HCD handle
1055 * @retval HAL state
1057 HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef *hhcd)
1059 return hhcd->State;
1063 * @brief Return URB state for a channel.
1064 * @param hhcd HCD handle
1065 * @param chnum Channel number.
1066 * This parameter can be a value from 1 to 15
1067 * @retval URB state.
1068 * This parameter can be one of these values:
1069 * URB_IDLE/
1070 * URB_DONE/
1071 * URB_NOTREADY/
1072 * URB_NYET/
1073 * URB_ERROR/
1074 * URB_STALL
1076 HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1078 return hhcd->hc[chnum].urb_state;
1083 * @brief Return the last host transfer size.
1084 * @param hhcd HCD handle
1085 * @param chnum Channel number.
1086 * This parameter can be a value from 1 to 15
1087 * @retval last transfer size in byte
1089 uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1091 return hhcd->hc[chnum].xfer_count;
1095 * @brief Return the Host Channel state.
1096 * @param hhcd HCD handle
1097 * @param chnum Channel number.
1098 * This parameter can be a value from 1 to 15
1099 * @retval Host channel state
1100 * This parameter can be one of these values:
1101 * HC_IDLE/
1102 * HC_XFRC/
1103 * HC_HALTED/
1104 * HC_NYET/
1105 * HC_NAK/
1106 * HC_STALL/
1107 * HC_XACTERR/
1108 * HC_BBLERR/
1109 * HC_DATATGLERR
1111 HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1113 return hhcd->hc[chnum].state;
1117 * @brief Return the current Host frame number.
1118 * @param hhcd HCD handle
1119 * @retval Current Host frame number
1121 uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
1123 return (USB_GetCurrentFrame(hhcd->Instance));
1127 * @brief Return the Host enumeration speed.
1128 * @param hhcd HCD handle
1129 * @retval Enumeration speed
1131 uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
1133 return (USB_GetHostSpeed(hhcd->Instance));
1137 * @}
1141 * @}
1144 /** @addtogroup HCD_Private_Functions
1145 * @{
1148 * @brief Handle Host Channel IN interrupt requests.
1149 * @param hhcd HCD handle
1150 * @param chnum Channel number.
1151 * This parameter can be a value from 1 to 15
1152 * @retval none
1154 static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1156 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1157 uint32_t USBx_BASE = (uint32_t)USBx;
1158 uint32_t ch_num = (uint32_t)chnum;
1160 uint32_t tmpreg;
1162 if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
1164 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
1165 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1167 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
1169 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
1171 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
1173 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1174 hhcd->hc[ch_num].state = HC_STALL;
1175 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1176 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
1177 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1179 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
1181 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1182 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1183 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1184 hhcd->hc[ch_num].state = HC_DATATGLERR;
1185 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
1187 else
1189 /* ... */
1192 if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
1194 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1195 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1196 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
1198 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
1200 if (hhcd->Init.dma_enable != 0U)
1202 hhcd->hc[ch_num].xfer_count = hhcd->hc[ch_num].xfer_len - \
1203 (USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_XFRSIZ);
1206 hhcd->hc[ch_num].state = HC_XFRC;
1207 hhcd->hc[ch_num].ErrCnt = 0U;
1208 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
1210 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
1211 (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
1213 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1214 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1215 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1217 else if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
1219 USBx_HC(ch_num)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
1220 hhcd->hc[ch_num].urb_state = URB_DONE;
1222 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1223 hhcd->HC_NotifyURBChangeCallback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1224 #else
1225 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1226 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1228 else
1230 /* ... */
1232 hhcd->hc[ch_num].toggle_in ^= 1U;
1235 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
1237 __HAL_HCD_MASK_HALT_HC_INT(ch_num);
1239 if (hhcd->hc[ch_num].state == HC_XFRC)
1241 hhcd->hc[ch_num].urb_state = URB_DONE;
1243 else if (hhcd->hc[ch_num].state == HC_STALL)
1245 hhcd->hc[ch_num].urb_state = URB_STALL;
1247 else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
1248 (hhcd->hc[ch_num].state == HC_DATATGLERR))
1250 hhcd->hc[ch_num].ErrCnt++;
1251 if (hhcd->hc[ch_num].ErrCnt > 3U)
1253 hhcd->hc[ch_num].ErrCnt = 0U;
1254 hhcd->hc[ch_num].urb_state = URB_ERROR;
1256 else
1258 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1261 /* re-activate the channel */
1262 tmpreg = USBx_HC(ch_num)->HCCHAR;
1263 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1264 tmpreg |= USB_OTG_HCCHAR_CHENA;
1265 USBx_HC(ch_num)->HCCHAR = tmpreg;
1267 else if (hhcd->hc[ch_num].state == HC_NAK)
1269 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1270 /* re-activate the channel */
1271 tmpreg = USBx_HC(ch_num)->HCCHAR;
1272 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1273 tmpreg |= USB_OTG_HCCHAR_CHENA;
1274 USBx_HC(ch_num)->HCCHAR = tmpreg;
1276 else
1278 /* ... */
1280 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
1281 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1283 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
1285 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1286 hhcd->hc[ch_num].ErrCnt++;
1287 hhcd->hc[ch_num].state = HC_XACTERR;
1288 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1289 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
1291 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
1293 if (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR)
1295 hhcd->hc[ch_num].ErrCnt = 0U;
1296 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1297 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1299 else if ((hhcd->hc[ch_num].ep_type == EP_TYPE_CTRL) ||
1300 (hhcd->hc[ch_num].ep_type == EP_TYPE_BULK))
1302 hhcd->hc[ch_num].ErrCnt = 0U;
1303 if (hhcd->Init.dma_enable == 0U)
1305 hhcd->hc[ch_num].state = HC_NAK;
1306 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1307 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1310 else
1312 /* ... */
1314 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1316 else
1318 /* ... */
1323 * @brief Handle Host Channel OUT interrupt requests.
1324 * @param hhcd HCD handle
1325 * @param chnum Channel number.
1326 * This parameter can be a value from 1 to 15
1327 * @retval none
1329 static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
1331 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1332 uint32_t USBx_BASE = (uint32_t)USBx;
1333 uint32_t ch_num = (uint32_t)chnum;
1334 uint32_t tmpreg;
1336 if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_AHBERR) == USB_OTG_HCINT_AHBERR)
1338 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_AHBERR);
1339 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1341 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_ACK) == USB_OTG_HCINT_ACK)
1343 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_ACK);
1345 if (hhcd->hc[ch_num].do_ping == 1U)
1347 hhcd->hc[ch_num].do_ping = 0U;
1348 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1349 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1350 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1353 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NYET) == USB_OTG_HCINT_NYET)
1355 hhcd->hc[ch_num].state = HC_NYET;
1356 hhcd->hc[ch_num].do_ping = 1U;
1357 hhcd->hc[ch_num].ErrCnt = 0U;
1358 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1359 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1360 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NYET);
1362 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_FRMOR) == USB_OTG_HCINT_FRMOR)
1364 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1365 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1366 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_FRMOR);
1368 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_XFRC) == USB_OTG_HCINT_XFRC)
1370 hhcd->hc[ch_num].ErrCnt = 0U;
1371 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1372 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1373 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_XFRC);
1374 hhcd->hc[ch_num].state = HC_XFRC;
1376 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_STALL) == USB_OTG_HCINT_STALL)
1378 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_STALL);
1379 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1380 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1381 hhcd->hc[ch_num].state = HC_STALL;
1383 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_NAK) == USB_OTG_HCINT_NAK)
1385 hhcd->hc[ch_num].ErrCnt = 0U;
1386 hhcd->hc[ch_num].state = HC_NAK;
1388 if (hhcd->hc[ch_num].do_ping == 0U)
1390 if (hhcd->hc[ch_num].speed == HCD_SPEED_HIGH)
1392 hhcd->hc[ch_num].do_ping = 1U;
1396 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1397 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1398 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1400 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_TXERR) == USB_OTG_HCINT_TXERR)
1402 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1403 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1404 hhcd->hc[ch_num].state = HC_XACTERR;
1405 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_TXERR);
1407 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_DTERR) == USB_OTG_HCINT_DTERR)
1409 __HAL_HCD_UNMASK_HALT_HC_INT(ch_num);
1410 (void)USB_HC_Halt(hhcd->Instance, (uint8_t)ch_num);
1411 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_NAK);
1412 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_DTERR);
1413 hhcd->hc[ch_num].state = HC_DATATGLERR;
1415 else if ((USBx_HC(ch_num)->HCINT & USB_OTG_HCINT_CHH) == USB_OTG_HCINT_CHH)
1417 __HAL_HCD_MASK_HALT_HC_INT(ch_num);
1419 if (hhcd->hc[ch_num].state == HC_XFRC)
1421 hhcd->hc[ch_num].urb_state = URB_DONE;
1422 if ((hhcd->hc[ch_num].ep_type == EP_TYPE_BULK) ||
1423 (hhcd->hc[ch_num].ep_type == EP_TYPE_INTR))
1425 hhcd->hc[ch_num].toggle_out ^= 1U;
1428 else if (hhcd->hc[ch_num].state == HC_NAK)
1430 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1432 else if (hhcd->hc[ch_num].state == HC_NYET)
1434 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1436 else if (hhcd->hc[ch_num].state == HC_STALL)
1438 hhcd->hc[ch_num].urb_state = URB_STALL;
1440 else if ((hhcd->hc[ch_num].state == HC_XACTERR) ||
1441 (hhcd->hc[ch_num].state == HC_DATATGLERR))
1443 hhcd->hc[ch_num].ErrCnt++;
1444 if (hhcd->hc[ch_num].ErrCnt > 3U)
1446 hhcd->hc[ch_num].ErrCnt = 0U;
1447 hhcd->hc[ch_num].urb_state = URB_ERROR;
1449 else
1451 hhcd->hc[ch_num].urb_state = URB_NOTREADY;
1454 /* re-activate the channel */
1455 tmpreg = USBx_HC(ch_num)->HCCHAR;
1456 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1457 tmpreg |= USB_OTG_HCCHAR_CHENA;
1458 USBx_HC(ch_num)->HCCHAR = tmpreg;
1460 else
1462 /* ... */
1465 __HAL_HCD_CLEAR_HC_INT(ch_num, USB_OTG_HCINT_CHH);
1466 HAL_HCD_HC_NotifyURBChange_Callback(hhcd, (uint8_t)ch_num, hhcd->hc[ch_num].urb_state);
1468 else
1470 /* ... */
1475 * @brief Handle Rx Queue Level interrupt requests.
1476 * @param hhcd HCD handle
1477 * @retval none
1479 static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
1481 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1482 uint32_t USBx_BASE = (uint32_t)USBx;
1483 uint32_t pktsts;
1484 uint32_t pktcnt;
1485 uint32_t temp;
1486 uint32_t tmpreg;
1487 uint32_t ch_num;
1489 temp = hhcd->Instance->GRXSTSP;
1490 ch_num = temp & USB_OTG_GRXSTSP_EPNUM;
1491 pktsts = (temp & USB_OTG_GRXSTSP_PKTSTS) >> 17;
1492 pktcnt = (temp & USB_OTG_GRXSTSP_BCNT) >> 4;
1494 switch (pktsts)
1496 case GRXSTS_PKTSTS_IN:
1497 /* Read the data into the host buffer. */
1498 if ((pktcnt > 0U) && (hhcd->hc[ch_num].xfer_buff != (void *)0))
1500 (void)USB_ReadPacket(hhcd->Instance, hhcd->hc[ch_num].xfer_buff, (uint16_t)pktcnt);
1502 /*manage multiple Xfer */
1503 hhcd->hc[ch_num].xfer_buff += pktcnt;
1504 hhcd->hc[ch_num].xfer_count += pktcnt;
1506 if ((USBx_HC(ch_num)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) > 0U)
1508 /* re-activate the channel when more packets are expected */
1509 tmpreg = USBx_HC(ch_num)->HCCHAR;
1510 tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
1511 tmpreg |= USB_OTG_HCCHAR_CHENA;
1512 USBx_HC(ch_num)->HCCHAR = tmpreg;
1513 hhcd->hc[ch_num].toggle_in ^= 1U;
1516 break;
1518 case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
1519 break;
1521 case GRXSTS_PKTSTS_IN_XFER_COMP:
1522 case GRXSTS_PKTSTS_CH_HALTED:
1523 default:
1524 break;
1529 * @brief Handle Host Port interrupt requests.
1530 * @param hhcd HCD handle
1531 * @retval None
1533 static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
1535 USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
1536 uint32_t USBx_BASE = (uint32_t)USBx;
1537 __IO uint32_t hprt0, hprt0_dup;
1539 /* Handle Host Port Interrupts */
1540 hprt0 = USBx_HPRT0;
1541 hprt0_dup = USBx_HPRT0;
1543 hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1544 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1546 /* Check whether Port Connect detected */
1547 if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
1549 if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
1551 USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
1553 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1554 hhcd->ConnectCallback(hhcd);
1555 #else
1556 HAL_HCD_Connect_Callback(hhcd);
1557 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1559 hprt0_dup |= USB_OTG_HPRT_PCDET;
1562 /* Check whether Port Enable Changed */
1563 if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
1565 hprt0_dup |= USB_OTG_HPRT_PENCHNG;
1567 if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
1569 if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
1571 if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
1573 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
1575 else
1577 (void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
1580 else
1582 if (hhcd->Init.speed == HCD_SPEED_FULL)
1584 USBx_HOST->HFIR = 60000U;
1587 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1588 hhcd->PortEnabledCallback(hhcd);
1589 hhcd->ConnectCallback(hhcd);
1590 #else
1591 HAL_HCD_PortEnabled_Callback(hhcd);
1592 HAL_HCD_Connect_Callback(hhcd);
1593 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1596 else
1598 #if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
1599 hhcd->PortDisabledCallback(hhcd);
1600 #else
1601 HAL_HCD_PortDisabled_Callback(hhcd);
1602 #endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
1604 /* Cleanup HPRT */
1605 USBx_HPRT0 &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
1606 USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
1608 USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_DISCINT);
1612 /* Check for an overcurrent */
1613 if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
1615 hprt0_dup |= USB_OTG_HPRT_POCCHNG;
1618 /* Clear Port Interrupts */
1619 USBx_HPRT0 = hprt0_dup;
1623 * @}
1627 * @}
1630 #endif /* defined (USB_OTG_FS) || defined (USB_OTG_HS) */
1631 #endif /* HAL_HCD_MODULE_ENABLED */
1634 * @}
1638 * @}
1641 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/